通常,我们用aidl实现android上层进程间的通信, 除此之外,我们也可以用messenger来实现。 当然,
这俩者背后都是binder机制的实现,这里主要讲messenger的方式。
参考android4.0 bluetooth的源码,BluetoothHDPActivity.java, BluetoothHDPService.java这两个文件,其中,
Activity作为 client.
先看Server端,BuetoothHDPService.java
private class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// Register UI client to this service so the client can receive messages.
case MSG_REG_CLIENT:
Log.d(TAG, "Activity client registered");
mClient = msg.replyTo;
break;
// Unregister UI client from this service.
case MSG_UNREG_CLIENT:
mClient = null;
break;
// Register health application.
case MSG_REG_HEALTH_APP:
registerApp(msg.arg1);
break;
// Unregister health application.
case MSG_UNREG_HEALTH_APP:
unregisterApp();
break;
// Connect channel.
case MSG_CONNECT_CHANNEL:
mDevice = (BluetoothDevice) msg.obj;
connectChannel();
break;
// Disconnect channel.
case MSG_DISCONNECT_CHANNEL:
mDevice = (BluetoothDevice) msg.obj;
disconnectChannel();
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
};
在server端, 定义了一个messenger,参数是一个Handler, 可以想到的是,这个Handler 一定是给 Client 去调用的,
并通过 onBind 方法, 返回了这个messenger的 binder对象(aidl的方式中,返回的是Server 的一个代理 finalIRemoteService.Stub mBinder=newIRemoteService.Stub() )
好了,我们看看,client 端, 通过bindService, 做了什么操作。
BluetoothHDPActivity.java,
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mHealthServiceBound = true;
Message msg = Message.obtain(null, BluetoothHDPService.MSG_REG_CLIENT);
msg.replyTo = mMessenger;
mHealthService = new Messenger(service);\
try {
mHealthService.send(msg);
} catch (RemoteException e) {
Log.w(TAG, "Unable to register client to service.");
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
mHealthService = null;
mHealthServiceBound = false;
}
};
这里, 我们看到,onServiceConnected 里,获取了server端的 messenger, 并通过send 的方式, 实现
了向 server 里的 handler 发送消息的功能,至此, 我们了解了, 通过messenger, 实现跨进程发送消息的功能.
在这段代码里, 他send 一个消息给server端, 看代码, msg.replyTo = mMessenger, 这里, 他有带了一个
client 端的mMessager 给server端,我们看mMessenger:
// Handles events sent by {@link HealthHDPService}.
private Handler mIncomingHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// Application registration complete.
case BluetoothHDPService.STATUS_HEALTH_APP_REG:
mStatusMessage.setText(
String.format(mRes.getString(R.string.status_reg),
msg.arg1));
break; //此处省略部分代码
case BluetoothHDPService.STATUS_DESTROY_CHANNEL:
mStatusMessage.setText(
String.format(mRes.getString(R.string.status_destroy_channel),
msg.arg1));
mConnectIndicator.setText(R.string.disconnected);
break;
default:
super.handleMessage(msg);
}
}
};
private final Messenger mMessenger = new Messenger(mIncomingHandler);
这部分代码跟之前的代码一样, 功能也是一样的, 几可以将messenger对象带个server, 实现server向 client 发送消息。
通过上述介绍,利用messeger, 可以实现在 client和server之间相互发送消息, 个人觉得, 比aidl 的方式要好用些,
也容易理解些, aidl 的方式, 本文就不做过多的讲述。
总结:
1. 使用Messenger方式比使用AIDL的方式,实现起来要简单很多
2. 使用Messenger时,所有从Activity传过来的消息都会排在一个队列里,不会同时请求Service,所以是线程安全的。如果你的程序就是要多线程去访问Service,就可以用AIDL,不然最好使用Messenger的方式。