服务端 IBinder类的创建
Binder是Android一个类实现了Ibinder接口,Binder也是Android跨进程通信的一种方式,Binder是连接Android各种manager和ManagerService的桥梁,Binder还是服务端和客户端通信的媒介,
bindService时,服务端会返回一个包含了服务端一些方法的Binder对象,通过该对象我们可以调用服务端的服务。
我们通常使用AIDL来创建自己的Binder类,AIDL是系统为我们提供的快速创建Binder接口的工具,创建一个实现了parcelable的类,创建一个aidl文件,将需要使用到的类导入到aidl文件中尽管在头一个包下,sdk会自动生成一个Binder接口。
该接口继承自IInterface,内部类Stub 和Stub的内部类Proxy 是该接口的核心实现。
首先,来看看sdk根据aidl文件自动生成的Binder接口的内容.
首先创建三个文件Book.java ,Book.aidl, IBookManager
package com.example.learnipc.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable{
public int bookId;
public String bookString;
public Book(int bookId, String bookString) {
super();
this.bookId = bookId;
this.bookString = bookString;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookString);
}
//反序列化
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book[] newArray(int size) {
return new Book[size];
}
//反序列化
@Override
public Book createFromParcel(Parcel source) {
return new Book(source);
}
};
private Book (Parcel in){
bookId = in.readInt();
bookString = in.readString();
}
}
Book.aidl是Book类在aidl中的声明,需要在进程间传输的类都要进行声明,所以都要创建类对应的aidl文件
package com.example.learnipc.aidl;
parcelable Book;
IBookManager.aidl,定义一个接口,该接口用于IPC的类服务端进行实现,注意需要导入需要使用的类,如Book
package com.example.learnipc.aidl;
import com.example.learnipc.aidl.Book;
interface IBookManager{
List<Book> getBookList();
void addBook(in Book book);
}
写完上面的三个文件之后,在gen目录下,自动生成的IBookManager.java
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\houson_record\\learnIPC\\src\\com\\example\\learnipc\\aidl\\IBookManager.aidl
*/
package com.example.learnipc.aidl;
//继承自IIterface,
public interface IBookManager extends android.os.IInterface {
public java.util.List<com.example.learnipc.aidl.Book> getBookList() throws android.os.RemoteException;
public void addBook(com.example.learnipc.aidl.Book book) throws android.os.RemoteException;
/** Local-side IPC implementation stub class. */
//IBookManager 的核心类Stub,继承Binder实现了外部类IBookManager接口,即上面两个方法,Binder也是继承IInterface
//Stub是抽象类具体实现由子类去实现,一般在service中创建自己的Binder类时实现
public static abstract class Stub extends android.os.Binder implements com.example.learnipc.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.example.learnipc.aidl.IBookManager";//Binder 的唯一标识
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);//标识IBookManager接口的方法id
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.learnipc.aidl.IBookManager
* interface, generating a proxy if needed.
*/
//这里将binder转为我们自己定义的IBoolManager类型,客户端请求时使用这种类型请求的
public static com.example.learnipc.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//当在同一进程下时返回这个
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.learnipc.aidl.IBookManager))) {
return ((com.example.learnipc.aidl.IBookManager) iin);
}
//在不同进程下返回Stub的内部累Proxy,会走transact流程
return new com.example.learnipc.aidl.IBookManager.Stub.Proxy(obj);
}
//直接返回BInder自己
@Override
public android.os.IBinder asBinder() {
return this;
}
//当客户端跨进程调用服务端时,该方法被调用.根据客户端的请求的方法id来调用不同服务端方法
//返回false,客户端会调用失败,可以做权限验证
//该方法运行在服务端的Binder线程池中
@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);//输入的data中取出参数
java.util.List<com.example.learnipc.aidl.Book> _result = this.getBookList();//执行服务端方法
reply.writeNoException();//将返回值写入reply
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.example.learnipc.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.learnipc.aidl.Book.CREATOR.createFromParcel(data);//反序列化
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//Stub的内部类 用于远程调用 ,实现BookManager接口
//执行transact()
private static class Proxy implements com.example.learnipc.aidl.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.example.learnipc.aidl.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.example.learnipc.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.example.learnipc.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(com.example.learnipc.aidl.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();
}
}
}
}
}
需要注意:
1.IBookManager是在服务端被实现的,运行在服务端的Binder线程池内,所以不需要在方法内部创建线程,被客户端调用客户端是阻塞的,如果服务端的方法耗时,客户端不能在UI线程下调用服务.
2.使用aidl使系统生成的IBookManager只是方便我们定义Binder类(即内部的Stub类),我们可以手动定义Binder类.
Binder的工作机制如下图
对服务端的binder死亡进行监听
binder死亡如果没有监听,客户端调用就会失败,Binder提供了linkTODeath()和unlinkToDeath()方法
1.需要一个IBinder.DeathRecipient对象,实现器binderDied()方法,在该方法中重新绑定到service
2.在客户端绑定成功后使用服务端返回的binder.linkToDeath(DeathRecipient对象,flag);