前言
java
爲使應用程序之間可以彼此通訊,Android提供了IPC (Inter Process Communication,進程間通訊)的一種獨特實現: AIDL (Android Interface Definition Language, Android接口定義語言)。android
網上看了幾篇關於AIDL的文章,寫得都很不錯,不過例子構造大多略微複雜: 創建兩個Android項目,一個是client,一個是server(提供service)。app
這篇文章將經過一個項目來介紹AIDL用法,包含了service和client。可能簡單了些,不太輕省許多。
ide
這篇博文包含如下三個部分:
工具
1、AIDL介紹測試
2、定義this
三、用例: HelloSumAIDLspa
3.一、建立工程線程
3.二、定義AIDL文件code
3.三、實現遠程服務(Service)
3.四、「暴露」服務
3.五、相關代碼
1、 AIDL介紹
在Android中,每一個應用(Application)執行在它本身的進程中,沒法直接調用到其餘應用的資源,這也符合「沙箱」的理念。所謂沙箱原理,通常來講用在移動電話業務中,簡單地說旨在部分地或所有地隔離應用程序。關於沙箱技術咱們這裏就很少作介紹了,能夠參看51CTO的這篇文章。
所以,在Android中,當一個應用被執行時,一些操做是被限制的,好比訪問內存,訪問傳感器,等等。這樣作能夠最大化地保護系統,省得應用程序「隨心所欲」。
那咱們有時須要在應用間交互,怎麼辦呢?因而,Android須要實現IPC協議。然而,這個協議仍是有點複雜,主要由於須要實現數據管理系統(在進程或線程間傳遞數據)。爲了暫時減緩這個「會呼吸的痛」,Android爲咱們實現了本身的IPC,也就是梁靜茹,oh,sorry,是AIDL :]
2、 定義
AIDL是IPC的一個輕量級實現,用了對於Java開發者來講很熟悉的語法。Android也提供了一個工具,能夠自動建立Stub(類構架,類骨架)。當咱們須要在應用間通訊時,咱們須要按如下幾步走:
1. 定義一個AIDL接口
2. 爲遠程服務(Service)實現對應Stub
3. 將服務「暴露」給客戶程序使用
3、 用例: HelloSumAIDL
AIDL的語法很相似Java的接口(Interface),只須要定義方法的簽名。
AIDL支持的數據類型與Java接口支持的數據類型有些不一樣
1. 全部基礎類型(int, char, 等)
2. String,List,Map,CharSequence等類
3. 其餘AIDL接口類型
4. 全部Parcelable的類
爲了更好地展現AIDL的用法,咱們來看一個很簡單的例子: 兩數相加。
3.1建立工程
事不宜遲,咱們就建立一個Android項目。如下是項目的基本信息(不必定要同樣):
- 項目名稱: HelloSumAIDL
- 目標平臺: 4.3
- 包名: com.android.hellosumaidl
- Activity名稱: HelloSumAidlActivity
3.2 建立工程
在com.android.hellosumaidl這個包中,新建一個普通文件(New->File),取名爲 IAdditionService.aidl。在這個文件中輸入如下代碼:
package com.android.hellosumaidl; // Interface declaration interface IAdditionService { // You can pass the value of in, out or inout // The primitive types (int, boolean, etc) are only passed by in int add(in int value1, in int value2); }
一旦文件被保存,Android的AIDL工具會在gen/com/android/hellosumaidl這個文件夾裏自動生成對應的IAdditionService.java這個文件。由於是自動生成的,因此無需改動。這個文件裏就包含了Stub,咱們接下來要爲咱們的遠程服務實現這個Stub。
3.3 實現遠程服務
首先咱們在com.android.hellosumaidl這個包中新建一個類,取名叫AdditionService.java。爲了實現咱們的服務,咱們須要讓這個類中的onBind方法返回一個IBinder類的對象。這個IBinder類的對象就表明了遠程服務的實現。爲了實現這個服務,咱們要用到自動生成的子類IAdditionService.Stub。在其中,咱們也必須實現咱們以前在AIDL文件中定義的add()函數。下面是咱們遠程服務的代碼:
package com.android.hellosumaidl; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; /* * This class exposes the service to client */ public class AdditionService extends Service { @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { return new IAdditionService.Stub() { /* * Implement com.android.hellosumaidl.IAdditionService.add(int, int) */ @Override public int add(int value1, int value2) throws RemoteException { return value1 + value2; } }; } @Override public void onDestroy() { super.onDestroy(); } }
3.4 「暴露」服務
一旦實現了服務中的onBind方法,咱們就能夠把客戶程序(在這裏是HelloSumAidlActivity.java)與服務鏈接起來了。爲了創建這樣的一個連接,咱們須要實現ServiceConnection類。咱們在HelloSumAidlActivity.java建立一個內部類AdditionServiceConnection,這個類繼承ServiceConnection類,而且重寫了它的兩個方法:onServiceConnected和onServiceDisconnected。下面給出內部類的代碼:
/* * This inner class is used to connect to the service */ class AdditionServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder boundService) { service = IAdditionService.Stub.asInterface((IBinder)boundService); Toast.makeText(HelloSumAidlActivity.this, "Service connected", Toast.LENGTH_LONG).show(); } public void onServiceDisconnected(ComponentName name) { service = null; Toast.makeText(HelloSumAidlActivity.this, "Service disconnected", Toast.LENGTH_LONG).show(); } }
這個方法接收一個遠程服務的實現做爲參數。這個實現隨後被轉換(cast)爲咱們本身的AIDL的實現。咱們使用 IAdditionService.Stub.asInterface((IBinder)boundService)。
3.5 相關代碼
爲了完成咱們的測試項目,咱們須要首先改寫main.xml(主界面的格局文件)和string.xml (字符串定義文件):
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="22sp" /> <EditText android:id="@+id/value1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/hint1" > </EditText> <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/plus" android:textSize="36sp" /> <EditText android:id="@+id/value2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/hint2" > </EditText> <Button android:id="@+id/buttonCalc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/equal" > </Button> <TextView android:id="@+id/result" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/result" android:textSize="36sp" /> </LinearLayout>
string.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">HelloSumAIDL</string> <string name="hello">Hello Sum AIDL</string> <string name="result">Result</string> <string name="plus">+</string> <string name="equal">=</string> <string name="hint1">Value 1</string> <string name="hint2">Value 2</string> </resources>
最後,咱們的HelloSumAidlActivity.java以下:
package com.android.hellosumaidl; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; public class HelloSumAidlActivity extends Activity { IAdditionService service; AdditionServiceConnection connection; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initService(); Button buttonCalc = (Button)findViewById(R.id.buttonCalc); buttonCalc.setOnClickListener(new OnClickListener() { TextView result = (TextView)findViewById(R.id.result); EditText value1 = (EditText)findViewById(R.id.value1); EditText value2 = (EditText)findViewById(R.id.value2); @Override public void onClick(View v) { int v1, v2, res = -1; v1 = Integer.parseInt(value1.getText().toString()); v2 = Integer.parseInt(value2.getText().toString()); try { res = service.add(v1, v2); } catch (RemoteException e) { e.printStackTrace(); } result.setText(Integer.valueOf(res).toString()); } }); } @Override protected void onDestroy() { super.onDestroy(); releaseService(); } /* * This inner class is used to connect to the service */ class AdditionServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder boundService) { service = IAdditionService.Stub.asInterface((IBinder)boundService); Toast.makeText(HelloSumAidlActivity.this, "Service connected", Toast.LENGTH_LONG).show(); } public void onServiceDisconnected(ComponentName name) { service = null; Toast.makeText(HelloSumAidlActivity.this, "Service disconnected", Toast.LENGTH_LONG).show(); } } /* * This function connects the Activity to the service */ private void initService() { connection = new AdditionServiceConnection(); Intent i = new Intent(); i.setClassName("com.android.hellosumaidl", com.android.hellosumaidl.AdditionService.class.getName()); boolean ret = bindService(i, connection, Context.BIND_AUTO_CREATE); } /* * This function disconnects the Activity from the service */ private void releaseService() { unbindService(connection); connection = null; } }
將此項目運行起來,獲得的兩個截圖以下:
Fig 1 : 填寫數字前
Fig 2 : 按下計算按鈕後
後記
附上測試項目的Android代碼包