用途:您可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信
详细讲解的博客
https://www.jianshu.com/p/c2fd499261a8
文档
https://developer.android.google.cn/guide/components/aidl?hl=zh_cn
如要使用 AIDL 创建绑定服务,请执行以下步骤:
-
- 创建 .aidl 文件
此文件定义带有方法签名的编程接口。
-
- 实现接口
Android SDK 工具会基于您的
.aidl
文件,使用 Java 编程语言生成接口。此接口拥有一个名为Stub
的内部抽象类,用于扩展Binder
类并实现 AIDL 接口中的方法。您必须扩展Stub
类并实现这些方法。 -
- 向客户端公开接口
实现
Service
并重写onBind()
,从而返回Stub
类的实现。
1. 创建 .aidl 文件
AIDL 使用一种简单语法,允许您通过一个或多个方法(可接收参数和返回值)来声明接口。参数和返回值可为任意类型,甚至是 AIDL 生成的其他接口。
您必须使用 Java 编程语言构建 .aidl
文件。每个 .aidl
文件均须定义单个接口,并且只需要接口声明和方法签名。
interface IIotAidlInterface {
/**
* @param lockNum 锁号
* @return result 开门状态 1正常
*/
int openDoor(int lockNum);
}
2. 实现接口
当您构建应用时,Android SDK 工具会生成以 .aidl
文件命名的 .java
接口文件。生成的接口包含一个名为 Stub
的子类(例如,YourInterface.Stub
),该子类是其父接口的抽象实现,并且会声明 .aidl
文件中的所有方法。
如要实现 .aidl
生成的接口,请扩展生成的 Binder
接口(例如,YourInterface.Stub
),并实现继承自 .aidl
文件的方法。
以下示例展示使用匿名实例实现 IIotAidlInterface
接口(由以上 IIotAidlInterface.aidl
示例定义)的过程:
class IotService : Service() {
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
//第二部实现接口
private val binder = object :IIotAidlInterface.Stub(){
override fun openDoor(lockNum: Int): Int {
TODO("Not yet implemented")
}
}
}
3. 向客户端公开接口
在为服务实现接口后,您需要向客户端公开该接口,以便客户端进行绑定。如要为您的服务公开该接口,请扩展 Service
并实现 onBind()
,从而返回实现生成的 Stub
的类实例(如前文所述)。以下是向客户端公开 IRemoteService
示例接口的服务示例。
class IotService : Service() {
override fun onBind(intent: Intent): IBinder {
return binder
}
//第二部实现接口
private val binder = object :IIotAidlInterface.Stub(){
override fun openDoor(lockNum: Int): Int {
TODO("Not yet implemented")
}
}
}
现在,当客户端(如 Activity)调用 bindService()
以连接此服务时,客户端的 onServiceConnected()
回调会接收服务的 onBind()
方法所返回的 binder
实例。
客户端还必须拥有接口类的访问权限,因此如果客户端和服务在不同应用内,则客户端应用的 src/
目录内必须包含 .aidl
文件(该文件会生成 android.os.Binder
接口,进而为客户端提供 AIDL 方法的访问权限)的副本。
当客户端在 onServiceConnected()
回调中收到 IBinder
时,它必须调用 *YourServiceInterface*.Stub.asInterface(service)
,以将返回的参数转换成 *YourServiceInterface*
类型。例如:
客户端
在客户端添加同样的AIDL文件
1.创建AIDL文件
package com.tic.aidls;
// Declare any non-default types here with import statements
interface IIotAidlInterface {
/**
* @param lockNum 锁号
* @return result 开门状态 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);
}
服务端
class IotService : Service() {
val mCallbacks: RemoteCallbackList = RemoteCallbackList()
override fun onBind(intent: Intent): IBinder {
return binder
}
//第二部实现接口
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
}
}
}