一、概述
Android中谈进程间通信肯定是要提AIDL,而Messenger底层就是运用了AIDL,对AIDL做了简单封装。但是它和AIDL又有些不同,Messenger利用了Handler处理通信,所以它是线程安全的(不支持并发处理);而AIDL不是线程安全的(支持并发处理)。
二、简单入门
这里,写两个apk,一个作为client,一个座位server。
服务端代码:
创建service:
//处理消息
private static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
Message message = Message.obtain(null,0);
String data = msg.getData().getString("msg");
System.out.println( "msg----------" + data); ;
Messenger client = msg.replyTo ;
Bundle bundle = new Bundle();
bundle.putString("msg", "服务端消息已经收到");
message.setData(bundle);
try {
client.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
}
创建一个Handler的继承类
private Messenger messenger = new Messenger(new MyHandler()) ;
通过handler创建一个Messenger对象。
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
在onBind方法中返回IBinder。
<service android:name="com.lw.messengerdemo.MessengerService">
<intent-filter>
<action android:name="com.lw.messengerdemo"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
不要忘记在清单文件中配置了。
客户端:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent() ;
intent.setAction("com.lw.messengerdemo") ;
intent.setPackage("com.lw.messengerdemo");
bindService(intent, new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(getApplicationContext(), "failed", 1).show();
}
//service连接上了
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.this, "success", 1).show() ;
server = new Messenger(service);
//获取消息
Message message = Message.obtain(null, 1) ;
Bundle bundle = new Bundle();
bundle.putString("msg", "hello word ,我是客户端") ;
//为消息绑定数据
message.setData(bundle) ;
message.replyTo = mReply ;
//发送
try {
//使用信使发送消息
server.send(message) ;
} catch (Exception e) {
e.printStackTrace();
}
}
}, Context.BIND_AUTO_CREATE) ;
}
绑定服务。绑定成功后,通过服务端返回的IBinder对象封装成一个Messenger,然后通过Messenger发送消息。注意下面这几行代码:
private static class MessengerHandler extends Handler{
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
Messenger client = msg.replyTo ;
String data = msg.getData().getString("msg");
System.out.println("msg -------" + data );
break;
default:
break;
}
};
} ;
private Messenger mReply = new Messenger(new MessengerHandler()) ;
message.replyTo = mReply ;
这是用来处理服务端接收到信息后返回给客户端的。
运行结果:
06-18 11:47:19.252: I/System.out(11245): msg----------hello word ,我是客户端
06-18 11:47:19.320: I/System.out(11226): msg -------服务端消息已经收到
三、工作原理
首先看服务端的这行代码:
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
/**
* Retrieve the IBinder that this Messenger is using to communicate with
* its associated Handler.
*
* @return Returns the IBinder backing this Messenger.
*/
public IBinder getBinder() {
return mTarget.asBinder();
}
这里的mTarget是什么东西呢?
/**
* Create a new Messenger pointing to the given Handler. Any Message
* objects sent through this Messenger will appear in the Handler as if
* {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
* been called directly.
*
* @param target The Handler that will receive sent messages.
*/
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
通过我们传递过来的handler获取一个IMessenger对象。
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
再看看MessengerImpl是什么东东
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
MessengerImpl继承了IMessenger.Stub。到这里应该清楚了,如果我们在写AIDL的时候,在服务端就是继承Stub然后返回的。查看IMessenger的源码
/* //device/java/android/android/app/IActivityPendingResult.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
只有一个send(in Message msg),方法MessengerImpl继承stub实现了send方法,最后可以看到交给了Handler处理。
Handler.this.sendMessage(msg);
接着,当和服务连接成功后,如下代码:
server = new Messenger(service);
跟进去
/**
* Create a Messenger from a raw IBinder, which had previously been
* retrieved with {@link #getBinder}.
*
* @param target The IBinder this Messenger should communicate with.
*/
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
这里又是比较熟悉,通过IBinder返回一个AIDL接口对象,接着就可以通过AIDL接口对象调用方法。这里只是分析了客户端调用服务端,可以看出与AIDL类似。
接着服务端调客户端,这里我也不是太懂,看其鸿神博客的。
Android 基于Message的进程间通信 Messenger完全解析推荐看一下
,首先应该注意一个非常重要的
message.replyTo = mReply ;//这个mReply就是Messenger对象
查看源码,看replyTo 是什么东西
/**
* Optional Messenger where replies to this message can be sent. The
* semantics of exactly how this is used are up to the sender and
* receiver.
*/
public Messenger replyTo;
通过消息携带一个客户端的Messenger到服务端。查看Message源码:
public final class Message implements Parcelable {
可见它是一个可序列化对象,如果还不知道序列化的请看序列化的两种方式。Message的反序列化代码,这里只用看replyTo 参数
private void readFromParcel(Parcel source) {
what = source.readInt();
arg1 = source.readInt();
arg2 = source.readInt();
if (source.readInt() != 0) {
obj = source.readParcelable(getClass().getClassLoader());
}
when = source.readLong();
data = source.readBundle();
replyTo = Messenger.readMessengerOrNullFromParcel(source);
sendingUid = source.readInt();
}
replyTo 又是Messenger.readMessengerOrNullFromParcel(source);赋值,
/**
* Convenience function for reading either a Messenger or null pointer from
* a Parcel. You must have previously written the Messenger with
* {@link #writeMessengerOrNullToParcel}.
*
* @param in The Parcel containing the written Messenger.
*
* @return Returns the Messenger read from the Parcel, or null if null had
* been written.
*/
public static Messenger readMessengerOrNullFromParcel(Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new Messenger(b) : null;
}
那么看它是如何write的
/**
* Convenience function for writing either a Messenger or null pointer to
* a Parcel. You must use this with {@link #readMessengerOrNullFromParcel}
* for later reading it.
*
* @param messenger The Messenger to write, or null.
* @param out Where to write the Messenger.
*/
public static void writeMessengerOrNullToParcel(Messenger messenger,
Parcel out) {
out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
: null);
}
这里的messenger.mTarget.asBinder()其实就是MessengerImpl。首先分析Message是如何创建的?前面提到过,再看一遍
/**
* Create a new Messenger pointing to the given Handler. Any Message
* objects sent through this Messenger will appear in the Handler as if
* {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
* been called directly.
*
* @param target The Handler that will receive sent messages.
*/
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
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);
}
}
public IBinder getBinder() {
return mTarget.asBinder();
}
IMessenger.Stub
@Override
public android.os.IBinder asBinder()
{
return this;
}
由此可以看出messenger.mTarget.asBinder()返回的就是MessengerImpl