Android IPC 之 Service 和 Messenger
IPC機制是Android的重要組成部分,本文介紹其中的Service和Messenger。結合模擬的支付調用作為例子,翔實明了,簡直不能再良心。
IPC(進程間通信)
Interprocess Communication
Service
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.
可以看到主要有兩點是比較有特點的:不可見并且和用戶長時間交互、為其他應用程序提供服務。
Service可以脫離Activity的生命周期獨立存在。不過,有一點看上去Service要比Thread“弱”一些:Service一般是不會在新的線程中運行,如果里面進行了耗時操作的話,還是需要新開線程的。
Service主要分為應用程序內部使用的Local Service 和 進行IPC的Remote Messenger Service(含AIDL)。
作用
-
A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to Context.startService() , which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it.
應用程序告訴操作系統要在后臺處理些事情。
-
A facility for an application to expose some of its functionality to other applications. This corresponds to calls to Context.bindService() , which allows a long-standing connection to be made to the service in order to interact with it.
向其他應用程序暴露自己的一些功能,即跨進程通信。
Service的啟動
bindService(Intent service, ServiceConnection conn, int flags);
-
service,要綁定的那個Service
-
coon,這個接口有兩個方法,對應service的bind和unbind兩個節點。bindService是異步的,onServiceConnected() 作為綁定成功的回調。
-
flag,設置綁定的模式,如BIND_AUTO_CREATE
bindService() 會立即返回空值,Service onBinder() 返回Binder時回調ServiceConnection的 onServiceConnected() 方法,并將該Binder作為參數傳入。
startService(Intent service)
使用 bindService() 啟動Service,在Service失去所有綁定后將執行 onDestroy() 。
只要使用了 startService() 方法(執行onCreate的調用或者在bind之后的調用),Service不會在Activity退出后stop。
Lifecycle of Service
IBinder/Binder
遠程對象的基本接口,為進行高性能的進程內/間調用而設計的輕量級遠程調用機制的核心部分。這個接口描述了與遠程對象進行交互的抽象協議。一般使用的時候從Binder繼承,不要直接implement這個接口。
IBinder onBind();
真正的通信部分由Binder完成。API文檔中有更具體的描述
一般來說,對于一個僅僅在應用程序內部使用的Service我們可以拓展Binder,添加getService()這個方法,來達到暴露Service內部功能的目的。但是對于進程間的調用來說這樣就很難行得通了(本地沒有對應的class文件,不知道Service里面到底添加了哪些方法),所以,自上而下,來看Messenger。
Messenger
這個類的注釋文檔中寫道:
Reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Messenger to another process.
Note: the implementation underneath is just a simple wrapper around a {@link Binder} that is used to perform the communication.
引用,指向一個Handler。可以被用來發送消息(充當信使/郵差的功能)。通過在一個進程創造一個 指向Handler 的Messenger 并且把這個Messenger傳遞到另一個進程 ,來允許基于Message的進程間通信。
注意:這個類的底層是對Binder的一個簡單封裝,Binder是用來執行通信的。(這個類的結構很簡單,里面封裝了一些Binder的行為)
雖然把這些名稱翻譯成中文挺奇怪的,但是找到這些類在現實生活中的映射對于更好的理解有很大幫助。Messenger,譯作“信使”,應該是古代負責傳遞消息的使節或衙役之類的人物。在IPC機制中起到的作用就應該是傳遞信息,比如Service持有一個Messenger,通過這個Messenger發送消息。
Constructor
new Messenger(IBinder/Handler target); //IBinder-Client / Handler-Service
構造方法可以接收兩種參數,也分別對應了兩種情形:
-
IBinder
在綁定Activity的時候, bindService() 要求一個參數ServiceConnection,而綁定成功的回調結果就是一個Binder(由Service的onBind()返回)。
這個構造方法一般是用在請求綁定的一端,構造出來的 Messenger 向Service發送 Message 。
-
Handler
Handler作為Android里的跨線程機制的重要組成部分,和Message一直有著密不可分的關系。它的作用就是handle一些東西(Message),而在Service的使用中,一般是由請求端向Service端發出一個請求(信息包含在Message里)。這也就意味著,在引入Messenger的情況下,Service中要包含一個Handler用來處理發過來的請求。
這個構造方法一般用在Service端,將Handler和Messenger鏈接起來。
以上兩個構造方法完成了Messenger的傳遞。
具體過程
Messenger的主要作用過程如下:
-
Messenger在Service中以Handler以參數創建
Messenger mMessenger = new Messenger(new PaymentHandler()); //Simple Sample
-
Service被綁定后,發起綁定的一方用Binder為參數創建。
Service中返回Messenger的Binder:
@Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind"); return mMessenger.getBinder(); }
Activity(eg.)中獲取并實例化:
ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //來自Service的Messenger Messenger messenger = new Messenger(service); ...... } @Override public void onServiceDisconnected(ComponentName name) { ...... } };
-
進行通信:
Message msg = Message.obtain(); //fill your info into msg messenger.send(msg);
實現雙向的消息發送
在ServiceConnection的 onServiceConnected() 里面發送一個Message,具體過程如下:
- new 一個Handler,負責處理Service發過來的消息
- 用這個Handler創建一個Messenger
- 發送一個Message,replyTo設置為剛才創建的Messenger
一個實例:
? 模擬一個支付調用,簡單得有些簡陋。
? 一側:
@SuppressLint("HandlerLeak")
Handler responseHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//打印支付結果
Log.i(TAG, "handleMessage: Response from Service");
Log.i(TAG, "handleMessage: " + msg.obj);
}
};
msg.replyTo = new Messenger(responseHandler);
//發起支付請求
msg.obj = "I request to pay $233.33.";
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
? 另一側:
public void handleMessage(Message msg) {
//打印支付的消息內容
Log.i(TAG, "handleMessage: " + msg.obj);
try {
//模擬支付成功的回調
Message reply = Message.obtain();
reply.obj = "Payment Success!";
msg.replyTo.send(reply);
} catch (RemoteException e) {
e.printStackTrace();
}
}
打印出來的Log如下:
I/IPC:LocalService: onCreate
I/IPC:LocalService: Received start id 1: Intent { cmp=com.boileryao.ipc/.LocalService }
I/IPC:LocalService: onBind
I/IPC:LocalService: handleMessage: I request to pay $233.33.
I/ContentValues: handleMessage: Response from Service
I/ContentValues: handleMessage: Payment Success!
Happy Coding :)
via 鍋爐工
ref:
Android Developer :: Service
來自:http://www.jianshu.com/p/46bd9cb29c90