AIDL原理和调用

1.用法

(1)服务端声明和创建

<!--exported:允许外界访问该服务,AIDL必备条件-->
<service
android:name=".MyService"
android:exported="true"/>
</application>

(2)添加aidl文件, 比如一个+方法

右键包添加aidl. 在生成的文件中写上自己的方法

interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
int add(int num1, int num2);
}

(3)点击编译按钮, 自动生成


(4)服务端当然是写一个服务, 用来提供这个接口的代理

public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return myS;
}

private IBinder myS = new IMyAidlInterface.Stub() {

@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

}

@Override
public int add(int num1, int num2) throws RemoteException {
return num1 + num2;
}
};
}

(5)服务端启动这个服务

startService(new Intent(this, MyService.class));

2.客户端


(1)从服务端原封不动拷贝过来

(2)在oncreate中绑定上面生成的服务

        Intent intent = new Intent();
        intent.setComponent(new ComponentName("lynash.com.aidl_service", "lynash.com.aidl_service.MyService"));
        bindService(intent, conn, BIND_AUTO_CREATE);
   
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);//获取代理
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iMyAidlInterface = null;
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
(3)在业务逻辑中调用代理

 int res = iMyAidlInterface.add(1, 2);

2. 调用过程

1.客户端与服务端其实是用过一个binder来进行数据交互.

2.分析一下根据IMyAidlInterface.aidl 生成的IMyAidlInterface.java, 它是文件的核心

3.IMyAidlInterface包含一个内部类

public static abstract class Stub extends android.os.Binder implements lynash.com.aidl_service.IMyAidlInterface
4.Stub中包含了一个代理类

private static class Proxy implements lynash.com.aidl_service.IMyAidlInterface
{
	private android.os.IBinder mRemote;
5.客户端获得binder的代码

public void onServiceConnected(ComponentName name, IBinder service) {  
	iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);  
}  
代码定位到Stub类asInterface方法:
 
return new lynash.com.aidl_service.IMyAidlInterface.Stub.Proxy(obj);
 
我们将传过来的obj(这个obj 就是服务的具体实现, 他实现了Binder接口).   传给了它的代理类来处理,返回的是代理类的对象. 

6.客户端调用方法

int res = iMyAidlInterface.add(1, 2);  
服务端代理对add的处理

@Override  
	            public int add(int num1, int num2) throws android.os.RemoteException {  
	                android.os.Parcel _data = android.os.Parcel.obtain();  
	                android.os.Parcel _reply = android.os.Parcel.obtain();  
	                int _result;  
	                try {  
	                    _data.writeInterfaceToken(DESCRIPTOR);  
	                    _data.writeInt(num1);  
	                    _data.writeInt(num2);  
	                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);  
	                    _reply.readException();  
	                    _result = _reply.readInt();  
                } finally {  
	                    _reply.recycle();  
	                    _data.recycle();  
	                }  
	                return _result;  
	            }  
它把数据写进了_data里面,最后调用transact方法,传入_data数据,唯一标识Stub.TRANSACTION_add。
然后, 代理通过

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);  
将方法标识和参数, 通过binder的机制, 传给Stub类.调用Stub中的onTransact方法, 这个方法才是真正的计算逻辑.

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
...
case TRANSACTION_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
最后将计算结果返回给客户端, 通过

return super.onTransact(code, data, reply, flags);  
super就是Binder. 

3. 原理分析

(1)客户端bindservice

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }
(2)服务返回Binder
public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return myS;
    }

    private IBinder myS = new IMyAidlInterface.Stub() {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.i("Hensen", "从客户端发来的AIDL请求:num1->" + num1 + "::num2->" + num2);
            return num1 + num2;
        }
    };
}
(3)可见, 服务器返回的Binder是 实现了Binder implements IBinder的 IMyAidlInterface.Stub()对象.

(4)客户端通过这个IBinder, 就是onServiceConnected的参数IBinder service对象, 获取AIDL的代理

iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
(5)通过IMyAidlInterface.Stub.asInterface(service) , 返回来的是一个IMyAidlInterface实例

(6)这个实例是new lynash.com.aidl_service.IMyAidlInterface.Stub.Proxy(obj); 

//以上是AIDL的代码obj就是service, Proxy也是实现了IMyAidlInterface接口的, 所以才能利用这个代理来调用add方法

(7)客户端调用,iMyAidlInterface.add

这个是核心调用过程, 代理的add, 设置了data的具体内容. data是android.os.Parcel _data.

然后调用service对象的transact. 这样就将data数据和方法标识(add)传递给了Stub.

Stub调用onTransact进行计算, 然后将运算结果返回给proxy. proxy再将结果返回给客户端. 

桥梁代码就是这个:proxy中的add代码

@Override public int add(int num1, int num2) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(num1);
_data.writeInt(num2);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);//mRemote就是实现了binder的Stub. 通过binder把数据传递给Stub.进行计算, 并把结果写入到_reply
_reply.readException();
_result = _reply.readInt();//取出结果, 返回给客户端.
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值