【Android】AIDL介紹和實例講解

wKiom1WdYZeRweJPAADqGFPsXR0526.jpg



前言
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類,而且重寫了它的兩個方法:onServiceConnectedonServiceDisconnected。下面給出內部類的代碼:

/*
 * 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;
    }
}


將此項目運行起來,獲得的兩個截圖以下:


wKioL1OgvObjCOZRAAERdi6UXI0769.jpg

Fig 1 : 填寫數字前



wKiom1OgvSnznMc-AADo-l6mSzk522.jpg

Fig 2 : 按下計算按鈕後




後記

附上測試項目的Android代碼包

相關文章
相關標籤/搜索