再看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的使用。您可以转载本文,但请勿盲目乱贴。不是我小气,我不权威,我怕它被贴到泛滥,以讹传讹,害了人。