一、 Android进程间通讯之Messenger 的引入
(1)引言:
平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯。它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽。哈哈。此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。
(2) Messenger 与 AIDL 比较:
当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
二、 Messenger 的具体使用:
1. 客户端发送消息给服务端(单向通信)
服务端:
(1)创建一个handler对象,并实现hanlemessage方法,用于接收来自客户端的消息,并作处理 .
(2)创建一个messenger(送信人),封装handler .
(3)messenger创建一个IBinder对象,通过onBind返回给客户端
客户端:
(1)在activity中绑定服务
(2)创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化
(3)使用Messenger向服务端发送消息
(4)解绑服务
(5)服务端中在 handleMessage() 方法中接收每个 Message
这样,客户端并没有调用服务的"方法"。而客户端传递的"消息"(Message 对象)是服务在其 Handler 中接收的。
上面实现的仅仅是单向通信,即客户端给服务端发送消息。
2. 客户端与服务端双向通信
如果我需要服务端给客户端发送消息又该怎样做呢?
其实,这也是很容易实现的,下面就让我们接着上面的步骤来实现双向通信吧:
(1)在客户端中创建一个Handler对象,用于处理服务端发过来的消息。
(2)创建一个客户端自己的messenger对象,并封装handler。
(3)将客户端的Messenger对象赋给待发送的Message对象的replyTo字段。
(4)在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息。
这样就实现了客户端和服务端的双向通信了。
注意:
注:Service在声明时必须对外开放,即android:exported="true"
是不是看的头晕,忘掉吧,直接看下面。
三、代码示例:
(1)服务端service:
1 public class MyService extends Service { 2 private static final int CODE = 1; 3 public MyService() { 4 } 5 @Override 6 public IBinder onBind(Intent intent) { 7 return mMessenger.getBinder(); 8 } 9 10 //创建一个送信人,封装handler 11 private Messenger mMessenger = new Messenger(new Handler() { 12 @Override 13 public void handleMessage(Message msg) { 14 Message toClient = Message.obtain(); 15 switch (msg.what) { 16 case CODE: 17 //接收来自客户端的消息,并作处理 18 int arg = msg.arg1; 19 Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show(); 20 toClient.arg1 = 1111111111; 21 try { 22 //回复客户端消息 23 msg.replyTo.send(toClient); 24 } catch (RemoteException e) { 25 e.printStackTrace(); 26 } 27 } 28 super.handleMessage(msg); 29 } 30 }); 31 }
(2)客户端
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 }