AIDL是Android多进程通讯方式一种。
如要使用 AIDL 创建绑定服务,请执行以下步骤:
- 创建 .aidl 文件
此文件定义带有方法签名的编程接口。
- 实现接口
Android SDK 工具会基于您的
.aidl
文件,使用 Java 编程语言生成接口。此接口拥有一个名为Stub
的内部抽象类,用于扩展Binder
类并实现 AIDL 接口中的方法。您必须扩展Stub
类并实现这些方法。 - 向客户端公开接口
实现
Service
并重写onBind()
,从而返回Stub
类的实现。
以下是 .aidl
文件示例
// IMyAidlInterface.aidl
package com.jason.aidlserver;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
String getInfo() ;
}
服务端实现接口 :
功能实现,由客户端发送数据过来,简单保存一下aString。然后客户端读取时候返回。
class AidlServerService :Service(){
private var aS :String? = "empty"
private val mBinder = object: IMyAidlInterface.Stub (){
override fun basicTypes(
anInt: Int,
aLong: Long,
aBoolean: Boolean,
aFloat: Float,
aDouble: Double,
aString: String?
) {
aS = aString
}
override fun getInfo(): String {
return " RemoteService保存数据 => $aS"
}
}
override fun onBind(intent: Intent?): IBinder {
return mBinder
}
}
然后我们在注册清单 AndroidManifest给server加上权限。
<permission android:name="jason.aidl" android:protectionLevel="normal" /> <uses-permission android:name="jason.aidl" />
<service android:name=".AidlServerService" android:exported="true" android:permission="jason.aidl"> <intent-filter> <action android:name="jason.aidl.action" /> </intent-filter> </service>
这样server端服务已经开发好了,只需要在Activity把这个服务启动即可。
客户端集成接口:
客户端还必须拥有接口类的访问权限,因此如果客户端和服务在不同应用内,则客户端应用的 src/
目录内必须包含 .aidl
文件(该文件会生成 android.os.Binder
接口,进而为客户端提供 AIDL 方法的访问权限)的副本。
代码示例:
class MainActivity : AppCompatActivity() {
private lateinit var tvMsg :TextView
private var autoMex :Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvMsg = findViewById(R.id.tv_msg)
findViewById<Button>(R.id.btn_connect).setOnClickListener {
val intent = Intent( "jason.aidl.action")
intent.setClassName("com.jason.aidlserver","com.jason.aidlserver.AidlServerService")
bindService(intent,connect, Context.BIND_AUTO_CREATE)
}
findViewById<Button>(R.id.btn_send).setOnClickListener {
remoteService?.basicTypes(1,2L,true,1.5F,2.5,"haha ${autoMex ++}")
}
findViewById<Button>(R.id.btn_get).setOnClickListener {
tvMsg.text = remoteService?.info
}
}
private var remoteService :IMyAidlInterface ? = null
private val connect = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
remoteService = IMyAidlInterface.Stub.asInterface(service)
tvMsg.text = "onServiceConnected"
}
override fun onServiceDisconnected(name: ComponentName?) {
remoteService= null
tvMsg.text = "onServiceDisconnected"
}
}
override fun onDestroy() {
unbindService(connect)
super.onDestroy()
}
}
因为我们给server端记上了权限,那么客户端需要把对应权限加上 。否者会权限错误无法连接到远程服务。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jason.aidlclient"> <!--sdk 30后需要加上 --> <queries> <package android:name="com.jason.aidlserver"/> </queries> <!--加上服务权限 --> <uses-permission android:name="jason.aidl"/>
展示效果:
通过 IPC 传递对象
可以通过 IPC 接口,将某个类从一个进程发送至另一个进程。不过,您必须确保 IPC 通道的另一端可使用该类的代码,并且该类必须支持 Parcelable
接口。支持 Parcelable
接口很重要,因为 Android 系统能通过该接口将对象分解成可编组至各进程的原语。
如要创建支持 Parcelable
协议的类,您必须执行以下操作:
- 让您的类实现
Parcelable
接口。 - 实现
writeToParcel
,它会获取对象的当前状态并将其写入Parcel
。 - 为您的类添加
CREATOR
静态字段,该字段是实现Parcelable.Creator
接口的对象。 - 最后,创建声明 Parcelable 类的
.aidl
文件。如果您使用的是自定义编译进程,请勿在您的构建中添加
.aidl
文件。此.aidl
文件与 C 语言中的头文件类似,并未经过编译。
AIDL 会在其生成的代码中使用这些方法和字段,以对您的对象进行编组和解编。
AIDL官方文档指南: Android 接口定义语言 (AIDL) | Android 开发者 | Android Developershttps://developer.android.google.cn/guide/components/aidl?hl=zh-cn#Expose