用途:您可以利用它定義客戶端與服務(wù)均認(rèn)可的編程接口,以便二者使用進(jìn)程間通信 (IPC) 進(jìn)行相互通信
詳細(xì)講解的博客
http://www.itdecent.cn/p/c2fd499261a8
文檔
https://developer.android.google.cn/guide/components/aidl?hl=zh_cn
如要使用 AIDL 創(chuàng)建綁定服務(wù),請執(zhí)行以下步驟:
-
- 創(chuàng)建 .aidl 文件
此文件定義帶有方法簽名的編程接口。
-
- 實現(xiàn)接口
Android SDK 工具會基于您的
.aidl文件,使用 Java 編程語言生成接口。此接口擁有一個名為Stub的內(nèi)部抽象類,用于擴(kuò)展Binder類并實現(xiàn) AIDL 接口中的方法。您必須擴(kuò)展Stub類并實現(xiàn)這些方法。 -
- 向客戶端公開接口
實現(xiàn)
Service并重寫onBind(),從而返回Stub類的實現(xiàn)。
1. 創(chuàng)建 .aidl 文件
AIDL 使用一種簡單語法,允許您通過一個或多個方法(可接收參數(shù)和返回值)來聲明接口。參數(shù)和返回值可為任意類型,甚至是 AIDL 生成的其他接口。
您必須使用 Java 編程語言構(gòu)建 .aidl 文件。每個 .aidl 文件均須定義單個接口,并且只需要接口聲明和方法簽名。
interface IIotAidlInterface {
/**
* @param lockNum 鎖號
* @return result 開門狀態(tài) 1正常
*/
int openDoor(int lockNum);
}
2. 實現(xiàn)接口
當(dāng)您構(gòu)建應(yīng)用時,Android SDK 工具會生成以 .aidl 文件命名的 .java 接口文件。生成的接口包含一個名為 Stub 的子類(例如,YourInterface.Stub),該子類是其父接口的抽象實現(xiàn),并且會聲明 .aidl 文件中的所有方法。
如要實現(xiàn) .aidl 生成的接口,請擴(kuò)展生成的 Binder 接口(例如,YourInterface.Stub),并實現(xiàn)繼承自 .aidl 文件的方法。
以下示例展示使用匿名實例實現(xiàn) IIotAidlInterface 接口(由以上 IIotAidlInterface.aidl 示例定義)的過程:
class IotService : Service() {
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
//第二部實現(xiàn)接口
private val binder = object :IIotAidlInterface.Stub(){
override fun openDoor(lockNum: Int): Int {
TODO("Not yet implemented")
}
}
}
3. 向客戶端公開接口
在為服務(wù)實現(xiàn)接口后,您需要向客戶端公開該接口,以便客戶端進(jìn)行綁定。如要為您的服務(wù)公開該接口,請擴(kuò)展 Service 并實現(xiàn) onBind(),從而返回實現(xiàn)生成的 Stub 的類實例(如前文所述)。以下是向客戶端公開 IRemoteService 示例接口的服務(wù)示例。
class IotService : Service() {
override fun onBind(intent: Intent): IBinder {
return binder
}
//第二部實現(xiàn)接口
private val binder = object :IIotAidlInterface.Stub(){
override fun openDoor(lockNum: Int): Int {
TODO("Not yet implemented")
}
}
}
現(xiàn)在,當(dāng)客戶端(如 Activity)調(diào)用 bindService() 以連接此服務(wù)時,客戶端的 onServiceConnected() 回調(diào)會接收服務(wù)的 onBind() 方法所返回的 binder 實例。
客戶端還必須擁有接口類的訪問權(quán)限,因此如果客戶端和服務(wù)在不同應(yīng)用內(nèi),則客戶端應(yīng)用的 src/ 目錄內(nèi)必須包含 .aidl 文件(該文件會生成 android.os.Binder 接口,進(jìn)而為客戶端提供 AIDL 方法的訪問權(quán)限)的副本。
當(dāng)客戶端在 onServiceConnected() 回調(diào)中收到 IBinder 時,它必須調(diào)用 *YourServiceInterface*.Stub.asInterface(service),以將返回的參數(shù)轉(zhuǎn)換成 *YourServiceInterface* 類型。例如:
客戶端
在客戶端添加同樣的AIDL文件
1.創(chuàng)建AIDL文件
package com.tic.aidls;
// Declare any non-default types here with import statements
interface IIotAidlInterface {
/**
* @param lockNum 鎖號
* @return result 開門狀態(tài) 1正常
*/
int openDoor(int lockNum);
}
2.使用
package com.tic.aidlc
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.widget.Toast
import com.tic.aidls.IIotAidlInterface
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var iotService: IIotAidlInterface? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initListener()
}
private fun initListener() {
val intent = Intent("com.tic.aidls")
intent.setPackage("com.tic.aidls")
mBtn1.setOnClickListener {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
}
mBtn2.setOnClickListener {
unbindService(mConnection)
}
mBtn3.setOnClickListener {
val openDoor = iotService?.openDoor(1)
Toast.makeText(this, "OpenDoor:$openDoor", Toast.LENGTH_LONG).show()
}
}
val mConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
iotService = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
iotService = IIotAidlInterface.Stub.asInterface(service)
}
}
}
雙向通信
aidl
// IInventoryCallback.aidl
package com.tic.aidls;
// Declare any non-default types here with import statements
interface IInventoryCallback {
void onSuccess(String data);
void onError(String message);
}
// IInventoryCallback.aidl
package com.tic.aidls;
// Declare any non-default types here with import statements
interface IInventoryCallback {
void onSuccess(String data);
void onError(String message);
}
服務(wù)端
class IotService : Service() {
val mCallbacks: RemoteCallbackList<IInventoryCallback> = RemoteCallbackList()
override fun onBind(intent: Intent): IBinder {
return binder
}
//第二部實現(xiàn)接口
private val binder = object : IIotAidlInterface.Stub() {
override fun openDoor(lockNum: Int): Int {
return 1
}
override fun register(callback: IInventoryCallback?) {
mCallbacks.register(callback)
}
override fun unRegister(callback: IInventoryCallback?) {
mCallbacks.unregister(callback)
}
override fun send(data: String?) {
val size = mCallbacks.beginBroadcast();
try {
for (i in 0 until size) {
mCallbacks.getBroadcastItem(i).onSuccess("盤點啊")
}
} catch (e: Exception) {
e.printStackTrace()
}
mCallbacks.finishBroadcast()
}
}
}
客戶端
package com.tic.aidlc
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.widget.Toast
import com.tic.aidls.IInventoryCallback
import com.tic.aidls.IIotAidlInterface
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var iotService: IIotAidlInterface? = null
private var remoteCallback: IInventoryCallback.Stub? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initListener()
initCallback()
}
private fun initCallback() {
remoteCallback = object : IInventoryCallback.Stub() {
override fun onSuccess(data: String?) {
}
override fun onError(message: String?) {
}
}
}
private fun initListener() {
val intent = Intent("com.tic.aidls")
intent.setPackage("com.tic.aidls")
mBtn1.setOnClickListener {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
}
mBtn2.setOnClickListener {
unbindService(mConnection)
}
mBtn3.setOnClickListener {
val openDoor = iotService?.openDoor(1)
Toast.makeText(this, "OpenDoor:$openDoor", Toast.LENGTH_LONG).show()
}
}
private val mConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
iotService = IIotAidlInterface.Stub.asInterface(service)
try {
iotService?.register(remoteCallback)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onServiceDisconnected(name: ComponentName?) {
iotService = null
remoteCallback = null
}
}
}