詳解Android中AIDL的使用
AIDL,即Android Interface Definition Language,Android接口定義語言。這門語言是為瞭實現進程間通信。每一個進程都有自己的一塊獨立的內存,都在自己的內存上存儲自己的數據,執行自己的操作,每個進程之間你不知我,我不知你,而AIDL,就是兩個進程之間溝通的橋梁。
AIDL用來做什麼
AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫,對於小白來說,AIDL的作用是讓你可以在自己的APP裡綁定一個其他APP的service,這樣你的APP可以和其他APP交互。
aidl文件支持的數據類型包括:
- 八種基本數據類型:byte、char、short、int、long、float、double、boolean
- String、CharSequence
- 實現瞭Parcelable接口的數據類型
- List類型。List承載的數據必須是AIDL支持的類型,或者是其他聲明的AIDL對象
- Map類型。Map承載的數據必須是AIDL支持的類型,或者是其他聲明的AIDL對象
在使用其他聲明的AIDL對象的時候必須要導包,即使要使用的AIDL對象文件和當前正在編輯的aidl文件在同一個文件夾下。
aidl文件可以分為兩類,一類用來聲明實現瞭Parcelable接口的數據類型,以供其他AIDL文件使用那些非默認支持的數據類型。還有一類是用來定義接口方法,聲明要暴露哪些接口給客戶端調用。
AIDL的具體使用步驟是:
一、創建一個服務端工程
1、如果aidl文件中涉及到實現瞭Parcelable接口的數據類型,則先將該aidl文件定義出來。在src文件夾下右鍵,選擇新建aidl文件,這裡新建瞭一個Book.aidl文件。
新建完以後,會在main文件下生成一個aidl的文件夾,aidl文件夾下的目錄結構和java文件夾下的目錄結構一樣。
Book.aidl文件中會有一個默認方法。
我們刪除掉這個默認方法,隻聲明一個parcelable數據類型,這個文件就成為聲明Parcelable數據類型的AIDL文件。註意這裡的parcelable中的p是小寫的。
2、這個時候我們來定義Book類並實現Parcelable接口,註意Book類在java文件夾下的目錄與Book.aidl文件在aidl文件夾下的目錄保持一致。
public class Book implements Parcelable { private String name; public Book(String name) { this.name=name; } protected Book(Parcel in) { this.name = 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]; } }; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); } /** * 這個方法是自己寫上去的,並不是根據錯誤提示自動生成的代碼 * 默認生成的模板類的對象隻支持為in的定向tag。因為默認生成的類裡面隻有 writeToParcel() 方法。 * 而如果要支持為out或者inout的定向tag的話,還需要實現readFromParcel()方法。 * 而這個方法其實並沒有在 Parcelable 接口裡面,所以需要我們從頭寫。 */ public void readFromParcel(Parcel dest){ name=dest.readString(); } }
這裡需要註意的一點是如果要支持為out或inout的定向tag的話,需要我們手寫readFromParcel()方法。
3、然後我們開始寫BookController.aidl文件來定義能被客戶端調用的接口。
package com.example.service; import com.example.service.Book; // Declare any non-default types here with import statements interface BookController { int getInt();//int類型 String getString();//String類型 List<Book> getBookList();//aidl對象 void addBook(inout Book book);//aidl對象 }
這裡需要註意的是,雖然Book.aidl文件和BookController.aidl文件在同一個包下,還是需要手動導入一下。
4、至此,我們的aidl文件寫完瞭,然後我們Rebuild project,系統會幫我們生成一個與AIDL文件同名的java文件,這個java文件才是與我們跨進程通信密切相關的東西。
5、定義一個Service,通過這個Service將接口暴露給外部。
public class AIDLService extends Service { private List<Book> bookList; public AIDLService() { } @Override public void onCreate() { super.onCreate(); bookList = new ArrayList<>(); initData(); } private void initData() { Book book1 = new Book("花千骨"); Book book2 = new Book("公主小妹"); Book book3 = new Book("仙劍奇俠傳"); Book book4 = new Book("飄"); Book book5 = new Book("茶花女"); Book book6 = new Book("解憂雜貨鋪"); Book book7 = new Book("活著"); Book book8 = new Book("三生三世十裡桃花"); bookList.add(book1); bookList.add(book2); bookList.add(book3); bookList.add(book4); bookList.add(book5); bookList.add(book6); bookList.add(book7); bookList.add(book8); } private final BookController.Stub stub = new BookController.Stub() { @Override public int getInt() throws RemoteException { return bookList == null ? 0 : bookList.size(); } @Override public String getString() throws RemoteException { return bookList == null ? "" : bookList.get(0).getName(); } @Override public List<Book> getBookList() throws RemoteException { return bookList; } @Override public void addBook(Book book) throws RemoteException { if (book != null) { bookList.add(book); } else { Log.i("ruxing", "接收到瞭一個空對象 Inout"); } } }; @Nullable @Override public IBinder onBind(Intent intent) { return stub; } }
6、在清單文件中註冊服務。
<service android:name=".AIDLService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.service.action"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>
至此,服務端開發完成瞭。
二、創建一個custom工程
1、新建一個custom工程,把服務端的aidl文件夾下的內容全部拷貝到新項目中,如果aidl中有用到bean實體類,把實體類也拷貝過來,然後Rebuild Project。
2、在客戶端的activity中連接遠程服務,實現aidl通信。
public class MainActivity extends AppCompatActivity { private BookController bookController; private boolean connected; private List<Book> bookList; private Button mBtnGetBookList; private Button mBtnAddBook; private Button mBtnGetBookSize; private Button mBtnGetFirstBookName; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bookController = BookController.Stub.asInterface(service); connected = true; } @Override public void onServiceDisconnected(ComponentName name) { bookController = null; connected = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnGetBookList = findViewById(R.id.btn_get_book_list); mBtnAddBook = findViewById(R.id.btn_add); mBtnGetBookSize = findViewById(R.id.btn_get_book_size); mBtnGetFirstBookName = findViewById(R.id.btn_first_book_name); mBtnGetBookList.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (connected) { try { bookList = bookController.getBookList(); for (int i = 0; i < bookList.size(); i++) { Log.i("ruxing", "name=" + bookList.get(i).getName()); } } catch (RemoteException e) { e.printStackTrace(); } } } }); mBtnAddBook.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (connected) { Book book = new Book("新書"); try { bookController.addBook(book); Log.i("ruxing", "向服務器添加瞭一本新書==="+book.getName()); } catch (RemoteException e) { e.printStackTrace(); } } } }); mBtnGetBookSize.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (connected) { try { int size = 0; size = bookController.getInt(); Log.i("ruxing", "共有" + size + "本書"); } catch (RemoteException e) { e.printStackTrace(); } } } }); mBtnGetFirstBookName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (connected) { try { String name = bookController.getString(); Log.i("ruxing", "第一本書的書名是:" + name); } catch (RemoteException e) { e.printStackTrace(); } } } }); Intent intent = new Intent(); intent.setPackage("com.example.service"); intent.setAction("com.example.service.action"); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); if (connected) { unbindService(serviceConnection); } } }
完整的代碼地址:
https://github.com/ruxing1102/AIDL.git
到此這篇關於Android中AIDL的使用的文章就介紹到這瞭,更多相關Android AIDL使用內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 解析Android AIDL的實例與原理
- Java實現圖書管理系統的示例代碼
- Android BindService使用案例講解
- Android進程間使用Intent進行通信
- Java順序表實現圖書管理系統