您的位置:首页 > 移动开发 > Android开发

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

2018-01-24 18:00 260 查看
通常我们熟悉同一进程的通信方式,关于跨进程之间的通信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<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.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<Book> 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<Book> books = new ArrayList<>();
private final IBookManager.Stub binder = new IBookManager.Stub() {
@Override
public List<Book> 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<Book> 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<Book> _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<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<Book> _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<Book> 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";


代码下载地址如下所示:

服务端源代码下载地址

客户端源代码下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: