Android AIDL浅析(一)

一、什么是AIDL?

  • AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言;
  • AIDL是进行进程间通信的常用方式

二、怎么使用AIDL?

总体来说,使用AIDL的过程可以总结为:
  1. 定义AIDL接口
  2. 服务端对AIDL接口进行逻辑补全
  3. 客户端通过AIDL接口调用服务端逻辑进行各种操作

数据跨进程传输过程就在这种调用与被调用过程中通过binder进行

代码详析(非原始数据类型):

1. 待传输对象类:

public class People implements Parcelable {

    private String name;
    private int age;
    private String sex;

    //无参构造函数
    public People() {
        name = "";
        age = 0;
        sex = "";
    }

    //一般构造函数,提供给用户构造People对象
    public People(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    //Android studio可自动生成,提供给系统 Creator 生成People对象
    protected People(Parcel in) {
        name = in.readString();
        age = in.readInt();
        sex = in.readString();
    }

    //这个对象是AIDL中tag为in或inout时候调用的,即从序列化流中创建people对象的时候调用
    public static final Creator<People> CREATOR = new Creator<People>() {
        @Override
        public People createFromParcel(Parcel in) {
            return new People(in);
        }

        @Override
        public People[] newArray(int size) {
            return new People[size];
        }
    };

    //Parcel的内容包含文件描述符,一般传0
    @Override
    public int describeContents() {
        return 0;
    }

    //如果你需要使用out或inout的tag的话,就要自己定义这个函数,它目的是通过流修改当前people对象的属性
    public void readFromParcel(Parcel parcel) {
        name = parcel.readString();
        age = parcel.readInt();
        sex = parcel.readString();
    }

    //将为tag为in的数据写入流中传输
    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(age);
        parcel.writeString(sex);
    }

    //无特殊意义,只是为了方便显示
    @Override
    public String toString() {
        return name + ", " + age + " years old, is a " + sex;
    }

2. 待传输对象的AIDL文件(AIDL类1):

package com.AIDL_demo;
parcelable People;//只需要声明本类为parcelable

3. 定义接口方法的AIDL(AIDL类2):

package com.AIDL_demo;
import com.AIDL_demo.People;

interface IMethod {
    List<People> getPeople();
}

4. 服务端:

public class MyService extends Service {

    List<People> people = new ArrayList<>();

    private final IMethod.Stub method = new IMethod.Stub() {
        @Override
        public List<People> getPeople() throws RemoteException {
            return people;
        }
    };

    public MyService() {
        People man1 = new People("Mike", 18, "male");
        people.add(man1);

        People man2 = new People("Lucy", 26, "female");
        people.add(man2);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return method;
    }
}

5. 客户端关键代码:

//跨进程启动service
public void bindRemoteService() {
        Intent intent = new Intent();
        intent.setAction("my_remote_service");//manifest中service的action
        intent.setPackage("com.AIDL_demo");//服务端的package名
        bindService(intent, connection, Service.BIND_AUTO_CREATE);
    }

    private IMethod method;

    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            method = IMethod.Stub.asInterface(iBinder);//获取远程服务端的AIDL通信对象
            if (method == null) {
                Log.d("LogTag", "IMethod is null");
                return;
            }
            try {
                List<com.AIDL_demo.People> peopleList = method.getPeople();//调用远程接口获取服务端数据
                //打印数据
                StringBuilder stringBuilder = new StringBuilder();
                for (People people : peopleList) {
                    stringBuilder.append(people.toString());
                    stringBuilder.append("\n");
                }
                Log.d("LogTag", stringBuilder.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("LogTag", "service disconnected");
        }
    };
最终运行会在客户端Logcat中打印:
D/LogTag: Mike, 18 years old, is a male
Lucy, 26 years old, is a female

结论:成功跨进程通信,将服务端创建的两个People对象,传输到了客户端;

注意事项

  • AIDL文件必须和这个非原始数据类在同名包下,只是一个在Java目录下,一个在AIDL目录下:
    这里写图片描述
  • AIDL中在参数为非默认数据类型的变量时,都需要设置定向的tag
  • ADIL中默认支持Java八大基本类型和String,CharSequence,List(元素必须是AIDL支持的,List可以使用泛型),Map(元素必须是AIDL支持,Map不支持泛型);

  • AIDL文件可以分为两类。一类是用来定义非默认支持的数据类型,以供其他AIDL文件使用的,如上面代码中的 “AIDL类1” ;一类是用来定义方法接口,用来完成跨进程通信的,如上面代码中的 “AIDL类2” 。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值