AIDL的使用

AIDL的概念

AIDL:全称是Android Interface Definition Language(Android接口定义语言)。它主要用在Android进程间通信中,Android中有一种进程间通信方式是Binder,AIDL就是帮我们自动生成了Binder相关代码,不需要我们自己去手动书写复杂的Binder类,我们只需要在AIDL接口文件中书写自己的调用远程服务的业务方法就可以了,大大简化了开发过程。当然,AIDL不是Binder通信所必须的,我们也可以不使用AIDL而自己去书写Binder代码。

AIDL支持的数据类型

  1. 基本数据类型(int、long、char、boolean、double等);
  2. String和CharSequence;
  3. List:只支持ArrayList,而且里面的每个元素也必须是AIDL所支持的类型;
  4. Map:只支持HashMap,而且里面的每个key和value都必须是AIDL所支持的类型;
  5. Parcelable:所有实现了Parcelable接口的对象;
  6. AIDL:所有的AIDL接口自身也可以在AIDL中使用;

AIDL使用步骤

上面介绍了AIDL的概念、作用、所支持的类型,那么下面开始写一个例子,看一下AIDL到底是怎么使用的,该例子就用刚哥的图书管理的那个场景(《Android开发艺术探索》第2章),实现的功能是两个独立的应用,一个是Client端,一个是Server端,Server端提供获取图书列表和添加图书两个功能,而Client通过和Server端的进程间通信在Client端操作那两个功能。

  1. 步骤1:在server端添加aidl包,在里面添加Book.java、Book.aidl、IBookManager.aidl三个文件。
    AIDL的使用_第1张图片

Book.java类,需要实现Parcelable接口(为了被AIDL所支持):

package com.znh.aidl.server;

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

/**
 * Created by znh on 2018/6/10.
 * 

* 封装图书信息的Book类 */ public class Book implements Parcelable { //图书ID public int bookId; //图书名称 public String bookName; public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; } private Book(Parcel source) { bookId = source.readInt(); bookName = source.readString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(bookId); dest.writeString(bookName); } public static Creator CREATOR = new Creator() { @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{" + "bookId=" + bookId + ", bookName='" + bookName + '\'' + '}'; } }

Book.aidl文件,需要声明一下:

// Book.aidl
package com.znh.aidl.server;

parcelable Book;

IBookManager.aidl文件:

// IBookManager.aidl
package com.znh.aidl.server;

import com.znh.aidl.server.Book;

interface IBookManager {

    /**
     * 获取图书列表
     */
    List getBookList();

    /**
     * 添加图书
     */
    void addBook(in Book book);
}

2、 步骤2:编译server端代码,会自动生成一个 IBookManager的java类, 里面书写了Binder相关代码。
AIDL的使用_第2张图片

IBookManager.java类,代码是系统自动生成的:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\Studiospace\\AidlDemo\\server\\src\\main\\aidl\\com\\znh\\aidl\\server\\IBookManager.aidl
 */
package com.znh.aidl.server;

public interface IBookManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.znh.aidl.server.IBookManager {
        private static final java.lang.String DESCRIPTOR = "com.znh.aidl.server.IBookManager";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.znh.aidl.server.IBookManager interface,
         * generating a proxy if needed.
         */
        public static com.znh.aidl.server.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.znh.aidl.server.IBookManager))) {
                return ((com.znh.aidl.server.IBookManager) iin);
            }
            return new com.znh.aidl.server.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getBookList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    com.znh.aidl.server.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.znh.aidl.server.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.znh.aidl.server.IBookManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * 获取图书列表
             */
            @Override
            public java.util.List getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.znh.aidl.server.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            /**
             * 添加图书
             */
            @Override
            public void addBook(com.znh.aidl.server.Book book) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    /**
     * 获取图书列表
     */
    public java.util.List getBookList() throws android.os.RemoteException;

    /**
     * 添加图书
     */
    public void addBook(com.znh.aidl.server.Book book) throws android.os.RemoteException;
}

3、步骤3:编写远程服务代码RemoteService:

package com.znh.aidl.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by znh on 2018/6/10.
 * 

* 远程服务 */ public class RemoteService extends Service { //图书列表 private List mBookList; @Override public IBinder onBind(Intent intent) { return new LocalBinder(); } @Override public void onCreate() { super.onCreate(); mBookList = new ArrayList<>(); } /** * 编写远程服务中的本地Binder */ private class LocalBinder extends IBookManager.Stub { @Override public List getBookList() throws RemoteException { return mBookList; } @Override public void addBook(Book book) throws RemoteException { mBookList.add(book); } } }

4、在server端的清单文件中注册该服务:

    
        
            
        
    

5、经过以上4步,服务端代码就编写完毕了,接下来,把服务端的aidl包连同它下面的文件都拷贝到客户端,aidl文件的包名不能变,要和服务端保持一致:
AIDL的使用_第3张图片

6、在Client的MainActivity中绑定远程服务,并调用远程服务中的方法实现功能:

package com.znh.aidl.client;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.znh.aidl.server.Book;
import com.znh.aidl.server.IBookManager;

import java.util.List;

/**
 * Created by znh on 2018/6/10.
 * 

* 本地调用 */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //远程服务Binder的代理 private IBookManager mIBookManager; //创建连接 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取远程服务Binder的代理 mIBookManager = IBookManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; /** * 绑定服务 * * @param view */ public void bindService(View view) { Intent intent = new Intent(); intent.setAction("com.znh.aidl.server.remoteservice"); intent.setPackage("com.znh.aidl.server"); startService(intent); bindService(intent, mConnection, BIND_AUTO_CREATE); } /** * 添加图书 * * @param view */ public void addBook(View view) { try { mIBookManager.addBook(new Book(1, "Android")); } catch (RemoteException e) { e.printStackTrace(); } } /** * 获取图书列表 * * @param view */ public void getBookList(View view) { try { List books = mIBookManager.getBookList(); Log.e("znh", "books:" + books.toString()); } catch (RemoteException e) { e.printStackTrace(); } } }

你可能感兴趣的:(Android)