一、概述: AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫。 其主要作用是用於進程間額通訊。 在Android系統中,每個進程都運行在一塊獨立的記憶體中, ...
一、概述:
AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫。
其主要作用是用於進程間額通訊。
在Android系統中,每個進程都運行在一塊獨立的記憶體中,在其中完成自己的各項活動,與其他進程都分隔開來。可是有時候我們又有應用間進行互動的需求,比較傳遞數據或者任務委托等,AIDL就是為了滿足這種需求而誕生的。通過AIDL,可以在一個進程中獲取另一個進程的數據和調用其暴露出來的方法,從而滿足進程間通信的需求。 二、語法: 1、支持的數據類型:- 八種基本數據類型:byte、char、short、int、long、float、double、boolean
- String,CharSequence
- 實現了Parcelable介面的數據類型
- List 類型。List承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象
- Map類型。Map承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象
2、
AIDL文件可以分為兩類。一類用來聲明實現了Parcelable介面的數據類型,以供其他AIDL文件使用那些非預設支持的數據類型。還有一類是用來定義介面方法,聲明要暴露哪些介面給客戶端調用,定向Tag就是用來標註這些方法的參數值。
3、
定向Tag。定向Tag表示在跨進程通信中數據的流向,用於標註方法的參數值,分為 in、out、inout 三種。其中 in 表示數據只能由客戶端流向服務端, out 表示數據只能由服務端流向客戶端,而 inout 則表示數據可在服務端與客戶端之間雙向流通。此外,如果AIDL方法介面的參數值類型是:基本數據類型、String、CharSequence或者其他AIDL文件定義的方法介面,那麼這些參數值的定向 Tag 預設是且只能是 in,所以除了這些類型外,其他參數值都需要明確標註使用哪種定向Tag。 4、明確導包。在AIDL文件中需要明確標明引用到的數據類型所在的包名,即使兩個文件處在同個包名下。
三、編寫代碼:
創建兩個工程,一個作為服務端,一個作為客戶端,客戶端綁定服務端service,然後調用方法向服務端獲取書籍列表,向服務端添加書籍。
1、服務端:
(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對象,實現裡面的兩個方法,客戶端拿到這個對象後就可以與服務端通訊了。
2、客戶端
(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用於向服務端添加書籍
轉載請標明出處:https://www.cnblogs.com/tangZH/p/10775848.html
參考:https://www.jianshu.com/p/29999c1a93cd