1、概述:html
AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫。java
其主要做用是用於進程間額通信。android
二、app
AIDL文件能夠分爲兩類。一類用來聲明實現了Parcelable接口的數據類型,以供其餘AIDL文件使用那些非默認支持的數據類型。還有一類是用來定義接口方法,聲明要暴露哪些接口給客戶端調用,定向Tag就是用來標註這些方法的參數值。ide
三、this
明確導包。在AIDL文件中須要明確標明引用到的數據類型所在的包名,即便兩個文件處在同個包名下。spa
3、編寫代碼:code
建立兩個工程,一個做爲服務端,一個做爲客戶端,客戶端綁定服務端service,而後調用方法向服務端獲取書籍列表,向服務端添加書籍。htm
一、服務端:對象
(1)、建立aidl文件Book.aidl
建立後即可以在目錄裏看到aidl文件。
接下來定義Book類,注意Books類的包名必須與Book.aidl包名同樣,可是不可與Book.aidl在同一個目錄下。
Book.class的代碼以下,其必須繼承Parcelable接口:
package com.status.aidlproject.com.aidl; import android.os.Parcel; import android.os.Parcelable; public class Book implements Parcelable { private String bookName; public Book(String name) { bookName = name; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } protected Book(Parcel in) { bookName = in.readString(); } public static final Creator<Book> CREATOR = new Creator<Book>() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(bookName); } public void readFromParcel(Parcel desc) { bookName = desc.readString(); } @Override public String toString() { return "bookName=" + bookName; } }
接下來修改Book.aidl文件,將其聲明爲parcelable類型,而且須要注意的是,原先默認的interface接口須要去掉,不然編譯會報錯。
// Book.aidl package com.status.aidlproject.com.aidl; // Declare any non-default types here with import statements parcelable Book; //須要刪除 /*interface Book { void default(String s); }*/
接下來即是要定義服務端暴露給客戶端的接口了(獲取書籍列表,添加書籍)
在一樣的目錄定義aidl文件BookManager.aidl
代碼以下:
// BookManager.aidl package com.status.aidlproject.com.aidl; // Declare any non-default types here with import statements import com.status.aidlproject.com.aidl.Book; interface BookManager { List<Book> getBookList(); void addBook(inout Book book); }
注意要把包手動導進來。
接下來,make project即可以看到aidl編譯成代碼文件
這個文件纔是咱們真正須要用到的。
(2)、建立Service,供客戶端綁定
package com.status.aidlproject; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import com.status.aidlproject.com.aidl.Book; import com.status.aidlproject.com.aidl.BookManager; import java.util.ArrayList; import java.util.List; public class BookService extends Service { private final String TAG = BookService.class.getSimpleName(); private List<Book> list; @Override public void onCreate() { super.onCreate(); list = new ArrayList<>(); for (int i = 0; i < 5; i++) { Book book = new Book("第" + i + "本書"); list.add(book); } } @Nullable @Override public IBinder onBind(Intent intent) { return bookManager; } private BookManager.Stub bookManager = new BookManager.Stub() { @Override public List<Book> getBookList() { Log.d(TAG, "getBookList"); return list; } @Override public void addBook(Book book) { Log.d(TAG, "addBook"); if (book != null) { list.add(book); } Log.d(TAG, book.toString()); } }; @Override public void unbindService(ServiceConnection conn) { super.unbindService(conn); } @Override public void onDestroy() { super.onDestroy(); } }
Manifests文件中能夠這樣寫:
<service android:name=".BookService" android:enabled="true" android:exported="true" android:process=":remote"> <intent-filter> <action android:name="android.intent.action.BookService" /> </intent-filter> </service>
onBind方法返回的是BookManager.Stub對象,實現裏面的兩個方法,客戶端拿到這個對象後就能夠與服務端通信了。
二、客戶端
(1)
將aidl文件與Book.class拷貝到客戶端的工程,注意他們的目錄須要與服務端的同樣,也就是說aidl與Book.class包名要與服務端的同樣。
make project一下便會生成編譯後的文件
(2)、編寫代碼,與服務端鏈接:
package com.status.aidlclient; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import com.status.aidlproject.com.aidl.Book; import com.status.aidlproject.com.aidl.BookManager; import com.status.aidlproject.com.aidl.IMyConnect; import java.util.List; public class MainActivity extends AppCompatActivity { private final String TAG = MainActivity.class.getSimpleName();private TextView textView3; private TextView textView4; private TextView textView5; private final String ACTION1 = "android.intent.action.ConnectService"; private final String ACTION2 = "android.intent.action.BookService"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView3 = findViewById(R.id.text3); textView4 = findViewById(R.id.text4); textView5 = findViewById(R.id.text5); textView3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(ACTION2); // 注意在 Android 5.0之後,不能經過隱式 Intent 啓動 service,必須制定包名 intent.setPackage("com.status.aidlproject"); bindService(intent, connection2, Context.BIND_AUTO_CREATE); } }); textView4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { if (manager != null) { List<Book> list = manager.getBookList(); Log.d(TAG, "getBookList:" + list); } } catch (RemoteException e) { e.printStackTrace(); } } }); textView5.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Book book = new Book("添加的書"); try { if (manager != null) { manager.addBook(book); } } catch (RemoteException e) { e.printStackTrace(); } } }); } private BookManager manager; ServiceConnection connection2 = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "onServiceConnected"); manager = BookManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { manager = null; } }; }
textView3用於綁定服務端
textView4用於獲取服務端書籍列表
textView5用於向服務端添加書籍