Service 綁定

一、Activity之間協調:
1.當在同一個進程中從一個Activity開啓另一個Activity時,它們的生命週期方法是這樣的:
A Activity 開啓了 B Activity:
A調用onPause(),B調用onCreate(),onStart(),onResume(),此時B Activity與用戶進行交互,
然後A Activity的onStop()方法調用,所以如果兩個界面共享一些數據,如存儲在數據庫
中的數據,則應該在A Activity的onPause()方法中保存數據,而不是onStop()方法。
2.橫豎屏切換
當用戶旋轉屏幕,切換屏幕狀態時,會創建新的Activity實例。


二、Service的onStartCommand()方法返回值


1.一個服務的onStartCommand()方法必須返回一個整數值,這個整數值描述了在系統因爲內存等問題殺死
該服務後,該服務在系統獲得了可用內存等資源如何繼續該服務,返回值必須爲以下其中之一:
a.START_NOT_STICKY:不要重新創建該服務,除非有意圖重新開啓該服務;
b.START_STICKY:用一個空的意圖重新創建該服務,如果有新的意圖,則用新的意圖開啓,適用於媒體播放器等邏輯;
c.START_REDELIVER_INTENT:用上一次開啓該服務的意圖重啓該服務,也就是繼續進行上次未完成的任務,
適用於文件下載,上傳等邏輯。


2.運行一個前臺服務:
前臺服務是用戶主動意識到的一種服務,因此在內存不足時,系統也不會考慮將其終止。 前臺服務必須爲狀態欄
提供通知,放在“正在進行”標題下方,這意味着除非服務停止或從前臺移除,否則不能清除通知。
要讓服務運行與前臺,需調用startForeground()方法,接收兩個參數,一個是通知的唯一標誌性ID,一個是

notification對象,如:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
注:ID值不能爲0;
要從前臺移除服務,請調用 stopForeground()。此方法接收一個布爾值,指示是否也移除狀態欄通知。 此方法不會停止
服務。 但是,如果在服務正在前臺運行時將其停止,則通知也會被移除。


3.定義可綁定的服務:
a.定義和客戶(client)交互的接口有三種方式,分別是:
(1)繼承Binder類,適用於此服務爲應用進程所私有,且client跟該服務處於同一應用進程中;
實現步驟:服務中定義一個類繼承Binder類,在服務的onBind()方法中返回一個自定義Binder實例對象,client在
onServiceConnected()方法中獲取該對象;
(2)使用Messager類提供跨進程綁定服務:
實現步驟:


服務實現一個 Handler,由其接收來自client的每個調用的回調,
Handler 用於創建 Messenger 對象(對 Handler 的引用),
Messenger 創建一個 IBinder,服務通過 onBind() 使其返回client,
client使用 IBinder 將 Messenger(引用服務的 Handler)實例化,然後使用後者將 Message 對象發送給服務,
服務在其 Handler 中(具體地講,是在 handleMessage() 方法中)接收每個 Message。
這樣,client並沒有調用服務的“方法”。而client傳遞的“消息”(Message 對象)是服務在其 Handler 中接收的。
如:

service:
public class MessengerService extends Service {
    /** Command to the service to display a message */
    static final int MSG_SAY_HELLO = 1;

    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

Activity:
public class ActivityMessenger extends Activity {
    /** Messenger for communicating with the service. */
    Messenger mService = null;

    /** Flag indicating whether we have called bind on the service. */
    boolean mBound;

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to the service
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}
(3)AIDL,有待後續拓展

4.客戶端(client)綁定服務:
client調用bindService()方法,然後服務會調用onBind()方法返回IBinder對象,但是因爲
這個綁定過程是異步的,bindService()調用後立即結束並不會返回IBinder()對象,因此需要一個ServiceConnection實例,
這個藉口提供onServiceConnected()和onServiceDisconnected()回調方法,當服務已經綁定時會調用onServiceConnected()方法,
並獲得IBinder實例對象;當服務崩潰或者被系統殺死時onServiceDisconnected()方法調用,而不是用戶調用unbindService()時調用。
如:

LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
    // Called when the connection with the service is established
    public void onServiceConnected(ComponentName className, IBinder service) {
        // Because we have bound to an explicit
        // service that is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    // Called when the connection with the service disconnects unexpectedly
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "onServiceDisconnected");
        mBound = false;
    }
};
綁定服務:

Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

5.bind service 生命週期:



6.Service完整生命週期:


發佈了34 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章