详解 Android IPC 机制(六)使用 AIDL 实现进程间通信

Author Avatar
wshunli 6月 08, 2018
  • 在其它设备中阅读本文章

AIDL(Android Interface Definition Language ,Android 接口定义语言),定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。

只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。

如果不需要执行跨越不同应用的并发 IPC,就应该通过实现一个 Binder 创建接口;或者,如果想执行 IPC,但根本不需要处理多线程,则使用 Messenger 类来实现接口。

1、创建 AIDL 文件

首先在 java 同级目录 aidl 文件夹,然后创建 .aidl 文件。

6.AIDL文件

// IBookManager.aidl
package com.wshunli.ipc.demo;
// Declare any non-default types here with import statements
import com.wshunli.ipc.demo.Book;
interface IBookManager {
    List<Book> getBookList();
    void addBook(in Book book);
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

.aidl 文件中支持的数据类型包括:

  • 基本数据类型
  • String 和 CharSequence
  • List:只支持 ArrayList , 里面的元素都必须被 AIDL 支持
  • Map:只支持 HashMap , 里面的元素必须被 AIDL 支持
  • 实现 Parcelable 接口的对象
  • 所有 AIDL 接口

然后创建实现了 Parcelable 的类:

public class Book implements Parcelable {

    public String name;

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

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

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

    public static 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];
        }
    };

    private Book(Parcel source) {
        name = source.readString();
    }

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

创建 Book.aidl 文件:

// Book.aidl
package com.wshunli.ipc.demo;
// Declare any non-default types here with import statements
parcelable Book;

这时候重新编译程序,工程就会自动生成 BookManager.aidl 接口对应的文件。

app\build\generated\source\aidl\debug\com\wshunli\ipc\demoIBookManager.java

2、创建服务端

服务端使用 IBookManager.Stub() 方法创建 Binder 实例并在 onBind() 方法中返回。

public class BookManagerService extends Service {
    private static final String TAG = "BookManagerService";

    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();

    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 basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
    };

    public BookManagerService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book("android"));
        mBookList.add(new Book("ios"));
    }

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

其中 onCreate() 方法中填充了数据。

当然在 AndroidManife 文件中要配置 Service

<service
    android:name="com.wshunli.ipc.demo.BookManagerService"
    android:enabled="true"
    android:exported="true"
    android:process=":remote" />

3、客户端

客户端还是使用 bindService() 方法绑定服务。

public class BookManagerActivity extends AppCompatActivity {

    private static final String TAG = "BookManagerActivity";

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            IBookManager bookManager = IBookManager.Stub.asInterface(service);
            try {
                List<Book> bookList = bookManager.getBookList();
                Log.d(TAG, "onServiceConnected: " + bookList.toString());

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

        Intent intent = new Intent(BookManagerActivity.this, BookManagerService.class);
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        super.onDestroy();
    }
}

其中 IBookManager 对象来调用具体服务器方法,获取数据。

AIDL 的功能远不止这些,后面再深入研究。

参考资料
1、《Android开发艺术探索》 — 2.4.4 使用 AIDL
2、Android 接口定义语言 (AIDL) | Android Developers
https://developer.android.com/guide/components/aidl
3、Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用 | 刘望舒的博客
http://liuwangshu.cn/application/ipc/3-aidl.html

如果本文对您有所帮助,且您手头还很宽裕,欢迎打赏赞助我,以支付网站服务器和域名费用。 https://paypal.me/wshunli 您的鼓励与支持是我更新的最大动力,我会铭记于心,倾于博客。
本文链接:https://www.wshunli.com/posts/75f6d3a2.html