AIDL(Android 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等),String,CharSequence,List和Map。若是你要在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]