深入理解AsyncChannel、Messenger

本文详细探讨了Android中的AsyncChannel和Messenger的原理,包括它们如何实现单进程和跨进程通信,以及在Android系统组件如ConnectivityService与NetworkAgent中的应用。AsyncChannel作为Handler和Messenger的扩展,提供了半连接和全连接两种通信方式,而Messenger则通过Binder机制实现跨进程消息传递。文章还通过源码分析解释了Messenger的内部工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章主要介绍Android AsyncChannel、Messenger原理及其应用实例
注:文章参考的是Andrdoid 8.0源码

AsyncChannel 简介
  
  AsyncChannel的源码位于 frameworks/base/core/java/com/android/internal/util/AsyncChannel.java,是对Handler和Messenger的一个扩展,用于单个进程内(包含不同线程间)或两个进程间的通信。在不同的进程间,AsyncChanne实质上使用的是IMessenger通过Binder的形式对消息进行发送和接收,当然,这种方式对单个进程内非remove service同样适用。
  在Android系统中,有很多地方都使用了这个工具类,如ConnectivityService与NetworkAgent的通信,WifiServiceImpl与WifiStateMachine之间的通信等。由于AsyncChannel属于系统内部源码,三方应用无法直接进行使用,但我们可以学习思想,甚至可以自己简单实现并作用于我们的APP代码中。

AsyncChannel的主要特点:

  • 可以在单进程或不同进程间实现消息传递
  • 支持建立单向通信或双向通信
  • 是对Handler,Messenger的一种包装,并没有实现额外的通信方式

Messenger

  由于AsyncChannel实际上使用的是Handler和Messenger的机制,考虑到很多开发者对Messenger还不够了解,所以我们这里有必要先对这个工具做一个详细的解析。
  Messenger的源码位于 frameworks/base/core/java/android/os/Messenger.java,是对Handler的一个再包装,并结合了Binder机制,使得跨进程间Message的传递和处理成为了可能。

成员变量及构造函数:

  主要成员变量是IMessenger类型的mTarget,该变量可以通过Handler或者IBinder进行初始化,分别应用于同进程消息或者跨Service(remote或者非remote)消息发送:

// IMessenger类型,mTarget代表message的目的端
private final IMessenger mTarget;

// 初始化mTarget并指向Handler中的IMessenger
public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}

// 初始化mTarget并指向IBinder的实际类型
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

Messenger的发送函数:

  无论是否跨进程,Messenger实际上都是利用IMessenger进行消息发送的:

public void send(Message message) throws RemoteException {
    mTarget.send(message);
}

IMessenger:

  源码位于 frameworks/base/core/java/android/os/IMessenger.aidl,其目的是通过AIDL使用Binder机制对Message进行发送:

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

通过Handler对mTarget进行初始化:

  Handler中MessengerImpl对IMessenger进行了实现,在 send 函数中最终还是使用Handler自身对Message进行了处理,因此,这里的IMessenger仅仅是一个中介:

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) {
        // 由于存在Binder调用,初始化sendingUid为发送端uid
        msg.sendingUid = Binder.getCallingUid();
        // 通过Handler自身发送消息并进行处理
        Handler.this.sendMessage(msg);
    }
}

通过Service IBinder对mTarget进行初始化:
  
  这里以Android源码中针对Messenger的测试case作为例子对其过程进行解析,源码路径:
- frameworks/base/core/tests/coretests/src/android/os/MessengerService.java
- frameworks/base/core/tests/coretests/src/android/os/MessengerTest.java

Service端实现(MessengerService.java):

public class MessengerService extends Service {
   
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 在这里处理client端发送的消息
        }
    };

    // 定义一个Messenger,Messenger中的mTarget即为mHandler中的mMessenger
    private final Messenger mMessenger = new Messenger(mHandler);

    @Override
    public IBinder onBind(Intent intent) {
        // 返回mHandler中的mMessenger
        return mMessenger.getBinder();
    }
}

Client端实现(MessengerTest.java):

  通过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值