Android进程通信之AIDL的使用与Binder浅谈

一、AIDL简介

AIDL是Android接口定义语言,有点类似于我们开发中的普通接口。由于不同进程间不能共享内存,为了解决进程间通信的问题,可以通过AIDL接口语言来实现进程间的通信。

二、AIDL文件支持的数据类型
  • 基本数据类型(int、long、char、boolean、double)
  • String和CharSequence
  • List和Map集合
  • 集合内元素必须是AIDL支持的数据类型
  • 服务端具体使用的集合必须是ArrayList和HashMap
  • Parcelable:实现了Parcelable接口的对象
  • AIDL本身接口也可以在AIDl文件使用。
三、AIDL使用步骤

主要有三大步骤

  1. 创建AIDL
    (1)创建实例类,必须实现Parcelable接口,用于序列化和反序列化
    (2)新建aidl文件夹,在其创建与实例类同名的aidl文件及其他aidl接口文件
    (3)rebuild项目,生成Binder的java接口文件。
  2. 创建服务端(Service)
    (1)创建Service,在onBind方法中返回Binder实例对象,并实现aidl接口方法。
  3. 编写客服端(Activity或其他)
    (1)使用bindService方式启动服务,实现ServiceConnection接口,拿到aidl生成的Binder对象。
    (2)调用aidl定义好的函数方法。
四、AIDL具体实现

为了方便AIDL的开发,建议所有和AIDL相关的类和文件全部放在同一个包,这样方便其他地方需要使用,可以直接复制过去。
下面是具体例子的文件目录:
在这里插入图片描述
注意:

aidl文件目录是和java目录同级的

1、创建AIDL
1.1、创建进程间需要传输的实体类,实现 Parcelable 接口
public class Book implements Parcelable{
   

    private String bookName;

    public Book(String bookName) {
   
        this.bookName = bookName;
    }

    @Override
    public int describeContents() {
   
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
   
        dest.writeString(this.bookName);
    }

    protected Book(Parcel in) {
   
        this.bookName = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
   
        @Override
        public Book createFromParcel(Parcel source) {
   
            return new Book(source);
        }

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

    @Override
    public String toString() {
   
        return "Book{" +
                "bookName='" + bookName + '\'' +
                '}';
    }
}

实现 Parcelable 接口是为了实例类能够在进程间通信。
其实进程间通信是一个序列化和反序列化的过程,关于序列化可以参考这篇文章Android进程通信之文件共享(序列化Serialzable与Parcelable)

1.2、新建aidl文件夹,在其创建与实例类同名的aidl文件及其他aidl接口文件
  • 新建aidl文件夹,主要aidl目录和java目录是同级的,在main目录下面。
    在这里插入图片描述
  • 创建与实体类(Book)同名的aidl文件:Book.aidl
// Book.aidl 
package com.hzw.progress.aidl;

//声明Book实体类已序列化,可用于进程间传输
parcelable Book;

这样做的目的是让aidl文件知道Book类实现了Parcelable接口,可将Book对象作为进程间传输数据的载体。

注意:

Book实体类和Book.aidl文件必须要在相同包结构目录下,否则会运行出错,是因为客服端需要反序列化服务端的AIDL接口相关的类,如果类的路径不一样的话,客户端会反序列失败。

IBookManager.aidl接口

// IBookManager.aidl
package com.hzw.progress.aidl;

// Declare any non-default types here with import statements
//虽然在IBookManager.aidl和Book.aidl同一个包名下,但必须以import方式将Book.aial文件导入(手动导入)
import com.hzw.progress.aidl.Book;

import com.hzw.progress.aidl.OnNewBookAddListener;

//定义客户端与服务端间的回调接口
interface IBookManager {
   

    //得到全部数据(全部书籍)
    List<Book> getBookList();
    //添加数据的操作(添加书籍)
    void addBook(in Book book);
    //注册监听,用于监听新数据的变化。是典型的观察者模式的运用
    void registerListener(OnNewBookAddListener listener);
    //解注册
    void unregisterListener(OnNewBookAddListener listener);
}

OnNewBookAddListener.aidl接口文件

// OnNewBookAddListener.aidl
package com.hzw.progress.aidl;

import com.hzw.progress.aidl.Book;


// Declare any non-default types here with import statements

//定义监听新数据变化的接口(添加新书籍)
interface OnNewBookAddListener {
   

    void onNewBookAdd(in Book book);

    void onAllBook();
}

以上需要注意的点,在addBook和onNewBookAdd方法接参中有个in,表示输入型参数。AIDL 中除了基本数据类型,其他数据类型必须标上方向,in,out 或者 inout。

  • in 表示输入型参数
  • out 表示输出型参数
  • inout 表示输入输出型参数
1.3 在创建好了aidl文件后,需要 rebuild项目,生成Binder的java接口文件。
2、创建服务端
2.1、创建服务端BookManagerService继承于Service
public class BookManagerService extends Service {
   

    private static final String TAG = "BookManagerService";
    private List<Book> mBookList=new ArrayList<>();
    private static List<OnNewBookAddListener> mAddListenerList=new ArrayList<>();

    public BookManagerService() {
   
    }

    @Override
    public void onCreate() {
   
        super.onCreate();
        //初始化书籍
        mBookList.add(new Book("Android群英传"));
        mBookList.add(new Book("Android开发艺术探索"));

    }

    @Override
    public IBinder onBind(Intent intent) {
   
        //获取Service需要的权限,进行自我验证,防止其他进程访问该服务
       int check= checkCallingOrSelfPermission("com.hzw.progress.aidl.permission.LOCAL");
       //未授权该应用,则无法访问
       if (check== PackageManager.PERMISSION_DENIED){
   
           return null;
       }
       //添加新书的过程
        BookFactory factory = new BookFactory();
        factory.execute(5); //添加五本书
        return mBinder;
    }

    /*
    * 初次new IBookManager方式构建Binder对象,会报错找不到IBookManager对象
    * 需要Rebuild下项目
    * */
    private Binder mBinder=new IBookManager.Stub() {
   

        @Override
        public List<Book> getBookList() throws RemoteException {
   
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
   
            mBookList.add(book);
        }

        @Override
        public void registerListener(OnNewBookAddListener listener) throws RemoteException {
   
            if (!mAddListenerList.contains(listener)){
   
                mAddListenerList.add(listener);
            }
            Log.i(TAG, "registerListener: "+mAddListenerList.size());
        }

        @Override
        public void unregisterListener(OnNewBookAddListener listener) 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值