再看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();
}
}
});
}
}
很短,相信大家很容易看明白。注意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;
}
};
}
注意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的使用。您可以轉載本文,但請勿盲目亂貼。不是我小氣,我不權威,我怕它被貼到泛濫,以訛傳訛,害了人。