歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android Messenger 跨進程通信

Android Messenger 跨進程通信

日期:2017/3/1 10:34:21   编辑:Linux編程

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);     

......

}

這裡雖然是new了一個Messenger,但我們查看它的實現

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進行處理。

雙向通信宣告完成。


以下代碼來自ApiDemo

Service code:

[java]
  1. public class MessengerService extends Service {
  2. /** For showing and hiding our notification. */
  3. NotificationManager mNM;
  4. /** Keeps track of all current registered clients. */
  5. ArrayList<Messenger> mClients = new ArrayList<Messenger>();
  6. /** Holds last value set by a client. */
  7. int mValue = 0;
  8. /**
  9. * Command to the service to register a client, receiving callbacks
  10. * from the service. The Message's replyTo field must be a Messenger of
  11. * the client where callbacks should be sent.
  12. */
  13. static final int MSG_REGISTER_CLIENT = 1;
  14. /**
  15. * Command to the service to unregister a client, ot stop receiving callbacks
  16. * from the service. The Message's replyTo field must be a Messenger of
  17. * the client as previously given with MSG_REGISTER_CLIENT.
  18. */
  19. static final int MSG_UNREGISTER_CLIENT = 2;
  20. /**
  21. * Command to service to set a new value. This can be sent to the
  22. * service to supply a new value, and will be sent by the service to
  23. * any registered clients with the new value.
  24. */
  25. static final int MSG_SET_VALUE = 3;
  26. /**
  27. * Handler of incoming messages from clients.
  28. */
  29. class IncomingHandler extends Handler {
  30. @Override
  31. public void handleMessage(Message msg) {
  32. switch (msg.what) {
  33. case MSG_REGISTER_CLIENT:
  34. mClients.add(msg.replyTo);
  35. break;
  36. case MSG_UNREGISTER_CLIENT:
  37. mClients.remove(msg.replyTo);
  38. break;
  39. case MSG_SET_VALUE:
  40. mValue = msg.arg1;
  41. for (int i = mClients.size() - 1; i >= 0; i --) {
  42. try {
  43. mClients.get(i).send(Message.obtain(null,
  44. MSG_SET_VALUE, mValue, 0));
  45. } catch (RemoteException e) {
  46. // The client is dead. Remove it from the list;
  47. // we are going through the list from back to front
  48. // so this is safe to do inside the loop.
  49. mClients.remove(i);
  50. }
  51. }
  52. break;
  53. default:
  54. super.handleMessage(msg);
  55. }
  56. }
  57. }
  58. /**
  59. * Target we publish for clients to send messages to IncomingHandler.
  60. */
  61. final Messenger mMessenger = new Messenger(new IncomingHandler());
  62. @Override
  63. public void onCreate() {
  64. mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
  65. // Display a notification about us starting.
  66. showNotification();
  67. }
  68. @Override
  69. public void onDestroy() {
  70. // Cancel the persistent notification.
  71. mNM.cancel(R.string.remote_service_started);
  72. // Tell the user we stopped.
  73. Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
  74. }
  75. /**
  76. * When binding to the service, we return an interface to our messenger
  77. * for sending messages to the service.
  78. */
  79. @Override
  80. public IBinder onBind(Intent intent) {
  81. return mMessenger.getBinder();
  82. }
  83. /**
  84. * Show a notification while this service is running.
  85. */
  86. private void showNotification() {
  87. // In this sample, we'll use the same text for the ticker and the expanded notification
  88. CharSequence text = getText(R.string.remote_service_started);
  89. // Set the icon, scrolling text and timestamp
  90. Notification notification = new Notification(R.drawable.stat_sample, text,
  91. System.currentTimeMillis());
  92. // The PendingIntent to launch our activity if the user selects this notification
  93. PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
  94. new Intent(this, Controller.class), 0);
  95. // Set the info for the views that show in the notification panel.
  96. notification.setLatestEventInfo(this, getText(R.string.remote_service_label),
  97. text, contentIntent);
  98. // Send the notification.
  99. // We use a string id because it is a unique number. We use it later to cancel.
  100. mNM.notify(R.string.remote_service_started, notification);
  101. }
  102. }
Copyright © Linux教程網 All Rights Reserved