Android進程間通訊之使用AIDL

AIDLAndroid Interface Definition Language ,可實現進程間的通訊,而且容許多線程訪問。(若是須要進程間通訊,又不須要處理多線程訪問,那麼使用Messenger的方式更爲合適),實現AIDL,須要如下幾個步奏。java

1.定義AIDL接口多線程

 

AIDL接口使用後綴名爲.aidl的文件來定義(例如建立一個IRemoteData.aidl),使用java語法來編寫,在編譯時,Android sdk工具會在/gen目錄下生成一個java文件(IRemoteData.java),此文件內有一個靜態內部抽象類Stub,繼承了Binder類並實現了接口(IRemoteData)。它提供了一個asInterface(android.os.IBinder obj)IBinder對象轉換成咱們聲明的接口類型(實際上就是在Service端對Stub的實現)。ide

 

AIDL支持如下五種數據類型:java基本數據類型(int,char,boolean)StringCharSequenceListMap。若是你要在AIDL中使用其餘數據類型,那麼必須使用import導入,即便該類型和aidl處於同一包中。其次,全部非原始數據類型都必須指定參數方向,傳入參數用關鍵字in表示,傳出參數用out,傳入傳出參數用inout,基本數據類型都是傳入值。函數

 

 1 package com.young.testserver.aidl;
 2 
 3 import com.young.testserver.aidl.Person;
 4 
 5 interface IRemoteData {
 6     int getRemoteData();
 7     void setRemoteData(int data);
 8     
 9     Person getPerson();
10     void setPerson(in Person person);
11 }

因爲該aidl文件中使用了非原始數據類型Person,因此須要建立一個aidl文件對Person進行聲明工具

1 package com.young.testserver.aidl;
2 
3 parcelable Person;

2.建立服務端Service,將咱們對AIDL接口的實現經過onBind()方法返出去。this

 1 public class AidlRemoteService extends Service {
 2 
 3     // IRemoteData.Stub的具體實現
 4     private class RemoteData extends IRemoteData.Stub {
 5         int data;
 6         Person person;
 7         @Override
 8         public int getRemoteData() throws RemoteException {
 9             return data;
10         }
11 
12         @Override
13         public void setRemoteData(int data) throws RemoteException {
14             this.data = data;
15         }
16 
17         @Override
18         public Person getPerson() throws RemoteException {
19             return person;
20         }
21 
22         @Override
23         public void setPerson(Person person) throws RemoteException {
24             this.person = person;
25         }
26 
27     }
28 
29     @Override
30     public IBinder onBind(Intent intent) {
31         // 將實現的IRemoteData.Stub類返出去,客戶端可使用Stub提供的asInterface得到
32         return new RemoteData();
33     }
34 }

3.將服務端對應的aidl文件與java文件拷貝到客戶端,在客戶端綁定服務時,使用Stub類提供的asInterface獲取服務端實現的接口類,而後使用這個已實現的接口類就能夠調用AIDL中的函數。spa

 1 public class AidlClientActivity extends Activity {
 2 
 3     private static final String TAG = "--DEBUG--";
 4   
 5     private static final String BIND_ACTION = "com.young.server.START_AIDL_SERVICE";
 6     private Button mBindBtn;
 7 
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_aidl_client);
12 
13         mBindBtn = (Button) findViewById(R.id.bind_service);
14         mBindBtn.setOnClickListener(new OnClickListener() {
15             @Override
16             public void onClick(View v) {
17                 bindService(new Intent(BIND_ACTION), conn, Context.BIND_AUTO_CREATE);
18             }
19         });
20     }
21 
22     private ServiceConnection conn = new ServiceConnection() {
23 
24         @Override
25         public void onServiceDisconnected(ComponentName name) {
26             Log.v(TAG, "AIDL 服務已斷開");
27         }
28 
29         @Override
30         public void onServiceConnected(ComponentName name, IBinder service) {
31             Log.v(TAG, "AIDL 服務已連接");
32 
33             // 得到服務端對Stub的實現
34             IRemoteData remoteData = IRemoteData.Stub.asInterface(service);
35             try {
36                 remoteData.setRemoteData(123456);
37                 int data = remoteData.getRemoteData();
38                 Log.v(TAG, "client get remote data=" + data);
39 
40                 remoteData.setPerson(new Person("Allen", 25));
41                 Person person = remoteData.getPerson();
42                 Log.v(TAG, "client get remote Person=" + person.toString());
43             } catch (RemoteException e) {
44                 e.printStackTrace();
45             }
46         }
47     };
48 }

4.經過AIDL在進程間傳遞對象,須要符合如下幾點要求線程

(1)實現Parcelable接口。日誌

(2)實現writeToParcel方法,以便將當前對象狀態寫入Parcel中。code

(3)增長一個名爲CREATOR的靜態變量,實現Parcelable.Creator<T>接口

(4)建立一個AIDL文件來聲明這個類(見上文的Person.aidl)

 1 public class Person implements Parcelable {
 2     
 3     private String name;
 4     private int age;
 5     
 6     public Person(String name, int age) {
 7         super();
 8         this.name = name;
 9         this.age = age;
10     }
11 
12     public String getName() {
13         return name;
14     }
15 
16     public void setName(String name) {
17         this.name = name;
18     }
19 
20     public int getAge() {
21         return age;
22     }
23 
24     public void setAge(int age) {
25         this.age = age;
26     }
27 
28     @Override
29     public String toString() {
30         return "Person [name=" + name + ", age=" + age + "]";
31     }
32 
33     // -------------分割線---------------
34 
35     // 注意讀入和寫出順序
36     public Person(Parcel parcel) {
37         name = parcel.readString();
38         age = parcel.readInt();
39     }
40 
41     public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
42 
43         @Override
44         public Person createFromParcel(Parcel source) {
45             return new Person(source);
46         }
47 
48         @Override
49         public Person[] newArray(int size) {
50             return new Person[size];
51         }
52 
53     };
54 
55     @Override
56     public int describeContents() {
57         return 0;
58     }
59 
60     @Override
61     public void writeToParcel(Parcel dest, int flags) {
62         dest.writeString(name);
63         dest.writeInt(age);
64     }

 

最後運行程序,打印日誌結果以下,客戶端取到了從客戶端傳給服務端的數據。

11-13 15:56:23.081: V/--DEBUG--(25361): AIDL 服務已連接11-13 15:56:23.081: V/--DEBUG--(25361): client get remote data=12345611-13 15:56:23.081: V/--DEBUG--(25361): client get remote Person=Person [name=Allen, age=25]

相關文章
相關標籤/搜索