文章目录
Android跨进程通信(一):AIDL使用教程1
Android跨进程通信(二):AIDL使用教程2
Android跨进程通信(三):Messenger使用教程
Android跨进程通信(四):AIDL源码解析
Android跨进程通信(五):Messenger源码解析
前面的文章我们学会了如何使用Messenger进行跨进程通信。本篇文章我们来探究一下Messenger源码。
Messenger创建
Messenger有两种构造方法,第一个是传入Handler,它是服务端的创建方式。第二个是传入IBinder,它是客户端的创建方式。
首先来看第一种创建方式。Messenger内部有一个IMessenger成员变量,它是由Handler获取的。
//Messenger.java
public final class Messenger implements Parcelable {
private final IMessenger 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();
}
...
}
进入到getIMessenger方法里,看来IMessenger的实现类是MessengerImpl类,深入看看。
@UnsupportedAppUsage
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
MessengerImpl类继承自IMessenger.Stub类,Stub似乎挺眼熟的。没错,它就是AIDL的产物。
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
通过AndroidXRef,我们会发现一个叫IMessenger.aidl的文件。这也就说明Messenger其实是AIDL的封装。
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
接下来再看看Messenger的另一个构造方法。果然,和AIDL客户端的创建方法一样,调用了Stub.asInterface方法。
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
Messenger发送数据
Messenger调用send方法来发送数据。从上面可以得知mTarget是IMessengerImpl的对象实例。
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
...
/** * Send a Message to this Messenger's Handler. * * @param message The Message to send. Usually retrieved through * {@link Message#obtain() Message.obtain()}. * * @throws RemoteException Throws DeadObjectException if the target * Handler no longer exists. */
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
...
}
继续深入会发现,send方法最终是由Handler来完成的。在发送之前Message设置了UID。在一个设备里,每个Android App都有一个独有的UID,不同UID的程序是不能直接访问对方数据的,这保证App的安全性。
回忆一下Messenger的使用方法,A程序要发送数据给B程序,A是用B的Messenger来发送的。同理,B要给A发送数据,B是用A的Messenger来完成的。
现在A要发送数据给B,这里的UID就应该是B的UID。
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
最后
本篇文章通过创建方法和发送数据两个方面讲解了Messenger的源码。
文章评论