概述
Messenger 翻译为信使,顾名思义,就是可以在不同进程之间传递Message对象。它是一种基于AIDL的轻量型的IPC方案。
定义
源码里面Messenger的定义比较简单,只是实现了Parcelable接口,之外提供了构造和发送方法。同时它也是一个final类。
代码语言:javascript复制public final class Messenger implements Parcelable {
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
...
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
从他的两个构造方法,其实可以看出有着AIDL的痕迹,比如“getIMessenger”、“IMessenger.Stub.”。所以可以看作是对AIDL的简单封装。
接着跟踪 getIMessenger(),发现
代码语言:javascript复制 final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
可以看到getIMessenger方法返回的是MessengerImpl对象,而MessengerImpl是Handle的一个内部类,并且继承了IMessenger.Stub,实现了其send()方法。看到这,想必大家看出来了IMessenger.Stub这种形式就和AIDL使用方式很像,所以印证了之前的说法。Messenger的底层的确是AIDL。
MessengerImpl 类的实现可以看到,客户端msg通过binder方式传递过来,而当前进程的Handler将其加入自己的messagequeue并处理它。 PS: IMessenger类位于:
代码语言:javascript复制frameworks/base/core/Java/android/os/IMessenger.aidl
使用
服务端
代码语言:javascript复制public class ServerService extends Service {
private static final String TAG = "ServerService";
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
private final Messenger mMessenger = new Messenger(new MessengerHandler());
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
Log.i(TAG,"Message data = " msg.getData().getString("data"));
break;
default:
super.handleMessage(msg);
}
}
}
}
分3步:
- 实现静态内部类继承Handler
- 新建Messenger对象
- Onbind方法返回Messenger.getBinder()
为了实现进程间通信,于是在Manifast文件注册可以指定进程号, 这样就实现了和主进程不同进程。
代码语言:javascript复制 <service
android:name=".ServerService"
android:process=":remote"></service>
就这么简单。剩下的就是等着客户端来撩骚你了。
客户端
代码语言:javascript复制public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Messenger mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, ServerService.class);
bindService(intent,mConnect, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnect = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG,"onServiceConnected ");
mService = new Messenger(service);
Message mag = Message.obtain(null, 1);
Bundle data = new Bundle();
data.putString("data"," Hello , i come from client ");
mag.setData(data);
try {
mService.send(mag);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
@Override
protected void onDestroy() {
unbindService(mConnect);
super.onDestroy();
}
}
为了对称也分3步:
- 绑定对应的service – bindService
- 初始化ServiceConnection 对象
- 拿到服务器返回的IBinder对象,通过这个初始化Messenger对象,就可以发送消息
运行结果
代码语言:javascript复制xxxx.messagertest I/MainActivity: onServiceConnected
xxxx.messagertest:remote I/ServerService: Message.what = Hello , i come from client
可以看到service收到了Activity的消息,并且service进程是xxxx.messagertest:remote,而Activity在xxxx.messagertest。说明进程间通讯成功实现!!
扩展双向通信
服务端
代码语言:javascript复制 @Override
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
Log.i(TAG,"Message.what = " msg.getData().getString("data"));
Messenger client = msg.replyTo; //主要添加这句
Message reply = Message.obtain(null ,2);
Bundle data = new Bundle();
data.putString("reply","ok , i get it!");
reply.setData(data);
try {
client.send(reply);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
客户端
代码语言:javascript复制 @Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG,"onServiceConnected ");
mService = new Messenger(service);
Message mag = Message.obtain(null,1);
Bundle data = new Bundle();
data.putString("data","Hello , i come from client");
mag.replyTo = mClientMessenger; //这句需要添加
mag.setData(data);
try {
mService.send(mag);
} catch (RemoteException e) {
e.printStackTrace();
}
}
...
private Messenger mClientMessenger = new Messenger(new ClientHander());
private static class ClientHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 2:
Log.i(TAG,"Message.what = " msg.getData().getString("reply"));
break;
default:
super.handleMessage(msg);
}
}
}
总结一下,其实就是客户端需要指定Messenger的replyto,其他类似于之前的服务端实现。而服务器端只需要拿到replyTo对象就可以向客户端发送消息。
运行结果
代码语言:javascript复制I/ServerService: Message.what = Hello , i come from client
I/MainActivity: Message.what = ok , i get it!