一个AIDL简单的实例

作者: kevinsong0810 | 来源:发表于2018-11-11 12:45 被阅读7次
一. AIDL是快速实现binder,实现跨进程通信的工具

AIDL:Android Interface Definition Language,安卓接口描述语言

二. 实现一个简单的AIDL通信示例

前提:IPersonManager类用于客户端(由PersonManager.aidl自动生成),PersonManagerService类用于服务端

  1. 实现一个PersonManager.aidl,定义所需的接口和方法,例如:
import com.kevin.test.testAIDL.Person;
interface IPersonManager {
          String getName();
          int getAge();
          void print();
          void changeName(in Person person);
}

注意:Person类是自定义类,需实现Parcel接口,并实现相关方法

  1. 开发工具,如Android Studio,会根据AIDL文件,自动帮我们实现IPersonManager.java类,继承自android.os.IInterface。其中有一个内部静态类Stub,Stub类有2个重要方法asInterface,onTransact和一个内部静态类Proxy。以下是它们的关系:

    • asInterface方法:将服务端的Binder对象转换为客户端所需的AIDL接口类型的对象。区分进程,如果二者在同一进程,返回服务端的Stub对象本身,如果跨进程,返回Stub.Proxy对象
    • onTransact方法运行在服务端的binder线程池中
    • 跨进程通信,会在Stub.Proxy中走transact过程,例如getName的核心实现是
      mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
  2. 实现一个PersonManagerService.java类,作为服务端,其中重要的是定义一个类成员变量Binder mBinder = new IPersonManager.Stub() {......},这是一个Stub类对象,其中真正实现各个调用的方法,如getName()等

  3. 客户端在使用时调用bindService接口,此时会传入一个ServiceConncetion对象,如bind成功,ServiceConncetion#onServiceConnected方法会被回调,在其中可将服务端返回的IBinder对象利用asInterface方法进行转换,如:
    IPersonManager personManager = IPersonManager.Stub.asInterface(iBinder);

三. 设置死亡代理

当服务端Service运行时出现异常,例如抛出DeadObjectException异常,进程终止等,这时已连接的客户端,如何接到通知,并进行一系列操作,如重新bindService等。这里用到Binder的死亡代理,分为2步:

  1. 客户端新建一个IBinder.DeathRecipient成员变量
    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            if (null == mPersonManager)
                return;
            // unlink binder death recipient
            mPersonManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
            // reconnect
            bindService(...);
        }
    };
  1. 注册代理
    public ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mPersonManager = IPersonManager.Stub.asInterface(iBinder);

            try {
                // link binder death recipient
                mPersonManager.asBinder().linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
                // ...
            }
        }

当服务端进程中止时,IBinder.DeathRecipient#binderDied方法会被回调

四. bindService的实现过程:
  1. Activity(基类是Context,其中方法真正实现在ContextImpl中)中调用bindService
  2. ContextImpl#bindServiceCommon中,利用binder通信,调用ActivityManager#bindService方法
  3. System_server进程中ActivityManagerService#bindService -> ActiveServices#bindServiceLocked方法,其中会检查权限,启动目标Service等,然后回调客户端ServiceConnection#onServiceConncetd方法(one-way通信),过程结束

相关文章

网友评论

    本文标题:一个AIDL简单的实例

    本文链接:https://www.haomeiwen.com/subject/qajxfqtx.html