文章目錄
- android跨程序(IPC)通信及AIDL
-
- 官方文檔
- 特别注意
- 過程說明
- 跨程序
- 标簽 in out inout oneway
- 跨程序回調RemoteCallbackList
- 多IBinder傳回如何處理
- 示例
- 計劃
- 參考
android跨程序(IPC)通信及AIDL
官方文檔
-
官方文檔詳見
https://developer.android.google.cn/guide/components/aidl?hl=en
特别注意
- aidl檔案裡不要出現中文,因為官方還不支援中文
- aidl支援java基本資料類型,以及String,CharSequence,List,Map(其中List,Map的具體類分别是ArrayList,HashMap,Map不支援泛型)
- aidl檔案中引用的對象即使在同一目錄,也要增加import語句
- 隻能定義int和String常量,如const int VERSION=1;
- 傳遞對象時必須聲明in out inout(預設是in),而基本類型預設是in也隻能是in,一般情況都是采用in
- 對于聲明out和inout的對象需要增加readFromParcel方法的實作
- build.gradle需要把aidl目錄也當作源碼目錄設定進去,否則會報“Unresolved reference:”,如
androd{ ... sourceSets { main { java.srcDirs = ['src/main/java', 'src/main/aidl'] } } }
過程說明
- aidl檔案看起來就像是一個接口類,跟我們寫接口其實差不太多,如果我們在aidl裡需要使用bean類,那麼需要寫一個aidl來聲明bean類,類似這樣
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL - 然後才可以在其他aidl中導入使用
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL - 寫好aidl檔案之後,我們需要build一下,這時會發現android sdk已經幫我們生成了一些代碼
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL - 它是根據我們的aidl檔案生成的接口類,裡面有個抽象類叫Stub,它是繼承android.os.Binder類,而Binder類實作IBinder接口,那麼這個Stub跟我們有啥關系呢
- 我們已經在aidl定義了互動的接口,那麼具體的實作呢,誰來負責,這個就得交給Stub了,是以我們一般都是繼承Stub這個抽象類,把具體的接口實作了,這塊是根據業務去做的,一般都是成為服務的一端去實作的,例如繼承Service後在onBind裡傳回
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL -
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL - 服務端實作好了之後,接下來其實就是等用戶端連過來然後去調用了
- 用戶端一般都是通過bindService,然後在ServiceConnection裡的建立連接配接成功的回調中得到了IBinder
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL - 那麼用戶端就可以根據sdk為我們生成好的接口(比如在本例中是IExample這個接口類)獲得Stub這個抽象類,然後調用它的asInterface這個方法将IBinder傳遞給它,這樣之後用戶端就可以愉快地調用服務端的接口了
-
android跨程式(IPC)通信及AIDLandroid跨程式(IPC)通信及AIDL
跨程序
- 為了跨程序,需要把service放置在另一程序中,需要在清單檔案中聲明android:process,其中冒号表示私有程序,後面的名字可以随便取,最後的程序名為"包名:自定義名"
<!-- 運作在私有程序--> <service android:name=".ConnectService" android:process=":remote123" />
标簽 in out inout oneway
- in out inout都隻能修飾參數,不能用在傳回值,參數對象都需要實作Parcelable接口(暫沒有迹象表明可以使用Serializable接口)
- oneway隻在遠端調用時起效,表示遠端調用時不會阻塞調用者的線程,如果是本地調用則還是同步阻塞的
- in:用戶端流向服務端,服務端所做的修改,用戶端不會發送變化;一般參數傳遞都是采用in類型,雙方互不影響
- out:服務端将會收到用戶端對象,該對象不為null,但是它裡面的字段為null,服務端所做的修改,用戶端會同步變化; 對象需要有readFromParcel方法
- inout:服務端将會接收到用戶端傳來對象的完整資訊,并且用戶端将會同步服務端對該對象的任何變動; 對象需要有readFromParcel方法
跨程序回調RemoteCallbackList
- 示範如何跨程序回調,主要是用到了android.os.RemoteCallbackList
var mListeners: RemoteCallbackList<IMessageListener> = RemoteCallbackList() val messageServiceBinder1 = object : IMessageService.Stub() { override fun unregisterMessageListener(listener: IMessageListener?) { showToast("unregister") //使用RemoteCallbackList才能使得遠端調用的注冊與反注冊成功生效,因為跨了程序 mListeners.unregister(listener) } override fun registerMessageListener(listener: IMessageListener?) { showToast("register") mListeners.register(listener) } override fun sendMessage(msg: String?) { if (!mIsConneted) { return } var n= mListeners.beginBroadcast() for( i in 0..n-1){ //直接将用戶端的資訊傳回 mListeners.getBroadcastItem(i).onMessage(msg) } mListeners.finishBroadcast() } }
多IBinder傳回如何處理
- 假如需要傳回多個IBinder對象,那麼應該聲明一個IBinder,這個IBinder用于傳回其他IBinder
lateinit var serviceConnection: ServiceConnection var iConnectService: IConnectService? = null var iMessageService: IMessageService? = null var iServiceManager: IServiceManager? = null serviceConnection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName, service: IBinder) { Log.i(TAG, "onServiceConnected:" + name.flattenToShortString()) showToast("onServiceConnected:" + name.flattenToShortString()) iServiceManager = IServiceManager.Stub.asInterface(service) iConnectService = IConnectService.Stub.asInterface(iServiceManager?.connectServiceBinder) iMessageService = IMessageService.Stub.asInterface(iServiceManager?.messageServiceBinder) } override fun onServiceDisconnected(name: ComponentName) { Log.i(TAG, "onServiceDisconnected:" + name.flattenToShortString()) showToast("onServiceDisconnected:" + name.flattenToShortString()) iServiceManager = null iConnectService = null iMessageService = null } }
示例
- 本文示例已經放到github: https://github.com/android-coding-well/aidldemo
計劃
- 接下來打算使用MemoryFile實作程序間共享記憶體
參考
-
官方說明
https://developer.android.google.cn/guide/components/aidl?hl=en
-
AIDL中的in、out、inout的差別 - 簡書
https://www.jianshu.com/p/a61da801b919
-
Android Service完全解析,關于服務你所需知道的一切(上) - 郭霖的專欄 - CSDN部落格
https://blog.csdn.net/guolin_blog/article/details/11952435
-
Android Binder機制全面解析 - 簡書
https://www.jianshu.com/p/b5cc1ef9f917
-
一篇文章了解相見恨晚的 Android Binder 程序間通訊機制
http://www.360doc.com/content/19/0211/14/15700426_814240466.shtml