Android关于aidl的理解

AIDL简介

Android中,进程之间原则上是不能进行通信的。但偏偏Android从四大组件到框架、底层到处都是IPC的影子。AIDL就是IPC方式之一。

AIDLAndroid 接口定义语言) 是 Android 提供的一种进程间通信 (IPC) 机制。

我们可以使用它在两个不同进程之间ClientServer进行通信

使用AIDL步骤

使用aidl大致分为三块,编写aidl生成必要文件。创建ClientServer使用。

  • 编写AIDL

    • 创建Bean类,实现Parcelable接口(便于序列化反序列化)。
    • 编写aidl文件
    • 生成java文件
  • 编写Server

    • 创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法
    • onBind()中返回
  • 编写Client

    • 实现 ServiceConnection 接口,在其中拿到 AIDL
    • 绑定服务
    • 调用aidl中的请求并等待返回结果

步骤一:编写AIDL

  • 创建Bean类,实现Parcelable接口(便于序列化反序列化
package com.cx.aidldemo.bean;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * 书的实体类
 */
public class Book implements Parcelable {

    private String name;
    private double price;

    public Book() {}

    public Book(String name, double price) {
        this.name = name;
        this.price = price;
    }

    protected Book(Parcel in) {
        name = in.readString();
        price = in.readDouble();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeDouble(price);
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 编写aidl文件

    • 不过在编写aidl文件之前,要拥有aidl目录。没有的话就创建。
    • 创建方式:在main目录下创建aidl目录,并在aidl目录下创建和java目录下子目录一样的包名。

    这里写图片描述

    • 创建Bean类的aidl
    // Book.aidl
    package com.cx.aidldemo.bean;
    
    parcelable Book;

    • 创建接口的aidl
    // IMyService.aidl
    package com.cx.aidldemo;
    
    import com.cx.aidldemo.bean.Book;
    
    interface IMyService {
    
      /**
       * 添加一个书
       */
      void addBook(in Book book);
    
      /**
       * 获取所有书
       */
      List<Book> getBookList();
    }
    

注意:

  1. 这个 Book.aidl 的包名要和实体类包名一致。
  2. 除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入),out(输出),inout(输入输出)。
  3. 非基本类型的数据需要导入它的全路径。即便是同级目录下。
  • 生成java文件
    • 方式:Build -> Make Project
    • 然后就会在app/build/generated/source/aidl/package_name/ 下生成一个 Java 文件
      这里写图片描述

现在我们就可以通过它来进行IPC通信了。

步骤二:编写Server

  • 创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法
  • onBind()中返回
public class MyAIDLService extends Service {

    private List<Book> books;

    public MyAIDLService() {
    }

    private IBinder mIBinder = new IMyService.Stub() {
        @Override
        public void addBook(Book book) throws RemoteException {
            books.add(book);
        }

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

    @Override
    public IBinder onBind(Intent intent) {
        books = new ArrayList<Book>();
        return mIBinder;
    }
}   

配置清单:

<service
    android:name=".MyAIDLService"
    android:enabled="true"
    android:exported="true"
    android:process=":aidl"></service>
  • enabled属性

    • 默认为true
    • 其值为true,则说明应用程序组件可以被Android系统自动实例化
    • 如果为false,则说明实例化组件的工作需要手工完成。
  • exported属性

    • 是否支持其它应用调用当前组件
    • 如果包含有intent-filter 默认值为true;没有intent-filter默认值为false
  • process属性

    • 如果该属性里设置的名字以冒号开头(:),那么在需要的时候它将生成该应用程序的一个私有新进程

服务端实现了接口,在 onBind() 中返回这个 Binder,客户端拿到就可以操作数据了。

步骤三:编写Client

  • 实现 ServiceConnection 接口,在其中拿到 AIDL
public class MainActivity extends AppCompatActivity {

    private IMyService iMyService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            // onBind连接后会返回 Binder,也就是iBinder参数
            // 将其转换成 AIDL,在不同进程会返回代理对象
            iMyService = IMyService.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            iMyService = null;
        }
    };
}
  • 绑定服务
Intent intent1 = new Intent(getApplicationContext(), MyAIDLService.class);
// 绑定服务
bindService(intent1, connection, BIND_AUTO_CREATE);
  • 调用aidl中的请求并等待返回结果
/**
 * 添加一本书
 * @param view
 */
public void onAddBook(View view) {
    Book book = new Book("Android_" + System.currentTimeMillis(), 100);
    try {
        iMyService.addBook(book);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

/**
 * 获取所有书籍
 * @param view
 */
public void onGetBooks(View view) {
    try {
        tvResult.setText(iMyService.getBookList().toString());
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

日志打印:

这里写图片描述
这里写图片描述

运行结果:

这里写图片描述

源码Demo下载地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值