天天看點

linux程序間通訊 aidl,Android程序間通信:使用AIDL

再看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的使用。您可以轉載本文,但請勿盲目亂貼。不是我小氣,我不權威,我怕它被貼到泛濫,以訛傳訛,害了人。

linux程式間通訊 aidl,Android程式間通信:使用AIDL