AIDL--初探篇

AIDL–初探篇

前言

如果说你问我什么是AIDL,那我只知道它叫做Android Interface Definition Language,即安卓接口定义语言,还有只知道它是基于Binder机制从而实现进程间通信的,在普遍的开发下挺少用到的,而且用起来有些麻烦,以上就是我所知道的AIDL,而下面要写的内容是我看着书去了解的,但还是对于AIDL只用皮毛的知识了解,那不多说了,继续写下面的笔记,开始。

设计目的

设计AIDL这门语言的目的就是为了实现进程间通信。在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求
通常,暴露方法给其他应用进行调用的应用称为服务端,调用其他应用的方法的应用称为客户端,客户端通过绑定服务端的Service来进行交互

AIDL传递的数据类型

1.基本数据类型(除short类型)
2.String、charSequence
3.List :List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象,
map:Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
4.parcelable

AIDL的创建可以参考这篇文章https://www.jianshu.com/p/29999c1a93cd,看到这篇文章后,再想想自己想说的简直乱的一塌糊涂,为了不误导其他人,还是看这边文章比较稳。

我的笔记的内容

自动生成的AIDL包在以下目录
在这里插入图片描述
若新建后出现该异常
Process ‘command ‘E:\Android\SDK\build-tools\28.0.3\aidl.exe’’ finished with non-zero exit value 1
需要在aidl包下创建与Book类名相同的aidl文件,内容如下在这里插入图片描述
这个一定要注意。

AIDL内容分析

DESCRIPTOR
表示Binder的唯一标识,一般为Binder的类名
在这里插入图片描述
asInterface(android.os.IBinder obj)
将Binder对象转换为com.hwt.myapplication.aidltest.IBookManage接口
将服务端的Binder对象转化为客户端所需的AIDL接口类型对象,这种是区分进程的,如果客户端和服务端位于同一个进程,则此方法返回的就是服务端本身的Sub对象,若不在同一进程,返回的是系统封装后的Sub.proxy对象。

public static com.hwt.myapplication.aidltest.IBookManage asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.hwt.myapplication.aidltest.IBookManage))) {
        return ((com.hwt.myapplication.aidltest.IBookManage) iin);
    }
    return new com.hwt.myapplication.aidltest.IBookManage.Stub.Proxy(obj);
}

asBinder
用于返回当前Binder对象

@Override
public android.os.IBinder asBinder() {
    return this;
}

@Override
public android.os.IBinder asBinder() {
    return mRemote;
}

onTransact

@Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
        java.lang.String descriptor = DESCRIPTOR;
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(descriptor);
                return true;
            }
            case TRANSACTION_basicTypes: {
                data.enforceInterface(descriptor);
                int _arg0;
                _arg0 = data.readInt();
                long _arg1;
                _arg1 = data.readLong();
                boolean _arg2;
                _arg2 = (0 != data.readInt());
                float _arg3;
                _arg3 = data.readFloat();
                double _arg4;
                _arg4 = data.readDouble();
                java.lang.String _arg5;
                _arg5 = data.readString();
                this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_addBook: {
                data.enforceInterface(descriptor);
                com.hwt.myapplication.aidltest.Book _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.hwt.myapplication.aidltest.Book.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.addBook(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getBookList: {
                data.enforceInterface(descriptor);
                java.util.List<com.hwt.myapplication.aidltest.Book> _result = this.getBookList();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }

这个方法运行在服务端的Binder线程池中,当客户端跨进程请求时,远程请求会通过系统底层封装后交给这个方法处理,该方法原型为public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags),服务端通过code判断客户端要请求什么方法,然后从data中取出目标方法所需的参数(如果有目标方法的参数的话),然后就执行目标方法,执行完毕后,就向reply写入返回值(如果目标方法有返回值的话),这就是onTransact的执行过程。
注意:如果该方法返回false,那么说明客户端请求失败,因此可以通过这个方法做权限验证,验证哪个进程可以远程调用我们的服务

Proxy的方法
例如有参数的方法:
getBookList内部执行过程如下:
创建该方法所需的输入型Parcel对象_data,输出型Parcel对象_reply和返回值对象List,然后把该方法的参数信息写入到_data中(如果有参);接着调用transact进行RPC(远程过程调用)请求,同时挂起当前线程,然后服务端的onTransact方法被调用,直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果,最后返回_reply中的数据。

@Override
public java.util.List<com.hwt.myapplication.aidltest.Book> getBookList() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    java.util.List<com.hwt.myapplication.aidltest.Book> _result;
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
        _reply.readException();
        _result = _reply.createTypedArrayList(com.hwt.myapplication.aidltest.Book.CREATOR);
    } finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

没参数和没返回值的方法:
它和有参数方法的过程时一样的,只是没有返回值,所以不需要从_reply中取出返回值
整个AIDL的流程
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值