Android跨进程通信(五):Messenger源码解析

文章目录

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的源码。

参考文章

《Android中的uid》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值