ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AIDL 接口中间插入方法导致第三方调用异常

AIDL 接口中间插入方法导致第三方调用异常 AIDL 接口中间插入方法导致第三方调用异常问题现象IServiceAidlInterface新增unInit接口后未更新 AIDL 的第三方 App 出现start()调用正常registerListener()调用异常根本原因AIDL Transaction Code 机制AIDL 基于 Android Binder IPC客户端调用服务端方法时传递的不是方法名而是一个整数编号transaction code。Android 编译器按.aidl文件中方法的声明顺序从 1 开始依次分配该编号。两端客户端 Proxy / 服务端 Stub各自根据自己持有的.aidl文件生成代码调用链如下客户端 Proxy 服务端 Stub registerListener() → 发送 codeN → onTransact(codeN) → 路由到第 N 个方法只要两端 code 映射一致通信正常。一旦在接口中间插入新方法后续所有方法的 code 全部错位两端映射不再匹配。本次变更的错位分析unInit被插入在stop和registerListener之间Transaction Code服务端新 AIDL第三方客户端旧 AIDL结果1start()start()✅ 正常2stop()stop()✅ 正常3unInit()registerListener()❌ 异常4registerListener()unregisterListener()❌ 异常5unregisterListener()(不存在)❌ 异常第三方调用registerListener()时发送 code 3服务端将 code 3 路由到unInit()参数类型不匹配调用异常start()仍是 code 1两端一致所以不受影响修复方案新增 AIDL 方法必须追加到接口末尾严禁插入到已有方法之间。interface IServiceAidlInterface { // ── 原有方法顺序和位置不变 ────────────────────────────── int start(); int stop(); void registerListener(in IServiceListener listener); void unregisterListener(in IServiceListener listener); // ── 新增方法统一追加到末尾 ──────────────────────────────── int unInit(); }这样旧客户端持有的所有 transaction code 映射保持不变向后兼容。规范约束操作是否允许在接口末尾追加新方法✅ 允许在已有方法之间插入新方法❌ 禁止删除或重排已有方法❌ 禁止修改已有方法的参数类型或顺序❌ 禁止AIDL 接口一旦对外发布已有方法的顺序、签名、位置均不可更改只能在末尾追加扩展。这与 Protobuf 字段编号、COM 接口 vtable 布局遵循同样的原则。
返回列表