1. 程式人生 > >Android中使用AIDL時的跨程序回撥—Server回撥Client

Android中使用AIDL時的跨程序回撥—Server回撥Client

首先建立在server端建立兩個aidl檔案

ITaskCallback.aidl 用於存放要回調client端的方法

  1. package com.cmcc.demo.server;   
  2. interface ITaskCallback {   
  3.     void actionPerformed(int actionId);  
  4. }   

ITaskBinder.aidl 用於存放供給client端呼叫的方法

  1. package com.cmcc.demo.server;   
  2. import com.cmcc.demo.server.ITaskCallback;   
  3. interface ITaskBinder {   
  4.     boolean isTaskRunning();   
  5.     void stopRunningTask();   
  6.     void registerCallback(ITaskCallback cb);   
  7.     void unregisterCallback(ITaskCallback cb);   
  8. }  

接著建立服務端,要實現回撥,需要新建RemoteCallbackList物件(一個儲存回撥物件的列表),通過類似傳送廣播的形式來實現回撥

MyService.java

  1. package com.cmcc.demo.server;   
  2. import com.cmcc.demo.server.ITaskBinder;  
  3. import com.cmcc.demo.server.ITaskCallback;  
  4. import android.app.Service;   
  5. import android.content.Intent;   
  6. import android.os.IBinder;   
  7. import android.os.RemoteCallbackList;   
  8. import android.os.RemoteException;   
  9. import android.util.Log;   
  10. publicclass MyService extends Service {   
  11.     privatestaticfinal
     String TAG = "aidltest";  
  12.     @Override
  13.     publicvoid onCreate() {   
  14.         printf("service create");   
  15.     }  
  16.     @Override
  17.     publicvoid onStart(Intent intent, int startId) {  
  18.         printf("service start id=" + startId);  
  19.         callback(startId);   
  20.     }  
  21.     @Override
  22.     public IBinder onBind(Intent t) {  
  23.         printf("service on bind");  
  24.         return mBinder;   
  25.     }  
  26.     @Override
  27.     publicvoid onDestroy() {   
  28.         printf("service on destroy");   
  29.         super.onDestroy();   
  30.     }  
  31.     @Override
  32.     publicboolean onUnbind(Intent intent) {   
  33.         printf("service on unbind");  
  34.         returnsuper.onUnbind(intent);   
  35.     }  
  36.     publicvoid onRebind(Intent intent) {   
  37.         printf("service on rebind");  
  38.         super.onRebind(intent);   
  39.     }  
  40.     privatevoid printf(String str) {   
  41.         Log.v(TAG, "###################------ " + str + "------");   
  42.     }  
  43.     void callback(int val) {   
  44.         finalint N = mCallbacks.beginBroadcast();  
  45.         for (int i=0; i<N; i++) {   
  46.             try {  
  47.                 mCallbacks.getBroadcastItem(i).actionPerformed(val);   
  48.             }  
  49.             catch (RemoteException e) {   
  50.                 // The RemoteCallbackList will take care of removing 
  51.                 // the dead object for us.   
  52.             }  
  53.         }  
  54.         mCallbacks.finishBroadcast();  
  55.     }  
  56.     privatefinal ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {  
  57.         publicvoid stopRunningTask() {  
  58.         }  
  59.         publicboolean isTaskRunning() {   
  60.             returnfalse;   
  61.         }   
  62.         publicvoid registerCallback(ITaskCallback cb) {   
  63.             if (cb != null) {   
  64.                 mCallbacks.register(cb);  
  65.             }  
  66.         }  
  67.         publicvoid unregisterCallback(ITaskCallback cb) {  
  68.             if(cb != null) {  
  69.                 mCallbacks.unregister(cb);  
  70.             }  
  71.         }  
  72.     };   
  73.     final RemoteCallbackList <ITaskCallback>mCallbacks = new RemoteCallbackList <ITaskCallback>();  
  74. }   

最後建立客戶端,使用aidl,實現回撥方法。

MyActivity.java

  1. package com.cmcc.demo;   
  2. import android.app.Activity;   
  3. import android.content.ComponentName;   
  4. import android.content.Intent;   
  5. import android.content.ServiceConnection;   
  6. import android.os.Bundle;   
  7. import android.os.IBinder;   
  8. import android.os.RemoteException;   
  9. import android.util.Log;   
  10. import android.view.View;   
  11. import android.view.View.OnClickListener;   
  12. import android.widget.Button;   
  13. import com.cmcc.demo.server.*;  
  14. publicclass MyActivity extends Activity {   
  15.     privatestaticfinal String TAG = "aidltest";  
  16.     private Button btnOk;   
  17.     private Button btnCancel;  
  18. @Override
  19. publicvoid onCreate(Bundle icicle) {   
  20.     super.onCreate(icicle);   
  21.     setContentView(R.layout.test_service);   
  22.     btnOk = (Button)findViewById(R.id.btn_ok);  
  23.     btnCancel = (Button)findViewById(R.id.btn_cancel);   
  24.     btnOk.setText("Start Service");   
  25.     btnCancel.setText("Stop Service");   
  26.     btnCancel.setEnabled(false);  
  27.     btnOk.setOnClickListener(new OnClickListener() {  
  28.             publicvoid onClick(View v) {  
  29.                 onOkClick();  
  30.             }  
  31.         });   
  32.     btnCancel.setOnClickListener(new OnClickListener() {  
  33.             publicvoid onClick(View v) {  
  34.                 onCancelClick();  
  35.             }  
  36.         });  
  37.     }   
  38.     void onOkClick() {  
  39.         printf("send intent to start");   
  40.         Bundle args = new Bundle();  
  41.         Intent intent = new Intent("com.cmcc.demo.IMyService");  
  42.         intent.putExtras(args);  
  43.         startService(intent);  
  44.         //bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  45.         btnCancel.setEnabled(true);  
  46.     }   
  47.     void onCancelClick() {   
  48.         printf("send intent to stop");  
  49.         //unbindService(mConnection);
  50.         Intent intent = new Intent("com.cmcc.demo.IMyService");  
  51.         stopService(intent);   
  52.         btnCancel.setEnabled(false);  
  53.     }   
  54.     privatevoid printf(String str) {   
  55.         Log.v(TAG, "###################------ " + str + "------");   
  56.     }  
  57.     ITaskBinder mService;   
  58.     private ServiceConnection mConnection = new ServiceConnection() {   
  59.         publicvoid onServiceConnected(ComponentName className, IBinder service) {  
  60.             mService = ITaskBinder.Stub.asInterface(service);   
  61.             try {   
  62.                 mService.registerCallback(mCallback);  
  63.             } catch (RemoteException e) {  
  64.             }  
  65.         }  
  66.         publicvoid onServiceDisconnected(ComponentName className) {   
  67.             mService = null;  
  68.         }   
  69.     };   
  70.     private ITaskCallback mCallback = new ITaskCallback.Stub() {  
  71.         publicvoid actionPerformed(int id) {   
  72.             printf("callback id=" + id);  
  73.         }   
  74.     };   
  75. }   

總結一下aidl的使用

AIDL的建立方法: AIDL語法很簡單,可以用來宣告一個帶一個或多個方法的介面,也可以傳遞引數和返回值。由於遠端呼叫的需要, 這些引數和返回值並不是任何型別.下面是些AIDL支援的資料型別:1. 不需要import宣告的簡單Java程式語言型別(int,boolean等)2. String, CharSequence不需要特殊宣告3. List, Map和Parcelables型別, 這些型別內所包含的資料成員也只能是簡單資料型別, String等其他比支援的型別.((另外: 我沒嘗試Parcelables, 在Eclipse+ADT下編譯不過, 或許以後會有所支援).下面是AIDL語法:// 檔名: SomeClass.aidl // 檔案可以有註釋, 跟java的一樣 // 在package以前的註釋, 將會被忽略. // 函式和變數以前的註釋, 都會被加入到生產java程式碼中. package com.cmcc.demo;// import 引入語句 import com.cmcc.demo.ITaskCallback;interface ITaskBinder {//函式跟java一樣, 可以有0到多個引數 ,可以有一個返回值 boolean isTaskRunning();void stopRunningTask(); //引數可以是另外的一個aidl定義的介面 void registerCallback(ITaskCallback cb);void unregisterCallback(ITaskCallback cb);//引數可以是String, 可以用in表入輸入型別, out表示輸出型別.int getCustomerList(in String branch, out String customerList);}

實現介面時有幾個原則: .丟擲的異常不要返回給呼叫者. 跨程序拋異常處理是不可取的..IPC呼叫是同步的如果你知道一個IPC服務需要超過幾毫秒的時間才能完成地話,你應該避免在Activity的主執行緒中呼叫。 也就是IPC呼叫會掛起應用程式導致介面失去響應. 這種情況應該考慮單起一個執行緒來處理..不能在AIDL介面中宣告靜態屬性。IPC的呼叫步驟: 1. 宣告一個介面型別的變數,該介面型別在.aidl檔案中定義。2. 實現ServiceConnection。3. 呼叫ApplicationContext.bindService(),並在ServiceConnection實現中進行傳遞.4. 在ServiceConnection.onServiceConnected()實現中,你會接收一個IBinder例項(被呼叫的Service). 呼叫 YourInterfaceName.Stub.asInterface((IBinder)service)將引數轉換為YourInterface型別。5. 呼叫介面中定義的方法。 你總要檢測到DeadObjectException異常,該異常在連線斷開時被丟擲。它只會被遠端方法丟擲。6. 斷開連線,呼叫介面例項中的ApplicationContext.unbindService()