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三个文件。
    这里写图片描述

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

package com.znh.aidl.server;

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

/**
 * Created by znh on 2018/6/10.
 * <p>
 * 封装图书信息的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<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];
        }
    };

    @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<Book> getBookList();

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

2、 步骤2:编译server端代码,会自动生成一个 IBookManager的java类, 里面书写了Binder相关代码。
这里写图片描述

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<com.znh.aidl.server.Book> _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<com.znh.aidl.server.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.znh.aidl.server.Book> _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<com.znh.aidl.server.Book> 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.
 * <p>
 * 远程服务
 */
public class RemoteService extends Service {

    //图书列表
    private List<Book> 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<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }
    }
}

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

    <service android:name=".RemoteService">
        <intent-filter>
            <action android:name="com.znh.aidl.server.remoteservice" />
        </intent-filter>
    </service>

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

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.
 * <p>
 * 本地调用
 */
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<Book> books = mIBookManager.getBookList();
            Log.e("znh", "books:" + books.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/huideveloper/article/details/80645478