android 跨应用进程之间的通信之AIDL

通常我们熟悉同一进程的通信方式,关于跨进程之间的通信AIDL的实现方式。

Android studio提供了aldl工具,创建步骤

1、右击项目文件,选择AIDL File


2、我们可以任意取一个文件名,点击finish


3、创建接口文件


4、创建我们要获取对象数据的Book.java文件

下面分别把这三个文件的源代码贴出来:

Book.java

public class Book implements Parcelable {
    private String bookName;
    private String bookPrice;
    protected Book(Parcel in) {
        bookName = in.readString();
        bookPrice = in.readString();
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookPrice() {
        return bookPrice;
    }

    public void setBookPrice(String bookPrice) {
        this.bookPrice = bookPrice;
    }

    public static final Creator CREATOR = new Creator() {
        @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(bookName);
        dest.writeString(bookPrice);
    }
}
Book.aidl文件

package package com.test.Book.aidl;

// Declare any non-default types here with import statements
parcelable Book;


IBookManager.aidl文件

package com.test.Book.aidl;

// Declare any non-default types here with import statements
import com.test.Book;
interface IBookManager {
List getBookList();
void addBook(in Book book);

}


我们点击编辑,在app/build/generated/source/debug/目录下会自动生成一个IBookManager.java文件

下面已service和client分别作为不同进程为例,做具体的实现过程。service和client可以是同一个android应用,也可以是不同的两个android应用。以上的三个文件作为两个进程通讯的基础文件。

Service端代码

public class BindService extends Service {
    List books = new ArrayList<>();
    private final IBookManager.Stub binder = new IBookManager.Stub() {
    @Override
    public List getBookList() throws RemoteException {
        synchronized (books) {
            return books;
        }
    }

    @Override
    public void addBook(Book book) throws RemoteException {
        synchronized (book) {
            if (!books.contains(book)) {
                books.add(book);
            }
        }
    }
};

    @Override
    public void onCreate() {
        super.onCreate();
        Book book = new Book("图书一","10");
        books.add(book);
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        Book book = new Book("图书二","20");
        if (books == null) {
            books.add(book);
        }else {
            if (!books.contains(book)) {
                books.add(book);
            }
        }
        return binder;
    }
}


client的读取service数据对象的代码:

首先绑定服务端

    public void onBindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.test.test", "com.test.tes.BindService"));
        bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);

    }
然后获取服务端进程数据对象

 public void getBookList(View view) {

        try {
            List bookList = binders.getBookList();
            for(Book book:bookList) {
                Log.e(tag,book.toString());
            }

        }catch (Exception e) {

            Log.e(tag,e.getMessage());
        }
    }

当然我们定义serviceconnection对象

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

            binders = IBookManager.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

即可完成跨进程之间的通信。

这里关于aidl文件的生成还有一种方式。可以写IBookManager.java文件,用法类似。

IBookManager.java文件代码通自动生成编译代码一样。

 public static abstract class Stub extends android.os.Binder implements IBookManager {
        private static final String DESCRIPTOR = "com.test.IBookManager";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        
        public static IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof IBookManager))) {
                return ((IBookManager) iin);
            }
            return new 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);
                    Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = 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 IBookManager {
            private android.os.IBinder mRemote;

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

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

            public String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * 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);
            @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(Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(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);
    }

    /**
     * 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);
    public java.util.List getBookList() throws android.os.RemoteException;

    public void addBook(Book book) throws android.os.RemoteException;
}

编译运行过程中出现以下报错信息:
Binder invocation to an incorrect interface

错误解决:确保service和client两进程的IBookManager.java文件中的以下变量值保持一致。如果是自动生成模式可以,修改aidl包名一致,如果是手动创建的IBookManager.java文件可以直接修改一致的变量值。即可解决上述报错问题。

        private static final String DESCRIPTOR = "com.test.IBookManager";

代码下载地址如下所示:

服务端源代码下载地址

客户端源代码下载地址




你可能感兴趣的:(android,AIDL,IPC)