概述
Messenger与Handler类似,可以用它来发送和处理消息,其低层的实现是对Binder的一个简单封装。使用起来也比较方便,在一个线程中通过指定一个Handler来创建Messenger,并把它传递给另一个进程,这样两个进程之间就可以通过消息(Message)来传递信息了。
使用方法
主要思路:
客户端通过bindService来绑定服务端,并从服务端获得IBinder接口用于创建服务端的Messenger实例,这样客户端就可以通过这个服务端的Messenger实例发送Message给服务器。其中,客户端的Messenger实例可以通过Message的replyTo参数传递给服务端。经过上述过程,客户端和服务端就各自获得了对方的Messenger实例,进而实现两个进程间的通信。
服务端代码:
public class MessengerService extends Service {
private final static String TAG = "LogTAG.MessengerService";
public final static int MSG_FROM_CLIENT = 0;
public final static int MSG_FROM_SERVICE = 1;
private Messenger mMessenger = new Messenger(new MessengerHandler());
public MessengerService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
@Override
public void onDestroy() {
super.onDestroy();
}
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_FROM_CLIENT:
Log.i(TAG,"Message from client = " + msg.getData().getString("msg"));
Message serviceMsg = Message.obtain();
serviceMsg.what = MSG_FROM_SERVICE;
Bundle data = new Bundle();
data.putString("msg","Hi, peter ! I am lemon .");
serviceMsg.setData(data);
if(msg.replyTo != null){
try {
msg.replyTo.send(serviceMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
default:
//do nothing
}
}
}
}
客户端代码:
public class ClientActivity extends AppCompatActivity implements View.OnClickListener{
private final static String TAG = "LogTAG.ClientActivity";
public final static int MSG_FROM_CLIENT = 0;
public final static int MSG_FROM_SERVICE = 1;
private Messenger mClientMessenger;
private Messenger mServiceMessenger;
private Button mBindService;
private Button mSend;
private ServiceConnection mSC = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG,"onServiceConnected name = " + name.toString());
mServiceMessenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG,"onServiceDisconnected name = " + name.toString());
mServiceMessenger = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
mClientMessenger = new Messenger(new MessengerHandler());
mBindService = findViewById(R.id.btn_bind_service);
mBindService.setOnClickListener(this);
mSend = findViewById(R.id.btn_client_send);
mSend.setOnClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mSC != null) {
unbindService(mSC);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind_service:
Intent intent = new Intent(this,MessengerService.class);
bindService(intent,mSC, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_client_send:
Message clientMsg = Message.obtain();
clientMsg.what = MSG_FROM_CLIENT;
clientMsg.replyTo = mClientMessenger;
Bundle data = new Bundle();
data.putString("msg","Hi, I am peter ! What's your name ?");
clientMsg.setData(data);
if(mServiceMessenger != null) {
try {
mServiceMessenger.send(clientMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
default:
//do nothing
}
}
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_FROM_SERVICE:
Log.i(TAG,"Message from service = " + msg.getData().getString("msg"));
break;
default:
//do nothing
}
}
}
}
Log如下:
07-24 22:29:21.316 20413-20413/com.android.peter.messengerdemo I/LogTAG.ClientActivity: onServiceConnected name = ComponentInfo{com.android.peter.messengerdemo/com.android.peter.messengerdemo.MessengerService}
07-24 22:29:23.459 20584-20584/com.android.peter.messengerdemo:remote I/LogTAG.MessengerService: Message from client = Hi, I am peter ! What's your name ?
07-24 22:29:23.470 20413-20413/com.android.peter.messengerdemo I/LogTAG.ClientActivity: Message from service = Hi, peter ! I am lemon .
源码解析
Messenger的源码比较短,一起来看一下是如何实现的。
- 初始化
Messenger类提供了如下两种初始化方式,其本质上都是为了初始化Messenger类中IMessenger接口类对象mTarget,通过这个接口类对象就能调用其内部提供的方法。
frameworks/base/core/java/android/os/Messenger.java
// 方法一
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
// 方法二
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
- 消息发送
在初始化方法一中,通过Handler的getIMessenger方法会创建并返回一个派生于IMessenger接口的MessengerImpl类的对象。通过这个对象就能访问Handler的sendMessage方法把消息传递给Handler处理。
frameworks/base/core/java/android/os/Handler.java
// 获得IMessenger接口的实例
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
// 派生IMessenger接口类并实现其方法
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
在初始化方法二中,需要传递IMessenger接口类对应的IBinder对象,Messenger类中提供了getBinder来获取这个对象。
public IBinder getBinder() {
return mTarget.asBinder();
}
另外,我搜索了所有源码,只有在Handler类中找到了MessengerImpl类派生于IMessenger.Stub的逻辑,但是被类被final修饰了不可以被派生,那么有可能自己实现一个类派生IMessenger.Stub来重新实现send方法么?进一步的去看了IMessenger.aidl源码,发现了hide、oneway等字样,看来这条路也行不通。
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
小结
通过上面对源码的分析可以看出,Messenger的初始化过程就是建立Messenger对象、IMessenger接口类对象和Handler对象三者之间的关联,Hanlder类可以看做是最终服务的提供者。
Demo