android的AIDL
一.AIDL的意義:
AIDL全稱是Android Interface Definition Language,是android接口定義語言。AIDL就是為了避免我們一遍遍的寫一些千篇一律的代碼而出現的一個模板。
目的:實現進程間通信,而且在能在多進程並發的情況下進行進程間的通信。
與Messenger的區別: Messenger 是以串行的方式處理客戶端發來的消息,如果有大量的並發請求那麽Messenger就不大適合這些情況了,同時Messenger的作用主要是為了傳遞消息,很多的時候我們可能需要跨進程調用服務端的方法,這種情形用Messenger就無法做到了,但是AIDL可以。AIDL也是Messenger的底層實現,因此Messenger的本質也是AIDL,只不過系統為我們做了封裝方便上層的調用。
二.AIDL的語法:
(1)文件類型:用AIDL書寫的文件的後綴是 .aidl,而不是 .java。
(2)數據類型:AIDL默認支持一些數據類型,在使用這些數據類型的時候是不需要導包的,但是除了這些類型之外的數據類型,在使用之前必須導包,就算目標文件與當前正在編寫的 .aidl 文件在同一個包下——在 Java 中,這種情況是不需要導包的。比如,現在我們編寫了兩個文件,一個叫做Book.java ,另一個叫做 BookManager.aidl,它們都在 com.lypeer.aidldemo 包下 ,現在我們需要在 .aidl 文件裏使用 Book 對象,那麽我們就必須在 .aidl 文件裏面寫上 import com.lypeer.aidldemo.Book; 哪怕 .java 文件和 .aidl 文件就在一個包下。
· 基本數據類型(int,long,char,boolean,double,boolean,short,byte)
· String類型和CharSequence類型;
· List類型:只支持ArrayList,裏面的每個元素必須能夠被AIDL支持,List支持泛型;
· Map類型: 只支持HashMap,裏面的每個元素必須能夠被AIDL支持,包括key和value,Map不支持泛型 。
· Parcelable :所有事項了Parcelable接口的對象;
· AIDL: 所有的AIDL接口本身也可以在AIDL文件中使用。
兩種AIDL文件:所有的AIDL文件大致可以分為兩類。一類是用來定義parcelable對象,以供其他AIDL文件使用AIDL中非默認支持的數據類型的。一類是用來定義方法接口,以供系統使用來完成跨進程通信的。可以看到,兩類文件都是在“定義”些什麽,而不涉及具體的實現,這就是為什麽它叫做“Android接口定義語言”。
舉個例子:
例子1:
// Book.aidl //第一類AIDL文件的例子 //這個文件的作用是引入了一個序列化對象 Book 供其他的AIDL文件使用 //註意:Book.aidl與Book.java的包名應當是一樣的 package com.ryg.chapter_2.aidl;
//註意parcelable是小寫
parcelable Book;
例子2:
//IBookManager.aidl
//第二類AIDL文件的例子
package com.ryg.chapter_2.aidl;
//導入所需要使用的非默認支持數據類型的包
import com.ryg.chapter_2.aidl.book;
interface IBookManager{
//所有的返回值前都不需要加任何東西,不管是什麽數據類型
List<Book> getBookList();
//傳參時除了Java基本類型以及String,CharSequence之外的類型 //都需要在前面加上定向tag,具體加什麽量需而定
void addBook(in Book book);
}
對象類要實現Parcelable接口:
參考這個bolg: http://blog.csdn.net/luoyanglizi/article/details/51980630
將要傳輸的數據轉化為能夠在內存之間流通的形式。這個轉化的過程就叫做序列化與反序列化。
比如現在我們要將一個對象的數據從客戶端傳到服務端去,我們就可以在客戶端對這個對象進行序列化的操作,將其中包含的數據轉化為序列化流,然後將這個序列化流傳輸到服務端的內存中去,再在服務端對這個數據流進行反序列化的操作,從而還原其中包含的數據——通過這種方式,我們就達到了在一個進程中訪問另一個進程的數據的目的。
AIDL中的in,out,inout:
http://blog.csdn.net/luoyanglizi/article/details/51958091
AIDL中的定向 tag 表示了在跨進程通信中數據的流向,其中 in 表示數據只能由客戶端流向服務端, out 表示數據只能由服務端流向客戶端,而 inout 則表示數據可在服務端與客戶端之間雙向流通。其中,數據流向是針對在客戶端中的那個傳入方法的對象而言的。in 為定向 tag 的話表現為服務端將會接收到一個那個對象的完整數據,但是客戶端的那個對象不會因為服務端對傳參的修改而發生變動;out 的話表現為服務端將會接收到那個對象的參數為空的對象,但是在服務端對接收到的空對象有任何修改之後客戶端將會同步變動;inout 為定向 tag 的情況下,服務端將會接收到客戶端傳來對象的完整信息,並且客戶端將會同步服務端對該對象的任何變動。
因為默認生成的模板類的對象只支持為 in 的定向 tag 。為什麽呢?因為默認生成的類裏面只有 writeToParcel() 方法,而如果要支持為 out 或者 inout 的定向 tag 的話,還需要實現 readFromParcel() 方法——而這個方法其實並沒有在 Parcelable 接口裏面,所以需要我們從頭寫。
readFromParcel()方法:
添加了 readFromParcel() 方法之後,我們的 Book類的對象在AIDL文件裏就可以用 out 或者 inout 來作為它的定向 tag 了。
三.在androidstudio快速生成aidl文件
在eclipse
四.後記
過程遇到的報錯:
(1)java.lang.SecurityException: Binder invocation to an incorrect interface報錯問題
解決方法: 客戶端的aidl文件包名要與服務端的包名一樣
(2)報錯:系統找不到 Book.java (對象)文件
解決方法一:
- 修改 build.gradle 文件:在 android{} 中間加上下面的內容:
-
sourceSets { main { java.srcDirs = [‘src/main/java‘, ‘src/main/aidl‘] } }
解決方法2:
把 java 文件放到 java 包下去:把 Book.java 放到 java 包裏任意一個包下,保持其包名不變,與 Book.aidl 一致。只要它的包名不變,Book.aidl 就能找到 Book.java ,而只要 Book.java 在 java 包下,那麽系統也是能找到它的。
例子:
把客戶端和服務端都運行到同一個虛擬機上
最後成功的logcat
客戶端
服務端
AIDL的例子demo下載傳送門:https://github.com/Qinxiaoshou/AIDLDemo
android的AIDL