Messenger:使用消息的跨進程通信
Messenger:信使
官方文檔解釋:它引用了一個Handler對象,以便others能夠向它發送消息(使用mMessenger.send(Message msg)方法)。該類允許跨進程間基於Message的通信(即兩個進程間可以通過Message進行通信),在服務端使用Handler創建一個Messenger,客戶端持有這個Messenger就可以與服務端通信了。
以前我們使用Handler+Message的方式進行通信,都是在同一個進程中,從線程持有一個主線程的Handler對象,並向主線程發送消息。
而Android既然可以使用bindler機製進行跨進行通信,所以我們當然可以將Handler與bindler結合起來進行跨進程發送消息。
查看API就可以發現,Messenger就是這種方式的實現。
一般使用方法如下:
1。遠程通過
mMessenger = new Messenger(mHandler)
創建一個信使對象
2。客戶端使用bindlerService請求連接遠程
3。遠程onBind方法返回一個bindler
return mMessenger.getBinder();
4.客戶端使用遠程返回的bindler得到一個信使(即得到遠程信使)
- public void onServiceConnected(ComponentName name, IBinder service) {
- rMessenger = new Messenger(service);
- ......
- }
public void onServiceConnected(ComponentName name, IBinder service) { rMessenger = new Messenger(service); ...... }
這裏雖然是new了一個Messenger,但我們查看它的實現
- /**
- * Create a Messenger from a raw IBinder, which had previously been
- * retrieved with {@link #getBinder}.
- *
- * @param target The IBinder this Messenger should communicate with.
- */
- public Messenger(IBinder target) {
- mTarget = IMessenger.Stub.asInterface(target);
- }
/** * Create a Messenger from a raw IBinder, which had previously been * retrieved with {@link #getBinder}. * * @param target The IBinder this Messenger should communicate with. */ public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
發現它的mTarget是通過Aidl得到的,實際上就是遠程創建的那個。
5。客戶端可以使用這個遠程信使對象向遠程發送消息:rMessenger.send(msg);
這樣遠程服務端的Handler對象就能收到消息了,然後可以在其handlerMessage(Message msg)方法中進行處理。(該Handler對象就是第一步服務端創建Messenger時使用的參數mHandler).
經過這5個步驟貌似隻有客戶端向服務端發送消息,這樣的消息傳遞是單向的,那麼如何實現雙向傳遞呢?
首先需要在第5步稍加修改,在send(msg)前通過msm.replyTo = mMessenger將自己的信使設置到消息中,這樣服務端接收到消息時同時也得到了客戶端的信使對象了,然後服務端可以通過
//得到客戶端的信使對象,並向它發送消息 cMessenger = msg.replyTo; cMessenger.send(message);
即完成了從服務端向客戶端發送消息的功能,這樣客服端可以在自己的Handler對象的handlerMessage方法中接收服務端發送來的message進行處理。
雙向通信宣告完成。
下麵改寫ApiDemos工程實現Messenger通信
MessengerService.java
- package com.xwangly.apidemo.app;
- import java.util.Random;
- import android.app.Service;
- import android.content.Intent;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.Messenger;
- import android.os.RemoteException;
- import android.util.Log;
- public class MessengerService extends Service {
- private String TAG = "MessengerService";
- @Override
- public void onDestroy() {
- // TODO Auto-generated method stub
- Log.i(TAG, "onDestroy");
- cMessenger = null;
- super.onDestroy();
- }
- @Override
- public boolean onUnbind(Intent intent) {
- // TODO Auto-generated method stub
- Log.i(TAG, "onUnbind");
- return super.onUnbind(intent);
- }
- static final int MSG_REGISTER_CLIENT = 1;
- static final int MSG_UNREGISTER_CLIENT = 2;
- static final int MSG_SET_VALUE = 3;
- private Random random = new Random();
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- Log.i(TAG, "handleMessage");
- switch (msg.what) {
- case MSG_SET_VALUE:
- try {
- Message message = Message.obtain(null,
- MessengerService.MSG_SET_VALUE);
- message.arg1 = random.nextInt(100);
- //得到客戶端的信使對象,並向它發送消息
- cMessenger = msg.replyTo;
- cMessenger.send(message);
- } catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
- default:
- super.handleMessage(msg);
- }
- }
- };
- /**
- * 自己的信使對象
- */
- private Messenger mMessenger = new Messenger(mHandler);
- /**
- * 客戶的信使
- */
- private Messenger cMessenger;
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- Log.i(TAG, "onBind");
- //返回自己信使的bindler,以供客戶端通過這個bindler得到服務端的信使對象(通過new Messenger(bindler))
- return mMessenger.getBinder();
- }
- @Override
- public void onRebind(Intent intent) {
- // TODO Auto-generated method stub
- Log.i(TAG, "onRebind");
- }
- }
package com.xwangly.apidemo.app; import java.util.Random; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; public class MessengerService extends Service { private String TAG = "MessengerService"; @Override public void onDestroy() { // TODO Auto-generated method stub Log.i(TAG, "onDestroy"); cMessenger = null; super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub Log.i(TAG, "onUnbind"); return super.onUnbind(intent); } static final int MSG_REGISTER_CLIENT = 1; static final int MSG_UNREGISTER_CLIENT = 2; static final int MSG_SET_VALUE = 3; private Random random = new Random(); private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub Log.i(TAG, "handleMessage"); switch (msg.what) { case MSG_SET_VALUE: try { Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE); message.arg1 = random.nextInt(100); //得到客戶端的信使對象,並向它發送消息 cMessenger = msg.replyTo; cMessenger.send(message); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; default: super.handleMessage(msg); } } }; /** * 自己的信使對象 */ private Messenger mMessenger = new Messenger(mHandler); /** * 客戶的信使 */ private Messenger cMessenger; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.i(TAG, "onBind"); //返回自己信使的bindler,以供客戶端通過這個bindler得到服務端的信使對象(通過new Messenger(bindler)) return mMessenger.getBinder(); } @Override public void onRebind(Intent intent) { // TODO Auto-generated method stub Log.i(TAG, "onRebind"); } }
MessengerServiceActivities.java
- package com.xwangly.apidemo.app;
- import com.xwangly.apidemo.R;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.Messenger;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.View;
- import android.widget.TextView;
- public class MessengerServiceActivities {
- public static class Binding extends Activity implements
- View.OnClickListener {
- private String TAG = "Binding";
- TextView mCallbackText;
- private boolean isBound;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.messenger_service_binding);
- findViewById(R.id.bind).setOnClickListener(this);
- findViewById(R.id.unbind).setOnClickListener(this);
- mCallbackText = (TextView) findViewById(R.id.callback);
- mCallbackText.setText("Not attached.");
- }
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- Log.i(TAG, "handleMessage");
- switch (msg.what) {
- case MessengerService.MSG_SET_VALUE:
- mCallbackText.setText("Received from service: " + msg.arg1);
- break;
- default:
- super.handleMessage(msg);
- }
- }
- };
- /**
- * 自己的信使
- */
- private Messenger mMessenger;
- /**
- * 遠程服務的信使
- */
- private Messenger rMessenger;
- private ServiceConnection connection = new ServiceConnection() {
- public void onServiceConnected(ComponentName name, IBinder service) {
- // TODO Auto-generated method stub
- Log.i(TAG, "onServiceConnected");
- rMessenger = new Messenger(service);
- mMessenger = new Messenger(mHandler);
- sendMessage();
- }
- public void onServiceDisconnected(ComponentName name) {
- // TODO Auto-generated method stub
- rMessenger = null;
- }
- };
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Intent intent = new Intent(
- "com.xwangly.apidemo.app.messenger_service");
- switch (v.getId()) {
- case R.id.bind:
- if (!isBound) {
- isBound = bindService(intent, connection, BIND_AUTO_CREATE);
- //isBound = true;
- }else {
- sendMessage();
- }
- break;
- case R.id.unbind:
- if (isBound) {
- unbindService(connection);
- isBound = false;
- }
- break;
- default:
- break;
- }
- }
- /**
- * 使用服務端的信使向它發送一個消息。
- */
- private void sendMessage() {
- // TODO Auto-generated method stub
- Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE);
- message.replyTo = mMessenger;
- try {
- rMessenger.send(message);
- } catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
package com.xwangly.apidemo.app; import com.xwangly.apidemo.R; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.TextView; public class MessengerServiceActivities { public static class Binding extends Activity implements View.OnClickListener { private String TAG = "Binding"; TextView mCallbackText; private boolean isBound; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.messenger_service_binding); findViewById(R.id.bind).setOnClickListener(this); findViewById(R.id.unbind).setOnClickListener(this); mCallbackText = (TextView) findViewById(R.id.callback); mCallbackText.setText("Not attached."); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { Log.i(TAG, "handleMessage"); switch (msg.what) { case MessengerService.MSG_SET_VALUE: mCallbackText.setText("Received from service: " + msg.arg1); break; default: super.handleMessage(msg); } } }; /** * 自己的信使 */ private Messenger mMessenger; /** * 遠程服務的信使 */ private Messenger rMessenger; private ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Log.i(TAG, "onServiceConnected"); rMessenger = new Messenger(service); mMessenger = new Messenger(mHandler); sendMessage(); } public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub rMessenger = null; } }; public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent( "com.xwangly.apidemo.app.messenger_service"); switch (v.getId()) { case R.id.bind: if (!isBound) { isBound = bindService(intent, connection, BIND_AUTO_CREATE); //isBound = true; }else { sendMessage(); } break; case R.id.unbind: if (isBound) { unbindService(connection); isBound = false; } break; default: break; } } /** * 使用服務端的信使向它發送一個消息。 */ private void sendMessage() { // TODO Auto-generated method stub Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE); message.replyTo = mMessenger; try { rMessenger.send(message); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
AndroidManifest.xml相關配置如下:
- <service android:name=".app.MessengerService" >
- <intent-filter>
- <action android:name="com.xwangly.apidemo.app.messenger_service" />
- </intent-filter>
- </service>
- <activity android:name=".app.MessengerServiceActivities$Binding"
- android:label="@string/activity_messenger_service_binding"
- android:launchMode="singleTop">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
<service android:name=".app.MessengerService" > <intent-filter> <action android:name="com.xwangly.apidemo.app.messenger_service" /> </intent-filter> </service> <activity android:name=".app.MessengerServiceActivities$Binding" android:label="@string/activity_messenger_service_binding" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
至於layout就不帖了,兩個按鈕一個文本域。
最後更新:2017-04-02 06:52:22