首页 > 代码库 > Android进程间通信之使用Messenger

Android进程间通信之使用Messenger

Messenger,信使,可使用它进行进程间的通信,而MessengerService的请求采用队列的方式,因此它不支持多线程通信。

 

看看官方文档对于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.

客户端和服务端可相互持有对方的Messenger来进行通信,下面我们来看看具体的实现。

在eclipse下创建两个工程,分别为客户端和服务端:

客户端的实现,创建客户端的Messenger,使用Messenger的构造方法指向一个handler实例,此handler用于处理服务端发过来的消息。

而客户端通过onServiceConnected获得服务端的Messenger,使用此Messenger给服务端发送消息,客户端的Messenger通过Message的replyTo传递给服务端。

 1 public class MainActivity extends Activity { 2  3     private static final String TAG = "--DEBUG--"; 4  5     // 用于启动service的ACTION 6     private static final String START_SERVER_ACTION = "com.young.server.START_SERVICE"; 7     private static final int WHAT_ON_TO_SERVICE = 1; 8     private static final int WHAT_ON_TO_CLIENT = 2; 9 10     private Button mBindBtn;11     private boolean isBindService = false;12 13     @Override14     protected void onCreate(Bundle savedInstanceState) {15         super.onCreate(savedInstanceState);16         setContentView(R.layout.activity_main);17         mBindBtn = (Button) findViewById(R.id.bind_service);18         mBindBtn.setOnClickListener(new OnClickListener() {19             @Override20             public void onClick(View v) {21                 bindService(new Intent(START_SERVER_ACTION), conn, Context.BIND_AUTO_CREATE);22             }23         });24     }25 26     // client端Handler,用于处理server端发来的消息27     private Handler mClientHandler = new Handler(new Callback() {28         @Override29         public boolean handleMessage(Message msg) {30             switch (msg.what) {31             case WHAT_ON_TO_CLIENT:32                 Log.v(TAG, "客户端收到服务端发来的消息!");33                 break;34 35             default:36                 break;37             }38             return false;39         }40     });41 42     // client端Messenger43     private Messenger mClientMessenger = new Messenger(mClientHandler);44 45     private ServiceConnection conn = new ServiceConnection() {46 47         @Override48         public void onServiceDisconnected(ComponentName name) {49             Log.v(TAG, "服务已断开");50 51             isBindService = false;52             mClientMessenger = null;53         }54 55         @Override56         public void onServiceConnected(ComponentName name, IBinder service) {57             Log.v(TAG, "服务已链接");58 59             isBindService = true;60             // 获得server端信使Messenger实例61             Messenger serverMessenger = new Messenger(service);62             // 向server端发送的消息63             Message toServerMessage = Message.obtain(null, WHAT_ON_TO_SERVICE);64             // 通过replyTo把client端的信使传递给service65             toServerMessage.replyTo = mClientMessenger;66             try {67                 serverMessenger.send(toServerMessage);68             } catch (RemoteException e) {69                 e.printStackTrace();70             }71         }72     };73 74     protected void onStop() {75         if (isBindService)76             unbindService(conn);77         super.onStop();78     };79 }

 

服务端Service的实现,服务端接收到客户端的消息以后,通过Message的replyTo取出客户端的Messenger,使用此Messenger给客户端发送消息,这就实现了进程之间的双向通信。

服务端通过Messenger的getBinder方法将IBinder对象返给客户端,用于共享服务端的Messenger。

 1 public class RemoteService extends Service { 2     private static final String TAG = "--DEBUG--"; 3  4     private static final int WHAT_ON_TO_SERVICE = 1; 5     private static final int WHAT_ON_TO_CLIENT = 2; 6  7     // server端handler,用来处理client发来的消息 8     private Handler mServerHandler = new Handler(new Callback() { 9         @Override10         public boolean handleMessage(Message msg) {11             switch (msg.what) {12             case WHAT_ON_TO_SERVICE:13                 Log.v(TAG, "收到客户端发来的消息");14                 // server端获得client端的信使Messenger15                 Messenger clientMessenger = msg.replyTo;16                 Message toClientMsg = Message.obtain(null, WHAT_ON_TO_CLIENT);17                 try {18                     // 使用客户端Messenger向客户端发送消息19                     clientMessenger.send(toClientMsg);20                 } catch (RemoteException e) {21                     e.printStackTrace();22                 }23                 break;24 25             default:26                 break;27             }28             return false;29         }30     });31 32     // server端信使Messenger33     private Messenger mServerMessenger = new Messenger(mServerHandler);34 35     @Override36     public IBinder onBind(Intent intent) {37         return mServerMessenger.getBinder();38     }

再来看看服务端service的声明,因为要在其他进程中启动service,所以设置android:exported为true,此外还为service加入启动了权限。

 1 <permission android:protectionLevel="normal" android:name="young.permission.START_SERVICE"></permission> 2      3 <service 4     android:name="com.young.server.RemoteService" 5     android:permission="young.permission.START_SERVICE" 6     android:exported="true" > 7     <intent-filter> 8         <action android:name="com.young.server.START_SERVICE" /> 9     </intent-filter>10 </service>

最后要在客户端添加相应的启动Service权限。

<uses-permission android:name="young.permission.START_SERVICE" />

 

程序运行后的结果,可以看到客户端和服务端都收到了对方发来的消息。

11-12 12:58:37.197: V/--DEBUG--(21322): 服务已链接
11-12 12:58:37.197: V/--DEBUG--(21268): 收到客户端发来的消息
11-12 12:58:37.197: V/--DEBUG--(21322): 客户端收到服务端发来的消息!

 

Android进程间通信之使用Messenger