轉自‘https://www.cnblogs.com/makaruila/p/4869912.html
平時一說進程間通訊,大家都會想到AIDL,其實messenger和AIDL作用一樣,都可以進行進程間通訊。它是基於消息的進程間通信,就像子線程和UI線程發送消息那樣,是不是很簡單,還不用去寫AIDL文件,是不是有點小爽。哈哈。
此外,還支持記錄客戶端對象的Messenger,然后可以實現一對多的通信;甚至作為一個轉接處,任意兩個進程都能通過服務端進行通信。
與 AIDL 比較:
當您需要執行 IPC 時,為您的接口使用 Messenger 要比使用 AIDL 實現更加簡單,因為 Messenger 會將所有服務調用排入隊列,而純粹的 AIDL 接口會同時向服務發送多個請求,服務隨后必須應對多線程處理。
對於大多數應用,服務不需要執行多線程處理,因此使用 Messenger 可讓服務一次處理一個調用。如果您的服務必須執行多線程處理,則應使用 AIDL 來定義接口。
接下來看下怎么用:
服務端:
1.創建一個handler對象,並實現hanlemessage方法,用於接收來自客戶端的消息,並作處理
2.創建一個messenger(送信人),封裝handler
3.用messenger的getBinder()方法獲取一個IBinder對象,通過onBind返回給客戶端
客戶端:
1.在activity中綁定服務
2.創建ServiceConnection並在其中使用 IBinder 將 Messenger實例化
3.使用Messenger向服務端發送消息
4.解綁服務
5.服務端中在 handleMessage() 方法中接收每個 Message
這樣,客戶端並沒有調用服務的“方法”。而客戶端傳遞的“消息”(Message 對象)是服務在其 Handler 中接收的。
上面實現的僅僅是單向通信,即客戶端給服務端發送消息,如果我需要服務端給客戶端發送消息又該怎樣做呢?
其實,這也是很容易實現的,下面就讓我們接着上面的步驟來實現雙向通信吧
1.在客戶端中創建一個Handler對象,用於處理服務端發過來的消息
2.創建一個客戶端自己的messenger對象,並封裝handler。
3.將客戶端的Messenger對象賦給待發送的Message對象的replyTo字段
4.在服務端的Handler處理Message時將客戶端的Messenger解析出來,並使用客戶端的Messenger對象給客戶端發送消息
這樣就實現了客戶端和服務端的雙向通信了。
注意:注:Service在聲明時必須對外開放,即android:exported="true"
是不是看的頭暈,忘掉吧,直接看下面。
看一個簡單的例子
1 package com.zixue.god.myapplication;
2
3 import android.app.Service;
4 import android.content.Intent;
5 import android.os.Handler;
6 import android.os.IBinder;
7 import android.os.Message;
8 import android.os.Messenger;
9 import android.os.RemoteException;
10 import android.widget.Toast;
11
12 //服務端service
13 public class MyService extends Service {
14 private static final int CODE = 1;
15 public MyService() {
16 }
17 @Override
18 public IBinder onBind(Intent intent) {
19 return mMessenger.getBinder();
20 }
21
22 //創建一個送信人,封裝handler
23 private Messenger mMessenger = new Messenger(new Handler() {
24 @Override
25 public void handleMessage(Message msg) {
26 Message toClient = Message.obtain();
27 switch (msg.what) {
28 case CODE:
29 //接收來自客戶端的消息,並作處理
30 int arg = msg.arg1;
31 Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show();
32 toClient.arg1 = 1111111111;
33 try {
34 //回復客戶端消息
35 msg.replyTo.send(toClient);
36 } catch (RemoteException e) {
37 e.printStackTrace();
38 }
39 }
40 super.handleMessage(msg);
41 }
42 });
43 }
//客戶端
1 package com.zixue.god.fuck;
2
3 import android.content.ComponentName;
4 import android.content.Intent;
5 import android.content.ServiceConnection;
6 import android.os.Bundle;
7 import android.os.Handler;
8 import android.os.IBinder;
9 import android.os.Message;
10 import android.os.Messenger;
11 import android.os.RemoteException;
12 import android.support.v7.app.AppCompatActivity;
13 import android.util.Log;
14 import android.view.View;
15 import android.widget.Button;
16 import android.widget.Toast;
17
18 public class MainActivity extends AppCompatActivity {
19 private boolean mBond;
20 private Messenger serverMessenger;
21 private MyConn conn;
22
23 @Override
24 protected void onCreate(Bundle savedInstanceState) {
25 super.onCreate(savedInstanceState);
26 setContentView(R.layout.activity_main);
27 //綁定服務
28 Intent intent = new Intent();
29 intent.setAction("com.zixue.god.myapplication.server");
30 conn = new MyConn();
31 bindService(intent, conn, BIND_AUTO_CREATE);
32 Button button = (Button) findViewById(R.id.bt);
33 button.setOnClickListener(new View.OnClickListener() {
34 @Override
35 public void onClick(View v) {
36 Message clientMessage = Message.obtain();
37 clientMessage.what = 1;
38 clientMessage.arg1 = 12345;
39 try {
40 clientMessage.replyTo = mMessenger;
41 serverMessenger.send(clientMessage);
42 } catch (RemoteException e) {
43 e.printStackTrace();
44 }
45 }
46 });
47 }
48
49 private class MyConn implements ServiceConnection {
50
51 @Override
52 public void onServiceConnected(ComponentName name, IBinder service) {
53 //連接成功
54 serverMessenger = new Messenger(service);
55 Log.i("Main", "服務連接成功");
56 mBond = true;
57 }
58
59 @Override
60 public void onServiceDisconnected(ComponentName name) {
61 serverMessenger = null;
62 mBond = false;
63 }
64 }
65 private Messenger mMessenger = new Messenger(new Handler(){
66 @Override
67 public void handleMessage(Message msg) {
68 Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();
69 super.handleMessage(msg);
70 }
71 });
72 @Override
73 protected void onDestroy() {
74 if (mBond) {
75 unbindService(conn);
76 }
77 super.onDestroy();
78 }
79
80 }

這樣就實現了客戶端和服務端雙向通信,是不是很簡單呢。
其實messenger底層也是AIDL。客戶端和服務端通訊,就是普通的AIDL,客戶端實例化stub之后,通過stub的send方法把消息發到服務端。服務端和客戶端通訊:服務端通過解析message的replyto,獲得客戶端的stub,然后通過send方法發送到客戶端。有精力的可以去翻一下源碼。

