AIDL简单使用
·
一、AIDL基础
AIDL(Android Interface Definition Language) 是Android用于跨进程通信的接口定义语言,基于Binder机制实现。
核心流程:
- 定义接口(.aidl文件)
- 实现接口(服务端)
- 绑定服务(客户端)
- 跨进程调用
二、Demo
- 定义AIDL接口
文件:ICalculator.aidl
// ICalculator.aidl
package com.example.aidldemo;
interface ICalculator {
int add(int a, int b);
int subtract(int a, int b);
}
- 实现服务端
CalculatorService.kt
class CalculatorService : Service() {
private val binder = object : ICalculator.Stub() {
override fun add(a: Int, b: Int): Int = a + b
override fun subtract(a: Int, b: Int): Int = a - b
}
override fun onBind(intent: Intent): IBinder = binder
}
AndroidManifest.xml
<service
android:name=".CalculatorService"
android:exported="true"
android:process=":remote"/>
客户端绑定与调用
MainActivity.kt
class MainActivity : AppCompatActivity() {
private var calculator: ICalculator? = null
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
calculator = ICalculator.Stub.asInterface(service)
}
override fun onServiceDisconnected(name: ComponentName?) {
calculator = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindService(
Intent(this, CalculatorService::class.java),
connection,
Context.BIND_AUTO_CREATE
)
// 调用示例
btnAdd.setOnClickListener {
val result = calculator?.add(5, 3) // 输出8
Toast.makeText(this, "Result: $result", Toast.LENGTH_SHORT).show()
}
}
override fun onDestroy() {
unbindService(connection)
super.onDestroy()
}
}
三、传递自定义对象
- 定义Parcelable对象
User.kt
@Parcelize
data class User(val id: Int, val name: String) : Parcelable
IUserManager.aidl
// IUserManager.aidl
package com.example.aidldemo;
import com.example.aidldemo.User;
interface IUserManager {
void addUser(in User user);
List<User> getUsers();
}
- 实现服务端
UserManagerService.kt
class UserManagerService : Service() {
private val users = mutableListOf<User>()
private val binder = object : IUserManager.Stub() {
override fun addUser(user: User) {
users.add(user)
}
override fun getUsers(): MutableList<User> = users
}
override fun onBind(intent: Intent): IBinder = binder
}
- 客户端调用
val userManager = IUserManager.Stub.asInterface(service)
userManager.addUser(User(1, "Alice"))
val userList = userManager.users // 获取用户列表
四、关键问题与解决方案
-
线程模型
- 服务端方法默认运行在Binder线程池
- 解决方案:
override fun addUser(user: User) { // 切换到主线程更新UI Handler(Looper.getMainLooper()).post { // 更新UI操作 } }
-
异常处理
try {
val result = calculator?.add(5, 3)
} catch (e: RemoteException) {
Log.e("AIDL", "Remote call failed", e)
}
- 权限控制
服务端验证权限:
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
val permission = checkCallingOrSelfPermission("com.example.PERMISSION")
if (permission != PackageManager.PERMISSION_GRANTED) {
throw SecurityException("Permission denied")
}
return super.onTransact(code, data, reply, flags)
}
五、性能优化技巧
批量数据传输:
// AIDL接口定义
void addUsers(in List<User> users);
使用oneway非阻塞调用:
oneway void logEvent(in String event);
对象池复用:
private val userPool = Pools.SynchronizedPool<User>(10)
fun getUser(): User = userPool.acquire() ?: User()
fun recycleUser(user: User) = userPool.release(user)
服务端断连处理
服务断开 → onServiceDisconnected/binderDied → 启动重连 → 指数退避重试
├─ 成功 → 重置重试计数
└─ 失败 → 提示用户
- 检测服务端断连
通过 ServiceConnection 监听连接状态
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// 绑定成功
aidlService = IMyAidlInterface.Stub.asInterface(service)
// 添加死亡监听(关键!)
service?.linkToDeath(deathRecipient, 0)
}
override fun onServiceDisconnected(name: ComponentName?) {
// 服务异常断开
aidlService = null
scheduleReconnect() // 触发重连逻辑
}
}
// Binder 死亡监听(更底层)
private val deathRecipient = IBinder.DeathRecipient {
runOnUiThread {
Toast.makeText(this, "服务端进程终止,尝试重连...", Toast.LENGTH_SHORT).show()
scheduleReconnect()
}
}
通过 linkToDeath 监听 Binder 死亡
//更底层监听 Binder 对象存活状态:
private fun registerBinderDeathListener(binder: IBinder?) {
binder?.linkToDeath(object : IBinder.DeathRecipient {
override fun binderDied() {
// Binder死亡(非主线程,需切线程处理)
runOnUiThread {
showToast("服务已断开,正在重连...")
scheduleReconnect()
}
}
}, 0) // flags 传0即可
}
- 自动重连策略
指数退避重连
private var reconnectAttempts = 0
private val maxReconnectAttempts = 5
private val reconnectHandler = Handler(Looper.getMainLooper())
private fun scheduleReconnect() {
if (reconnectAttempts >= maxReconnectAttempts) {
Log.w("AIDL", "超过最大重试次数,放弃重连")
return
}
val delay = 2_000L * (reconnectAttempts + 1) // 2s, 4s, 8s...
reconnectHandler.postDelayed({
bindAidlService()
reconnectAttempts++
}, delay)
}
private fun bindService() {
val intent = Intent(this, CalculatorService::class.java)
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
更多推荐

所有评论(0)