一、AIDL基础

AIDL(Android Interface Definition Language) 是Android用于跨进程通信的接口定义语言,基于Binder机制实现。
核心流程:

  1. 定义接口(.aidl文件)
  2. 实现接口(服务端)
  3. 绑定服务(客户端)
  4. 跨进程调用

二、Demo

  1. 定义AIDL接口
    文件:ICalculator.aidl
// ICalculator.aidl  
package com.example.aidldemo;  

interface ICalculator {  
    int add(int a, int b);  
    int subtract(int a, int b);  
}  
  1. 实现服务端
    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()  
    }  
}  

三、传递自定义对象

  1. 定义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();  
}  
  1. 实现服务端
    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  
}  
  1. 客户端调用
val userManager = IUserManager.Stub.asInterface(service)  
userManager.addUser(User(1, "Alice"))  
val userList = userManager.users // 获取用户列表  

四、关键问题与解决方案

  1. 线程模型

    • 服务端方法默认运行在Binder线程池
    • 解决方案:
      override fun addUser(user: User) {  
          // 切换到主线程更新UI  
          Handler(Looper.getMainLooper()).post {  
              // 更新UI操作  
          }  
      }  
      
  2. 异常处理

try {  
    val result = calculator?.add(5, 3)  
} catch (e: RemoteException) {  
    Log.e("AIDL", "Remote call failed", e)  
}  
  1. 权限控制
    服务端验证权限:
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 → 启动重连 → 指数退避重试
├─ 成功 → 重置重试计数
└─ 失败 → 提示用户

  1. 检测服务端断连
    通过 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即可
}
  1. 自动重连策略
    指数退避重连
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)
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐