Android:Service之AIDL傳遞系統基本類型資料

來源:互聯網
上載者:User

   什麼是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介面的文法非常相似,但是存在一些差異:

  AIDL定義介面的原始碼尾碼必須以.aidl結尾。

  AIDL一樣要指定AIDL介面的包資訊package *。

  AIDL介面無需指定public、private、protected等範圍,可以理解為就是public。

  AIDL預設情況下只能傳遞基本類型、String、List、Map、CharSequence。

  如果需要傳遞其他類型的對象,需要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 }

  54 }

  用戶端調用服務擷取資料:

  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 }

  106 }

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

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.