Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android應用開發入門(五十)AIDL接口通過綁定Service在進程間傳遞系統基本類型數據

Android應用開發入門(五十)AIDL接口通過綁定Service在進程間傳遞系統基本類型數據

編輯:Android開發實例

前言

  前面講解了Service的一些基本內容。但是對於綁定服務傳遞數據,只局限於本地服務,無法使用服務進行跨進程間的交互。如果需要用到跨進程交互的話,需要用到一個新的技術-AIDL, 本文就針對AIDL如何傳遞內置類型數據進行講解。對於Service不熟悉的朋友,可以先看看之前的文章:http://www.fengfly.com/plus/view-214081-1.html 、http://www.fengfly.com/plus/view-214082-1.html、http://www.fengfly.com/plus/view-214084-1.html。

  本文內容如下:

  1. 什麼是ADIL?
  2. 如何定義AIDL?
  3. ADIL做了什麼?
  4. 使用ADIL傳遞系統基本數據

 

什麼是AIDL?

  先來回顧一下,Android在本地的Service中如何與其它組件進行交互的,首先Service必須實現其onBind()方法,然後在onBind方法傳遞一個IBinder接口的實現,而在其它組件中使用bindService()綁定一個服務,再通過其中的參數ServiceConnection對象獲取到Service中定義的IBinder接口的實現。那麼與Service進行數據交互,其實就是傳遞一個IBinder,通過這個IBinder進行交互。

  而現在就碰到一個問題,在同一個進程中,是可以獲取到這個Service類的,也就可以獲得這個Service中定義的IBinder,但是如果在不同的應用中,即遠程服務,如何獲取IBinder呢?僅僅是在不同的應用定義一相同的類是沒有用的,所以Android為我們提供了AIDL語言,它需要先定義一個遠程調用接口,然後為該接口提供一個實現類,通過共享這個遠程調用接口來達到進程間數據交互的目的,而這個接口的代碼是有很多共性的,並且編寫過程相當枯燥乏味,所以Android開發者為我們提供了ADIL來簡化通訊接口的開發。

  AIDL(Android Interface Definition Language)是Android遠程調用接口的定義語言。它有它自己的一套語法規范,但是和Java類似,這並不難理解,詳細的這個會後面介紹。而當你定義好一個AIDL接口之後,你會發現在gen/目錄下,多出一個與定義的AIDL包名相同,文件名相同的一個Java類,這個類是編譯器根據定義的AIDL接口自動生成的代碼,觀察之後發現其實它也是繼承了Binder類(Binder是IBinder的實現類),所以它可以通過ServiceConnection進行數據傳遞。Service只需要暴露這個AIDL接口給客戶端,讓客戶端也定義它,這樣兩個應用進程就可以通訊了。

如何定義AIDL?

  AIDL的語法與Java接口的語法非常相似,但是存在一些差異:

  1. AIDL定義接口的源代碼後綴必須以.aidl結尾。
  2. AIDL一樣要指定AIDL接口的包信息package *。
  3. AIDL接口無需指定public、private、protected等作用域,可以理解為就是public。
  4. AIDL默認情況下只能傳遞基本類型、String、List、Map、CharSequence。
  5. 如果需要傳遞其他類型的對象,需要import對象的包名,並需要對對象進行特殊處理(之後會介紹)。

  例如:

  1. package com.example.aidlservicedemo.domain;  
  2.  
  3. interface IDog{  
  4.     String getName();  
  5.     int getAge();      
  6. }  

ADIL做了什麼?

  當你聲明完一個AIDL接口的時候,你會發現在項目的gen/目錄下,對應包中存在一個同名的Java文件,這個文件是Android幫我們自動生成的,裡面有很多代碼,這裡只講一下需要注意的。查看自動生成的這個Java文件代碼,會發現它定義了一個名為Stub的靜態抽象類,這個Stub繼承了Binder,實現了AIDL接口,當然其中也實現了AIDL接口的兩個方法,粗略看一下會發現它對數據做了一個序列化和反序列化的操作。正因為AIDL對數據進行了序列化和反序列化,所以才可以在進程間傳遞。

  

使用ADIL傳遞系統基本數據

  定義好AIDL接口之後,就需要通過服務把接口暴露給客戶端,這裡Service.onBind()傳遞的就是這個Stub靜態抽象類的實現類,其他沒什麼特別的。

  下面通過一個Demo來演示ADIL如何傳遞數據的,在示例中,給出兩個應用,分別實現Server與調用客戶端,使用的AIDL接口就是上面給出的AIDL示例代碼,這裡不再重復定義。

  AIDL服務:BaseTypeService.java

  1. package com.example.aidlservicedemo;  
  2.  
  3. import java.util.Random;  
  4.  
  5. import com.example.aidlservicedemo.domain.IDog.Stub;  
  6.  
  7. import android.app.Service;  
  8. import android.content.Intent;  
  9. import android.os.IBinder;  
  10. import android.os.RemoteException;  
  11. import android.util.Log;  
  12.  
  13. public class BaseTypeService extends Service {  
  14.     private final String TAG="main";  
  15.     private DogBinder binder=null;  
  16.     private String[] names=new String[]{"小白","旺財","小黑"};  
  17.     private int[] ages=new int[]{1,2,3};  
  18.       
  19.     /**  
  20.      * Stub的實現類,Stub內部實現了Binder  
  21.      * 內部實現AIDL定義的方法  
  22.      */ 
  23.     public class DogBinder extends Stub{  
  24.  
  25.         @Override 
  26.         public String getName() throws RemoteException {  
  27.             Random random=new Random();  
  28.             int nextInt = random.nextInt(2);              
  29.             return names[nextInt];  
  30.         }  
  31.  
  32.         @Override 
  33.         public int getAge() throws RemoteException {  
  34.             Random random=new Random();  
  35.             int nextInt = random.nextInt(2);              
  36.             return ages[nextInt];  
  37.         }          
  38.     }  
  39.       
  40.     @Override 
  41.     public void onCreate() {  
  42.         super.onCreate();  
  43.         // 實例化Binder對象  
  44.         binder=new DogBinder();  
  45.         Log.i(TAG, "創建服務成功");  
  46.     }  
  47.  
  48.     @Override 
  49.     public IBinder onBind(Intent intent) {  
  50.         Log.i(TAG, "綁定服務成功");  
  51.         // 返回Binder對象  
  52.         return binder;  
  53.     }  

 客戶端調用服務獲取數據: 

  1. package com.example.aidlClientdemo;  
  2.  
  3. import com.example.aidlservicedemo.domain.IDog;  
  4. import android.app.Activity;  
  5. import android.content.ComponentName;  
  6. import android.content.Intent;  
  7. import android.content.ServiceConnection;  
  8. import android.os.Bundle;  
  9. import android.os.IBinder;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.Button;  
  13. import android.widget.Toast;  
  14.  
  15. public class BaseTypeActivity extends Activity {  
  16.     private Button btn_startService, btn_endService,btn_getServiceData;  
  17.     private IDog dogService;  
  18.       
  19.     @Override 
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_service);  
  23.  
  24.         btn_startService = (Button) findViewById(R.id.btn_startService);  
  25.         btn_endService = (Button) findViewById(R.id.btn_endService);  
  26.         btn_getServiceData = (Button) findViewById(R.id.btn_getServiceData);  
  27.  
  28.         btn_startService.setOnClickListener(click);  
  29.         btn_endService.setOnClickListener(click);  
  30.         btn_getServiceData.setOnClickListener(click);  
  31.     }  
  32.  
  33.     private View.OnClickListener click = new OnClickListener() {  
  34.  
  35.         @Override 
  36.         public void onClick(View v) {  
  37.             switch (v.getId()) {  
  38.             case R.id.btn_startService:  
  39.                 startService();  
  40.                 break;  
  41.             case R.id.btn_endService:  
  42.                 endService();  
  43.                 break;  
  44.             case R.id.btn_getServiceData:  
  45.                 getServiceDate();  
  46.                 break;  
  47.             }  
  48.         }                  
  49.     };  
  50.     /*  
  51.      * 獲取數據  
  52.      */ 
  53.     private void getServiceDate() {  
  54.         try {  
  55.             if(dogService!=null){  
  56.                 StringBuilder sBuilder=new StringBuilder();  
  57.                 sBuilder.append("name:"+dogService.getName());  
  58.                 sBuilder.append("\nage:"+dogService.getAge());  
  59.                 Toast.makeText(BaseTypeActivity.this, sBuilder.toString(), Toast.LENGTH_SHORT).show();  
  60.             }  
  61.             else 
  62.             {  
  63.                 Toast.makeText(BaseTypeActivity.this, "請先綁定服務", Toast.LENGTH_SHORT).show();  
  64.             }  
  65.         } catch (Exception e) {  
  66.             e.printStackTrace();  
  67.         }          
  68.     }  
  69.  
  70.     private ServiceConnection connBase=new ServiceConnection() {  
  71.           
  72.         @Override 
  73.         public void onServiceDisconnected(ComponentName name) {  
  74.             dogService=null;  
  75.         }  
  76.           
  77.         @Override 
  78.         public void onServiceConnected(ComponentName name, IBinder service) {  
  79.             // IDog.Stub.asInterface,獲取接口  
  80.             dogService=IDog.Stub.asInterface(service);  
  81.         }  
  82.     };  
  83.       
  84.     /**  
  85.      * 開始服務  
  86.      */ 
  87.     private void startService(){  
  88.         Intent intent=new Intent();  
  89.         intent.setAction("cn.bgxt.Service.BASE_TYPE_SERVICE");  
  90.         bindService(intent, connBase, BIND_AUTO_CREATE);  
  91.         Toast.makeText(BaseTypeActivity.this, "開始綁定服務", Toast.LENGTH_SHORT).show();  
  92.     }  
  93.     /**  
  94.      * 停止服務  
  95.      */ 
  96.     private void endService(){  
  97.         if(connBase!=null)  
  98.         {  
  99.             unbindService(connBase);  
  100.             // 接觸綁定的時候需要回收dogService連接資源  
  101.             // 在源碼中漏了,這是後來加上的  
  102.             dogService=null;  
  103.             Toast.makeText(BaseTypeActivity.this, "服務解除綁定", Toast.LENGTH_SHORT).show();  
  104.         }  
  105.     }      

 

 

 效果展示:先運行服務應用,再運行客戶端應用。

 

   源碼下載

 

總結

  本文只介紹了AIDL的基本結構,以及如何通過AIDL接口傳遞一個系統內置類型的數據。下一篇將介紹一下AIDL的高級應用,如何傳遞一個自定義對象。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved