歡迎閱讀本文,你能關注本文,你知道你需要進程間通信、需要AIDL(以及Binder),那麼可以默認你對這些概念已經有了一些瞭解,你(大致) 知道它們是什麼,它們有什麼用,所以爲了節約大家的眼力和時間,在此我不復制粘貼網上氾濫的博客或者翻譯冗長的android文檔。
關於AIDL的介紹在文檔:docs/guide/developing/tools/aidl.html
關於IBinder的介紹在文檔:docs/reference/android/os/IBinder.html
以及Binder:docs/reference/android/os/Binder.html
在後文中,我將以我自己的理解向你介紹相關的概念。以我目前粗淺的經驗,應用程序使用AIDL的地方,幾乎都和Service有關,所以你也需要知道一些關於Service的知識。日後得閒我也會繼續寫一些關於Service的貼。
本文將以一個例子來和你分享使用AIDL的基礎技能,這個例子裏有:
1、一個類mAIDLActivity,繼承Activity。裏面有三個按鈕,text分別爲StartService,StopService,CallbackTest。
2、一個類mAIDLService,繼承Service。爲了充分展示ADIL的功能,它做以下工作:當用戶點擊CallbackTest按鈕時,從mAIDLActivity調用mAIDLService中的Stub 對象的一個方法invokCallBack(),而這個方法又會調用mAIDLActivity中Stub 對象的一個方法performAction(),這個方法在屏幕上顯示一個toast。沒什麼意義,只是展示一下AIDL如何使用。
3、兩個AIDL文件:forService.aidl和forActivity.aidl。對應名字,在Service和Activity中分別有對象需要用到它們定義的接口。
4、相關XML文件,略過。關於manifest中Service的語法,見docs/guide/topics/manifest /service-element.html。你也可以簡單地在<application></application>中加入
<service android:name=".mAIDLService" android:process=":remote"> </service>
開發環境爲Eclipse。
揀重要的先說,來看看aidl文件的內容:
文件:forActivity.aidl
- package com.styleflying.AIDL;
- interface ITaskCallback {
- void performAction();
package com.styleflying.AIDL; interface ITaskCallback { void performAction();
文件:forService.aidl
- package com.styleflying.AIDL;
- import com.styleflying.AIDL.forActivity;
- interface ITaskBinder {
- void registerTestCall(ITaskCallback tc);
- void invokCallBack();
- }
package com.styleflying.AIDL; import com.styleflying.AIDL.forActivity; interface ITaskBinder { void registerTestCall(ITaskCallback tc); void invokCallBack(); }
這兩個文件和Java文件放置的地方一樣,看包名。
在Eclipse中它們將被自動編譯爲forActivity.java和forService.java,它們存放在gen目錄下。爲了方便手頭無法演練的讀者,代碼貼上,不用細看。
文件forActivity.java:
- /*
- * This file is auto-generated. DO NOT MODIFY.
- * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forActivity.aidl
- */
- package com.styleflying.AIDL;
- import java.lang.String;
- import android.os.RemoteException;
- import android.os.IBinder;
- import android.os.IInterface;
- import android.os.Binder;
- import android.os.Parcel;
- public interface forActivity extends android.os.IInterface
- {
- /** Local-side IPC implementation stub class. */
- public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity
- {
- private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forActivity" ;
- /** Construct the stub at attach it to the interface. */
- public Stub()
- {
- this .attachInterface( this , DESCRIPTOR);
- }
- /**
- * Cast an IBinder object into an forActivity interface,
- * generating a proxy if needed.
- */
- public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj)
- {
- if ((obj== null )) {
- return null ;
- }
- android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!= null )&&(iin instanceof com.styleflying.AIDL.forActivity))) {
- return ((com.styleflying.AIDL.forActivity)iin);
- }
- return new com.styleflying.AIDL.forActivity.Stub.Proxy(obj);
- }
- 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_performAction:
- {
- data.enforceInterface(DESCRIPTOR);
- this .performAction();
- reply.writeNoException();
- return true ;
- }
- }
- return super .onTransact(code, data, reply, flags);
- }
- private static class Proxy implements com.styleflying.AIDL.forActivity
- {
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote)
- {
- mRemote = remote;
- }
- public android.os.IBinder asBinder()
- {
- return mRemote;
- }
- public java.lang.String getInterfaceDescriptor()
- {
- return DESCRIPTOR;
- }
- public void performAction() throws android.os.RemoteException
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0 );
- _reply.readException();
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- }
- }
- static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0 );
- }
- public void performAction() throws android.os.RemoteException;
- }
/* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forActivity.aidl */ package com.styleflying.AIDL; import java.lang.String; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; import android.os.Binder; import android.os.Parcel; public interface forActivity extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity { private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forActivity"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an forActivity interface, * generating a proxy if needed. */ public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forActivity))) { return ((com.styleflying.AIDL.forActivity)iin); } return new com.styleflying.AIDL.forActivity.Stub.Proxy(obj); } 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_performAction: { data.enforceInterface(DESCRIPTOR); this.performAction(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.styleflying.AIDL.forActivity { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } public void performAction() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0); } public void performAction() throws android.os.RemoteException; }
文件forService.java:
- /*
- * This file is auto-generated. DO NOT MODIFY.
- * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forService.aidl
- */
- package com.styleflying.AIDL;
- import java.lang.String;
- import android.os.RemoteException;
- import android.os.IBinder;
- import android.os.IInterface;
- import android.os.Binder;
- import android.os.Parcel;
- public interface forService extends android.os.IInterface
- {
- /** Local-side IPC implementation stub class. */
- public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService
- {
- private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService" ;
- /** Construct the stub at attach it to the interface. */
- public Stub()
- {
- this .attachInterface( this , DESCRIPTOR);
- }
- /**
- * Cast an IBinder object into an forService interface,
- * generating a proxy if needed.
- */
- public static com.styleflying.AIDL.forService asInterface(android.os.IBinder obj)
- {
- if ((obj== null )) {
- return null ;
- }
- android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!= null )&&(iin instanceof com.styleflying.AIDL.forService))) {
- return ((com.styleflying.AIDL.forService)iin);
- }
- return new com.styleflying.AIDL.forService.Stub.Proxy(obj);
- }
- 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_registerTestCall:
- {
- data.enforceInterface(DESCRIPTOR);
- com.styleflying.AIDL.forActivity _arg0;
- _arg0 = com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder());
- this .registerTestCall(_arg0);
- reply.writeNoException();
- return true ;
- }
- case TRANSACTION_invokCallBack:
- {
- data.enforceInterface(DESCRIPTOR);
- this .invokCallBack();
- reply.writeNoException();
- return true ;
- }
- }
- return super .onTransact(code, data, reply, flags);
- }
- private static class Proxy implements com.styleflying.AIDL.forService
- {
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote)
- {
- mRemote = remote;
- }
- public android.os.IBinder asBinder()
- {
- return mRemote;
- }
- public java.lang.String getInterfaceDescriptor()
- {
- return DESCRIPTOR;
- }
- public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- _data.writeStrongBinder((((cb!=null ))?(cb.asBinder()):( null )));
- mRemote.transact(Stub.TRANSACTION_registerTestCall, _data, _reply, 0 );
- _reply.readException();
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- }
- public void invokCallBack() throws android.os.RemoteException
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0 );
- _reply.readException();
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- }
- }
- static final int TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION + 0 );
- static final int TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION + 1 );
- }
- public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException;
- public void invokCallBack() throws android.os.RemoteException;
- }
/* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forService.aidl */ package com.styleflying.AIDL; import java.lang.String; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; import android.os.Binder; import android.os.Parcel; public interface forService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService { private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an forService interface, * generating a proxy if needed. */ public static com.styleflying.AIDL.forService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forService))) { return ((com.styleflying.AIDL.forService)iin); } return new com.styleflying.AIDL.forService.Stub.Proxy(obj); } 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_registerTestCall: { data.enforceInterface(DESCRIPTOR); com.styleflying.AIDL.forActivity _arg0; _arg0 = com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder()); this.registerTestCall(_arg0); reply.writeNoException(); return true; } case TRANSACTION_invokCallBack: { data.enforceInterface(DESCRIPTOR); this.invokCallBack(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.styleflying.AIDL.forService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null))); mRemote.transact(Stub.TRANSACTION_registerTestCall, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } public void invokCallBack() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION + 1); } public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException; public void invokCallBack() throws android.os.RemoteException; }
兩段代碼差不多,前面基本一樣,從後面看,最後跟着我們在AIDL中自定義的方法,沒有實現。兩個文件各定義一個了接口,這兩個接口分別會在 Activity和Service中使用,在那裏我們將實現自定義的方法。兩個接口中都定義了一個抽象類Stub,實現所在的接口。Stub中又有一個類 Proxy。Stub中有一個static的asInterface()方法,裏面有很多return語句,在mAIDLActivity中調用它時,它 返回一個新創建的內部類Proxy對象。
這個Stub對我們來說很有用,它繼承了Binder。Binder有什麼用呢?一個類,繼承了Binder,那麼它的對象就可以被遠程的進程使用 了(前提是遠程進程獲取了這個類的對象【對象的引用】,至於如如何獲得看下文),在本例中就是說,如果一個Service中有一個繼承了Stub的類的對 象,那麼這個對象中的方法就可以在Activity中使用,對Activity也是這樣。至於Binder的細節,網上有很多貼介紹,看不明白也不影響我 們完成這個例子。
再看mAIDLActivity.java:
- package com.styleflying.AIDL;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.Toast;
- public class mAIDLActivity extends Activity {
- private static final String TAG = "AIDLActivity" ;
- private Button btnOk;
- private Button btnCancel;
- private Button btnCallBack;
- private void Log(String str) {
- Log.d(TAG, "------ " + str + "------" );
- }
- private forActivity mCallback = new forActivity.Stub() {
- public void performAction() throws RemoteException
- {
- Toast.makeText(mAIDLActivity.this , "this toast is called from service" , 1 ).show();
- }
- };
- forService mService;
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className,
- IBinder service) {
- mService = forService.Stub.asInterface(service);
- try {
- mService.registerTestCall(mCallback);}
- catch (RemoteException e) {
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- Log("disconnect service" );
- mService = null ;
- }
- };
- @Override
- public void onCreate(Bundle icicle) {
- super .onCreate(icicle);
- setContentView(R.layout.main);
- btnOk = (Button)findViewById(R.id.btn_ok);
- btnCancel = (Button)findViewById(R.id.btn_cancel);
- btnCallBack = (Button)findViewById(R.id.btn_callback);
- btnOk.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- Bundle args = new Bundle();
- Intent intent = new Intent(mAIDLActivity. this , mAIDLService. class );
- intent.putExtras(args);
- bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- startService(intent);
- }
- });
- btnCancel.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- unbindService(mConnection);
- //stopService(intent);
- }
- });
- btnCallBack.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v)
- {
- try
- {
- mService.invokCallBack();
- } catch (RemoteException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- });
- }
- }
package com.styleflying.AIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class mAIDLActivity extends Activity { private static final String TAG = "AIDLActivity"; private Button btnOk; private Button btnCancel; private Button btnCallBack; private void Log(String str) { Log.d(TAG, "------ " + str + "------"); } private forActivity mCallback = new forActivity.Stub() { public void performAction() throws RemoteException { Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show(); } }; forService mService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = forService.Stub.asInterface(service); try { mService.registerTestCall(mCallback);} catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { Log("disconnect service"); mService = null; } }; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); btnOk = (Button)findViewById(R.id.btn_ok); btnCancel = (Button)findViewById(R.id.btn_cancel); btnCallBack = (Button)findViewById(R.id.btn_callback); btnOk.setOnClickListener(new OnClickListener() { public void onClick(View v) { Bundle args = new Bundle(); Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class); intent.putExtras(args); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); startService(intent); } }); btnCancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { unbindService(mConnection); //stopService(intent); } }); btnCallBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { mService.invokCallBack(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } }
很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);給mService賦值了,這個mService是一個 forService,而service是onServiceConnected()傳進來的參數,onServiceConnected()會在連接 Service的時候被系統調用,這個service參數的值來自哪裏呢?看mAIDLService.java:
- package com.styleflying.AIDL;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.os.RemoteCallbackList;
- import android.os.RemoteException;
- import android.util.Log;
- public class mAIDLService extends Service {
- private static final String TAG = "AIDLService" ;
- private forActivity callback;
- private void Log(String str) {
- Log.d(TAG, "------ " + str + "------" );
- }
- @Override
- public void onCreate() {
- Log("service create" );
- }
- @Override
- public void onStart(Intent intent, int startId) {
- Log("service start id=" + startId);
- }
- @Override
- public IBinder onBind(Intent t) {
- Log("service on bind" );
- return mBinder;
- }
- @Override
- public void onDestroy() {
- Log("service on destroy" );
- super .onDestroy();
- }
- @Override
- public boolean onUnbind(Intent intent) {
- Log("service on unbind" );
- return super .onUnbind(intent);
- }
- public void onRebind(Intent intent) {
- Log("service on rebind" );
- super .onRebind(intent);
- }
- private final forService.Stub mBinder = new forService.Stub() {
- @Override
- public void invokCallBack() throws RemoteException
- {
- callback.performAction();
- }
- @Override
- public void registerTestCall(forActivity cb) throws RemoteException
- {
- callback = cb;
- }
- };
- }
package com.styleflying.AIDL; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; public class mAIDLService extends Service { private static final String TAG = "AIDLService"; private forActivity callback; private void Log(String str) { Log.d(TAG, "------ " + str + "------"); } @Override public void onCreate() { Log("service create"); } @Override public void onStart(Intent intent, int startId) { Log("service start id=" + startId); } @Override public IBinder onBind(Intent t) { Log("service on bind"); return mBinder; } @Override public void onDestroy() { Log("service on destroy"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log("service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { Log("service on rebind"); super.onRebind(intent); } private final forService.Stub mBinder = new forService.Stub() { @Override public void invokCallBack() throws RemoteException { callback.performAction(); } @Override public void registerTestCall(forActivity cb) throws RemoteException { callback = cb; } }; }
注意onBind(),它的返回類型爲IBinder,返回了一個mBinder,看看mBinder的定義:
private final forService.Stub mBinder = new forService.Stub() {
@Override
public void invokCallBack() throws RemoteException
{
callback.performAction();
}
@Override
public void registerTestCall(forActivity cb) throws RemoteException
{
callback = cb;
}
};
它是實現了我們在AIDL中定義的方法,這個mBinder最終返回給了mAIDLActivity中的mService,於是在 mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一個類似mBinder的對象,看看定義:
private forActivity mCallback = new forActivity.Stub()
{
public void performAction() throws RemoteException
{
Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
}
};
我們要在界面上顯示一個toast,就是在這裏實現的。這個對象,在mConnection的onServiceConnected()被調用時, 通過調用mService(也就是遠程的mAIDLService中的mBinder)的registerTestCall(),傳遞給了 mAIDLService,於是在mAIDLService中可以調用performAction()了。
很囉嗦,只爲了能把這個細節說清楚。請大家認真看,我儘量避免錯別字、混亂的大小寫和邏輯不清的語法,相信你會看明白。是不是很簡單?再囉嗦一下,做一個大致總結,我們使用AIDL是要做什麼呢:
讓Acticity(或者說一個進程/一個類?)和Service(或者說遠端進程/遠端類/對象?)獲取對方的一個Stub對象,這個對象在定義 時實現了我們在AIDL中定義的方法,於是這些遠程對象中的方法可以在本地使用了。如果這種使用(通信)是單向的,比如只是Activity需要通知 Service做什麼,那麼只要Service中有一個Stub對象,並且傳給Acticity就夠了。
至於如何獲得遠程的Stub,參看上面的代碼,看mConnection、registerTestCall、onRebind,它們展示了一種方法。
另外,有時候我們可能在一個類中有多個Stub對象,它們都要給遠程交互的類的實例,這個時候可以考慮使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。
歡迎閱讀、收藏本文。例子隨手寫的,功能只在演示AIDL的使用。您可以轉載本文,但請勿盲目亂貼。不是我小氣,我不權威,我怕它被貼到氾濫,以訛傳訛,害了人。