美文网首页
Android关于aidl的理解

Android关于aidl的理解

作者: 海重山青 | 来源:发表于2018-03-14 16:33 被阅读0次

原创博客地址

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目录下子目录一样的包名。
aidl包名一致.png
  • 创建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 文件
生成java文件.png

现在我们就可以通过它来进行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();
    }
}

日志打印:

服务端进程名.png
客户端进程名.png

运行结果:

运行结果.gif

源码Demo下载地址

相关文章

  • AIDL

    Android中AIDL的基本用法Android 中AIDL的使用与理解Android AIDL使用详解彻底明白A...

  • Android关于aidl的理解

    原创博客地址 AIDL简介 在Android中,进程之间原则上是不能进行通信的。但偏偏Android从四大组件到框...

  • 收集_Binder机制

    为什么 Android 要采用 Binder 作为 IPC 机制?AIDL原理解析Android中AIDL的工作原...

  • Android平台必备技能(一)---进程间通信AIDL的应用详

    一些必备的背景知识,理解以下知识将有助于编写AIDL通信流程。 1. AIDL是什么? AIDL:Android ...

  • IPC相关

    Android权限之sharedUserId、签名(实例说明) Android 中AIDL的使用与理解 Binde...

  • AIDL的基本使用

    XSize的主页 AIDL的使用 AIDL是android中接口定义语言,用于进程间通信.这里大家其实应该好好理解...

  • Android中的AIDL

    Android中的AIDL使用详解 AIDL使用解析 Android进阶之AIDL的使用详解

  • AIDL通信

    这是看了《Android开发艺术》和官网的AIDL资料后对AIDL通信的一点理解,分析了AndroidStudio...

  • 对Binder的实现原理的理解

    写给 Android 应用工程师的 Binder 原理剖析简单理解Binder机制的原理 aidl Android...

  • AIDL使用详解及原理(附加例子)

    AIDL是什么? AIDL(Android Interface Define Language ——Android...

网友评论

      本文标题:Android关于aidl的理解

      本文链接:https://www.haomeiwen.com/subject/bqnfqftx.html