android中AIDL机制分析

AIDL的使用

通过AIDL接口实现下面的功能:
在一个页面中登录,activity只负责接口调用和参数传递,具体实现由service完成,service执行登录后把结果返回给activity。
首先需要新建一个.aidl文件,在里面申明AIDL接口方法:

interface IEcmServiceBinder {
     /**
      * 登录TF卡
      * 初始化加密卡并且获取当前卡的状态
      * @param passwd  登录卡的密码
      * @return  返回登录结果: xxxxxxxxxx
      */
     int[] loginTFCard(String passwd);
}

写好后build一下工程,然后在service端实现这个接口:

public IEcmServiceBinder.Stub mEcmServiceBinder = new IEcmServiceBinder.Stub() {

        /**
         * 登录TF卡
         * 初始化加密卡并且获取当前卡的状态
         * @param passwd  登录卡的密码
         * @return 返回登录结果: xxxxxxx
         */
        @Override
        public int[] loginTFCard(String passwd) throws RemoteException {
            return xxxxxxxxxxx;
        }
}

在activity端,采用bindservice方法启动service,在onServiceConnected中拿到IEcmServiceBinder对象,就可以调用service端的方法了:

private ServiceConnection sc = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IEcmServiceBinder sEcmServiceAIDL = IEcmServiceBinder.Stub.asInterface(service);

            sEcmServiceAIDL.loginTFCard("123456");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

机制分析

先看看编译.aidl文件后生成的IEcmServiceBinder.java,先看个大概,我把里面的具体内容省略了:
这里写图片描述
还有方法申明和方法对应的常量:
这里写图片描述

这里写图片描述
IEcmServiceBinder继承了IInterface,这是一个interface:
这里写图片描述
IEcmServiceBinder里面有个Stub类,Stub里还有个Proxy类。
我们在service端实现登录方法时是这样写的:

public IEcmServiceBinder.Stub mEcmServiceBinder = new IEcmServiceBinder.Stub() {
    ............
}

即在service端创建了一个Stub类对象,IEcmServiceBinder.Stub()是调用了Stub的构造函数:
这里写图片描述
这是Binder中的方法:
这里写图片描述
Stub本来就继承了Binder,这样是在这个Stub中保存了一个IInterface对象(就是这个Stub),将IInterface与Stub关联起来,之后通过queryLocalInterface()可以取出这个接口(Stub)。

下面看看activity端,onServiceConnected后,通过传来的IBinder拿到AIDL对象:

IEcmServiceBinder sEcmServiceAIDL = IEcmServiceBinder.Stub.asInterface(service);

还是要回到Stub类,它的asInterface()方法:
这里写图片描述
之前提到,queryLocalInterface()会取出在构造函数中保存的Stub对象,如果这个对象是IEcmServiceBinder的实例,转成IEcmServiceBinder返回;否则new一个Proxy对象返回。
这个地方现在不太明白,网上的说法:
这里写图片描述
http://blog.csdn.net/c10wtiybq1ye3/article/details/78362429
怎么区分不同进程的????????
关键在这几行代码:

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.cetcs.encryptcardmanager.EcmService.IEcmServiceBinder))) {
return ((com.cetcs.encryptcardmanager.EcmService.IEcmServiceBinder)iin);
}
return new com.cetcs.encryptcardmanager.EcmService.IEcmServiceBinder.Stub.Proxy(obj);

传了一个字符串常量进去,这个常量是完整类名,假如在其它进程中,可以想象就是其它应用的包名+类名,以此来区分是不是在相同进程。
跟到代码中去,是这样的:

public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

mOwner是这样定义的:

    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

这个方法又是在Stub的构造函数中,把descriptor传进去的:

public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}

Stub,是在服务端创建的:
这里写图片描述
这个stub是个静态内部类,直接就构造出来了。在需要判断是不是相同进程时,就通过stub的标签来判断是不是一样的。
那么又要看看Proxy的代码了:
这里写图片描述
还有一个与AIDL中方法名一样的方法:
这里写图片描述
先不管Proxy的其它代码,注意图中标红的部分,调用了mRemote的transact方法,transact是Binder的方法:
这里写图片描述
然后又调用Binder的onTransact:
这里写图片描述
我们看注释,它需要被override,所以不用关心里面的实现。注意到mRemote是初始化传进来的IBinder对象:
这里写图片描述
最后一行,那个obj其实是Stub构造函数中存入的Stub本身,这个Stub也override了onTransact方法:
这里写图片描述
所以通过asInterface返回的这个Proxy,具有和service端一样的方法loginTFCard,通过tracsact调用Stub中的onTransact,下面再看看onTransat:
这里写图片描述
如果还有其它方法,这里会有很多case。这里传进来了code,data,reply和flags。code就是每个实现方法对应的一个int型常量,data保留了方法调用时传如的参数,在这里是密码“123456”,reply中保留了方法调用的结果。这里调用到了this.loginTFCard(_arg0),this就是Stub,是一开始在service端创建的:

public IEcmServiceBinder.Stub mEcmServiceBinder = new IEcmServiceBinder.Stub() {
    xxxxxxxxxxxxxxxxxxxxxxxxx
}

这样回到了service端,可以调用里面的方法了。
所以,我们通过IEcmServiceBinder.Stub.asInterface(service),拿到AIDL的代理类Proxy,Proxy通过transact,调用Stub的onTransact,间接调用到service端的代码了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值