Binder探索の適用(上)
7567 ワード
本明細書では、クライアントActivity、サービス側リモートサービス、aidl、およびJavaインタフェースファイルを含むdemoコードを主に羅列し、クライアントおよびサービス側アプリケーションbinderインタラクションプロセスを記述する.
このコードの例を簡単に説明します.BookManagerServiceというリモート・サービスがあります.Bookオブジェクトを保存するためのlistを持ち、listのgetメソッドとaddメソッドを外部に提供します.クライアントActivityは、サービスをバインドし、そのインタフェースにアクセスします.クライアントActivityは、onCreate時にBookManagerServiceをバインドし、接続に成功するとIBookManagerオブジェクトを生成し、BookManagerServiceの外部インタフェースにアクセスできます. BookManagerServiceにはremoteが設定されており、別のプロセスで実行されるリモート・サービスであり、onCreate時にリストに2行のデータをロードした後、onBindメソッドでserviceBinderオブジェクトを返します.
まずaidlファイルです.
次にクライアントActivity:
最後に、サービス側BookManagerService:
プログラムは異なるプロセスで1つのサービスをバインドするもので、最初に実行される大まかなプロセスは次のとおりです.クライアントActivityプロセスは、AMSがシステムサービスプロセスで実行されるため、BookManagerServiceサービスをバインドする要求をAMSに送信する(これもbinder要求である). AMSルーチンチェックは、まずBookManagerServiceが登録されているか、どのアプリが登録されているか(これらの情報はappインストール時にmanifestを解析して取得されたもの)をチェックし、次にBookManagerServiceを起動するプロセスが存在するかをチェックします.BookManagerServiceはremoteを設定しているため、この時点でプロセスは存在しません.そこで、まずService情報を保存し、リクエストをバインドした後、新しいプロセスを作成します. 新しいプロセスが開始されると、AMSに準備が完了したことを通知し、AMSは先ほど保存したサービス情報を新しいプロセスに送信してサービス(oncreateなど)を開始し、サービスが開始された後にAMSに通知します. AMSは、バインドされた要求をBookManagerServiceに再送信し、BookManagerServiceはonbindを呼び出し、AMSにbinderオブジェクトを返します. AMSはbinderオブジェクトをクライアントActivity(onServiceConnected呼び出し) に返す.
これらのプロセスはandroidによってブロックされています.アプリケーションでは、クライアントActivityのonServiceConnectedが返すBinderProxyオブジェクトと、サービス側BookManagerServiceのonBindが返すBinderオブジェクトの2つのオブジェクトに注目する必要があります.しかし、アプリケーションではStubとProxyが見られ、StubはBinderを継承し、ProxyはBidnerProxyのパッケージクラスであり、BinderProxyもBidnerもIBinderインタフェースを実現し、IBinderで受信することができる. IBookManagerインタフェースはgetBookListとaddBookメソッドを定義し、Iinterfaceインタフェースも継承し、asBinderメソッドが複数あり、次のStubとProxyはIBookManagerインタフェースを実現しています. StubクラスはBidnerクラスだけでなくIBookManagerインタフェースも継承し、サービス側BookManagerServiceのserviceBinderはStubクラスを継承し、getBookListとaddBookメソッド(asBinderインタフェースはStubクラスで実現)を実現し、serviceBinderのオブジェクトmBinderはAMSに戻される. クライアントActivityのonServiceConnectedは、IBookManagerを介してBinderProxyに戻ります.Stub.asInterfaceメソッドはProxyオブジェクトにパッケージされており、Proxy実装のgetBookListメソッドとaddBookメソッドを呼び出すことができ、ProxyはasBinderインタフェースも実装している.
IBookManagerインタフェース:
Stubクラス:
Proxyクラス:
次の文章ではbinder通信プロセスについて説明する.
このコードの例を簡単に説明します.BookManagerServiceというリモート・サービスがあります.Bookオブジェクトを保存するためのlistを持ち、listのgetメソッドとaddメソッドを外部に提供します.クライアントActivityは、サービスをバインドし、そのインタフェースにアクセスします.
まずaidlファイルです.
//IBookManager.aidl
interface IBookManager {
List getBookList();
void addBook(in Book book);
}
//Book.aidl
parcelable Book;
次にクライアントActivity:
private IBookManager mRemoteBookManager;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
mRemoteBookManager = bookManager;
try {
//mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient, 0);
List list = bookManager.getBookList();
Book newBook = new Book(3, "Android ");
bookManager.addBook(newBook);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_manager);
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
最後に、サービス側BookManagerService:
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
private Binder mBinder = new serviceBinder();
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "Android"));
mBookList.add(new Book(2, "Ios"));
}
public class serviceBinder extends IBookManager.Stub{
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}@Override
public List getBookList() throws RemoteException {
return mBookList;
}
}
プログラムは異なるプロセスで1つのサービスをバインドするもので、最初に実行される大まかなプロセスは次のとおりです.
これらのプロセスはandroidによってブロックされています.アプリケーションでは、クライアントActivityのonServiceConnectedが返すBinderProxyオブジェクトと、サービス側BookManagerServiceのonBindが返すBinderオブジェクトの2つのオブジェクトに注目する必要があります.しかし、アプリケーションではStubとProxyが見られ、StubはBinderを継承し、ProxyはBidnerProxyのパッケージクラスであり、BinderProxyもBidnerもIBinderインタフェースを実現し、IBinderで受信することができる.
IBookManagerインタフェース:
public interface IBookManager extends IInterface {
static final String DESCRIPTOR = "com.example.testbinder.IBookManager";
static final int TRANSACTION_getBookList = (IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (IBinder.FIRST_CALL_TRANSACTION + 1);
public List getBookList()throws RemoteException;
public void addBook(Book book)throws RemoteException;
}
Stubクラス:
public static abstract class Stub extends Binder implements IBookManager {
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static IBookManager asInterface(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 IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
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);
}
@Override
public List getBookList() throws RemoteException {
//
return null;
}
@Override
public void addBook(Book book) throws RemoteException {
//
}
}
Proxyクラス:
private static class Proxy implements IBookManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public List getBookList()throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
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 RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = 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();
}
}
}
次の文章ではbinder通信プロセスについて説明する.