Android AIDL的用法

來源:互聯網
上載者:User

標籤:except   server   分享圖片   開放   thread   init   roi   ble   使用   

一、什麼是AIDL服務   一般建立的服務並不能被其他的應用程式訪問。為了使其他的應用程式也可以訪問本應用程式提供的服務,Android系統採用了遠端程序呼叫(Remote Procedure Call,RPC)方式來實現。與很多其他的基於RPC的解決方案一樣,Android使用一種介面定義語言(Interface Definition Language,IDL)來公開服務的介面。因此,可以將這種可以跨進程訪問的服務稱為AIDL(Android Interface Definition Language)服務。 二、AIDL基本文法 

  AIDL使用簡單的文法來聲明介面,描述其方法以及方法的參數和傳回值。這些參數和傳回值可以是任何類型,甚至是其他AIDL產生的介面。
  其中對於Java程式設計語言的基礎資料型別 (Elementary Data Type) (int, long, char, boolean,String,CharSequence)集合介面類型List和Map,不需要import 語句。
  而如果需要在AIDL中使用其他AIDL介面類型,需要import,即使是在相同包結構下。AIDL允許傳遞實現Parcelable介面的類,需要import
  需要特別注意的是,對於非基礎資料型別 (Elementary Data Type),也不是String和CharSequence類型的,需要有方向指示,包括in、out和inout,in表示由用戶端設定,out表示由服務端設定,inout是兩者均可設定。

  AIDL只支援介面方法,不能公開static變數。 

三、android應用程式層使用AIDL3.1、簡要步驟  1、在Eclipse Android工程的Java包目錄中建立一個副檔名為A.aidl的檔案,並寫下需要的介面。如果aidl檔案的內容是正確的,ADT會在gen目錄下自動產生一個A.Java介面檔案。
  2、建立一個服務類(Service的子類)。並在建立的服務類中建立一個內部類,實現由aidl檔案產生的Java介面。
  3、在服務類的onBind方法返回時,將實現aidl介面的內部類對象返回出去。
  4、在AndroidManifest.xml檔案中配置AIDL服務,尤其要注意的是,<action>標籤中android:name的屬性值就是用戶端要引用該服務的ID,也就是Intent類的參數值。3.2、具體操作3.2.1、建立檔案IMyService.aidl: 

        
  檔案內容:

  1. package du.pack;  
  2. interface IMyService{  
  3.     //只有一個介面  
  4.     String getValue();  
  5. }   
3.2.2、建立服務類及實現內部類
  1. public class MyService extends Service {  
  2.   
  3.     @Override  
  4.     public IBinder onBind(Intent arg0) {  
  5.         // 把內部類的對象返回給用戶端使用  
  6.         return new MyServiceImpl();  
  7.     }  
  8.   
  9.     // 建立一個繼承自IMyService.Stub的內部類  
  10.     public class MyServiceImpl extends IMyService.Stub {  
  11.   
  12.         // 必須實現AIDL檔案中的介面  
  13.         public String getValue() throws RemoteException {  
  14.             return null;  
  15.         }  
  16.     }  
  17. }  
  注意,我們寫的service中,onBind方法必須返回MyServiceImpl類的對象執行個體,否則用戶端無法獲得服務物件。
3.2.3、在AndroidManifest.xml檔案中配置MyService類
  1. <service android:name=".MyService" >  
  2.     <intent-filter>  
  3.         <action android:name="du.pack.IMyService" />  
  4.     </intent-filter>  
  5. </service>  

  上面的"du.pack.IMyService"是用戶端用於訪問AIDL服務的ID。 

4、本地用戶端的使用方法     4.1、建立一個Eclipse Android工程,並將剛才遠程服務端自動產生的gen目錄下面的IMyService.java檔案連同包目錄一起複製到用戶端工程的src目錄中。        

 4.2、調用AIDL服務首先要綁定服務,然後才能獲得服務物件。
  1. public class AidlClientTestActivity extends Activity {  
  2.     // 遠程服務端的對象  
  3.     IMyService mIMyService;  
  4.     private ServiceConnection mConnection = new ServiceConnection() {  
  5.   
  6.         public void onServiceConnected(ComponentName name, IBinder service) {  
  7.             // 綁定成功,得到遠程服務端的對象,目標完成!!!  
  8.             mIMyService = IMyService.Stub.asInterface(service);  
  9.         }  
  10.   
  11.         public void onServiceDisconnected(ComponentName name) {  
  12.             // 解除綁定  
  13.             mIMyService = null;  
  14.         }  
  15.   
  16.     };  
  17.   
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.main);  
  22.   
  23.         // 綁定遠程服務端服務  
  24.         Intent serviceIntent = new Intent("du.pack.IMyService");  
  25.         bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);  
  26.     }  
  27. }  
5、用法小結   回顧一下整個調用的過程:
  服務端方面:將需要開放的介面抽象到aidl檔案中,然後在自己的內部類中對介面進行實現,並在自己被綁定的時候把內部類對象返回給用戶端。用戶端方面:當我們需要遠程某個Service時,就像在綁定本地的Service一樣去bindService,然後在綁定成功的回呼函數中(也就是onServiceConnected方法)得到一個Ibinder對象(比如Service),這時調用IMyService.Stub.asInterface(service)這樣的語句,就可以得到服務端開放的interface介面對象,此時用戶端可以直接調用這個對象的方法,猶如直接調用遠端Service對象一般。

 

四、Framework中使用AIDL

         Framework中使用AIDL我們通過ITelephonyRegistry這個SystemService進行分析。該服務的主要作用就是對通話相關的事件進行監聽,我們重心放在AIDL的實現結構上,不去關注ITelephonyRegistry具體的實現。

1、AIDL檔案相關

        先來看一下這個服務的AIDL檔案: 

 
  1. @ITelephonyRegistry.aidl  
  2. interface ITelephonyRegistry {  
  3.     void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);  
  4.     void notifyCallState(int state, String incomingNumber);  
  5.     void notifyServiceState(in ServiceState state);  
  6.     void notifySignalStrength(in SignalStrength signalStrength);  
  7.     void notifyMessageWaitingChanged(boolean mwi);  
  8. }  

        再來看這個服務的真正實現: 

 
  1. @TelephonyRegistry.java  
  2. class TelephonyRegistry extends ITelephonyRegistry.Stub {  
  3.     TelephonyRegistry(Context context) {  
  4.         ......  
  5.     }  
  6.     void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow){  
  7.         ......  
  8.     }  
  9.     void notifyCallState(int state, String incomingNumber){  
  10.         ......  
  11.     }  
  12.     void notifyServiceState(in ServiceState state){  
  13.         ......  
  14.     }  
  15.     void notifySignalStrength(in SignalStrength signalStrength){  
  16.         ......  
  17.     }  
  18.     void notifyMessageWaitingChanged(boolean mwi){  
  19.         ......  
  20.     }  
  21. }  

        上面的兩個檔案是這個服務的核心部分,aidl檔案規定了這個服務的功能,而java檔案是對功能的具體實現。但是,此時的TelephonyRegistry並沒有繼承Service的類,也就是說,當前他並不具備作為一個Service的資格。那麼他是如何變成一個服務的呢?

     2、服務的註冊過程

         在SystemService中可以找到答案。

  1. @SystemServer.java  
  2. class ServerThread extends Thread {  
  3.     @Override  
  4.     public void run() {  
  5.         try {  
  6.             telephonyRegistry = new TelephonyRegistry(context);  
  7.             ServiceManager.addService("telephony.registry", telephonyRegistry);  
  8.         }  
  9.     }  
  10. }  

        我們看到,在這一步中,把telephonyRegistry對象(也就是ITelephonyRegistry.Stub的子類對象)作為一個Service註冊給了ServiceManager。並且註冊的名字是“telephony.registry”
        有了這一步,TelephonyRegistry就可以作為服務提供者向用戶端開放了。也就是說,有了這一步,TelephonyRegistry才算上是一個真正的Service,可以接受用戶端的串連申請。

        那麼接下來,我們怎麼得到這個Service呢?

3、如何得到註冊的服務

        既然通過ServiceManager註冊了服務,我們就需要再次通過ServiceManager得到它的服務物件。

  1. private ITelephonyRegistry sRegistry;  
  2. sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));  

        通過這樣的方法,我們就得到了ITelephonyRegistry.aidl的對象sRegistry。

4、流程總結

         回顧一下這種AIDL服務的架構:通過繼承ITelephonyRegistry.Stub父類去實現AIDL中規定的介面,然後把TelephonyRegistry作為ServiceManager註冊給SystemService。用戶端可以通過ServiceManager得到TelephonyRegistry的對象,然後就可以去調用AIDL中定義的介面了。

 

Android AIDL的用法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.