? IPC 机制之使用 AIDL

AIDL 介绍

IPC 即 Inter-Process Communication (进程间通信),AIDL(Android Interface definition language) 是其中的一种方式,其功能强大,支持一对多并发通信,支持实时通信。
AIDL的作用是让你可以在自己的APP里绑定一个其他APP(或者进程)的service,这样你的APP可以和其他APP交互。

AIDL 使用

① 数据类准备

AIDL 用于处理进程间的数据通信,那么必然要先有数据。
创建 Book.java ,并实现 Parcelable 接口。

package com.zhxumao.android.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
    int bookId;
    String bookName;
    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }
    public Book(int bookId, String bookName) {
        this.bookId = bookId;
        this.bookName = bookName;
    }
    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.writeInt(bookId);
        dest.writeString(bookName);
    }
}
复制代码

② AIDL 接口创建

1、创建 AIDL 接口类 :IBookManager.aidl,并添加自定义方法。
2、因为 IBookManager.aidl 中用到了自定义的 Parcelable 对象 Book(非6种基础类型外),所以也需要创建下同名文件 Book.aidl
3、重新 Build 下工程,可在 build > gen 目录下找到 IBookManager 的实现类,这是由编辑器自动生成。

// IBookManager.aidl
package com.zhxumao.android.aidl;
import com.zhxumao.android.aidl.Book;
interface IBookManager {
    void addBook(in Book book);
    List<Book> getBookList();
}
复制代码
// Book.aidl
package com.zhxumao.android.aidl;
// Declare any non-default types here with import statements
//声明 parcelable 对象
parcelable Book;
复制代码

编辑器生成的 IBookManager 实现类
主要关注抽象静态内部类 Stub,需要我们在 service 中继承实现。

package com.zhxumao.android.aidl;
public interface IBookManager extends android.os.IInterface
{
  /** Default implementation for IBookManager. */
  public static class Default implements com.zhxumao.android.aidl.IBookManager {
    //代码省略
    ...
  }
  public static abstract class Stub extends android.os.Binder implements com.zhxumao.android.aidl.IBookManager {
    //代码省略
    ...
  }
  public void addBook(com.zhxumao.android.aidl.Book book) throws android.os.RemoteException;
  public java.util.List<com.zhxumao.android.aidl.Book> getBookList() throws android.os.RemoteException;
}
复制代码

③ 远程服务端Service实现

1、创建 BookManagerService.java ,继承 Service
2、获取 AIDL 接口类中的 IBookManager#Stub 的实例,返回的是一个 Binder 对象: Binder mBinder = new IBookManager.Stub();
3、在 service 的 onBind() 中,返回以上 Binder 对象。
4、在 IBookManager 定义的方法体中,写自己服务端逻辑即可,服务端的功能就可以了。

public class BookManagerService extends Service {
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
    private Binder mBinder = new IBookManager.Stub() {
        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }
        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}
复制代码
//别忘记在 manifest.xml 中声明服务
<service
    android:name=".BookManagerService"
    android:process=":aidl" />
复制代码

④ 客户端实现

假设我们在某个 Activity 中:
1、实现 ServiceConnection 接口类,在 onServiceConnected() 中获取 IBookManager 对象。

private IBookManager manager;
private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        manager = IBookManager.Stub.asInterface(service);
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
    }
};
复制代码

2、启动服务 BookManagerService,使用 bindService() 绑定启动服务,设置好 ServiceConnection 。

bindService(new Intent(MainActivity.this, BookManagerService.class), connection, Context.BIND_AUTO_CREATE);
复制代码

3、服务启动完成后,我们将在 ServiceConnection 中获取到 IBookManager 的实例,到此我们才能进行客户端的逻辑编写,比如想往 service 中插入/获取数据:

//插入一条数据
manager.addBook(new Book(1, "android"));
//获取service所有已保存数据
List<Book> bookList = manager.getBookList();
复制代码

现在整个 AIDL 的使用方式都已经实现了,注意最后退出的时候,如果不需要服务继续运行了,不要忘了解绑服务。

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(connection);
}
复制代码

最后总结一下,使用 AIDL 进行进程间通信,大概需要进行以下几个步骤:

  • 创建 .aidl 接口文件。
  • 在 service 中实现 aidl 接口的 Stub,并补充 service 业务逻辑(注意处理好线程并发问题)。
  • 客户端实现 ServiceConnection ,并获取到 aidl 接口的实现类实例,并补充客户端业务逻辑。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享