gpt4 book ai didi

java - Android中如何正确升级AIDL接口(interface)?

转载 作者:行者123 更新时间:2023-11-29 05:43:11 24 4
gpt4 key购买 nike

我有两个应用程序:一个名为 my-app.apk,另一个名为 my-service.apk。服务应用程序只定义一个 Android Service ,它可以被主应用程序绑定(bind)以执行一些方法。这是使用 Androids 完成的 AIDL界面,而且效果很好 - 到目前为止。

现在想换个服务的接口(interface),想知道有什么需要注意的。我将 my-service.apk 的文件 IRemote.aidl 更改为以下内容:

package com.example.myservice;
interface IRemote {
void printHello();
void print(int i);
}

出于好奇,我将 my-app.apk 的 IRemote.aidl 更改为以下内容(注意区别!):

package com.example.myservice;
interface IRemote {
void printHello();
void printYeahThisHasADifferentNameAndParam(String s);
}

现在我得到了一个完全出乎意料的结果:调用

printYeahThisHasADifferentNameAndParam("hello world");

我的应用程序导致日志输出“11”。为什么??

  1. 我没想到会在调用 bindService() 时出现 SecurityException,尽管这在具有完全不同接口(interface)的情况下已经足够了。
  2. 我所期望的是在执行调用时出现 RemoteException,告诉我该方法不可用。
  3. 完全没有想到的是它只会调用一个不同的方法,将不同的数据作为参数。虽然我可以从低级的角度理解。也许他们这样做是为了确保这个界面的性能......

所以这是我的问题:

  1. 最好的升级策略是什么?只是不要删除/更改旧方法和顺序?
  2. 我注意到当 my-service.apk 升级(重新安装)时,my-app.apk 的服务丢失了。通常,系统会重新安排服务,这通常是在崩溃时进行的。我如何确保 my-app.apk 再次获取该服务?留意新安装的软件包?

预先感谢您的帮助! :-)

干杯,马克

最佳答案

如果您查看 AIDL 编译器生成的代码,您会发现 RPC 通过 Binder 按序号调用方法。接口(interface)中的每个方法都分配了编号,例如:

       SIZE = ::android::IBinder::FIRST_CALL_TRANSACTION + 0,
SETSIZE = ::android::IBinder::FIRST_CALL_TRANSACTION + 1,
READ = ::android::IBinder::FIRST_CALL_TRANSACTION + 2,
WRITE = ::android::IBinder::FIRST_CALL_TRANSACTION + 3,
SYNC = ::android::IBinder::FIRST_CALL_TRANSACTION + 4,

然后调用方使用此编号将调用的方法映射到平面 Parcel 缓冲区,并由 IPC 的接收方选择生成的方法来解码序列化参数数据并最终调用真正的实现。

因此,如果您在调用方替换了方法编号 1 的定义,但在接收方仍然有旧的实现,您将使用完全虚假的数据调用旧的实现。方法参数的序列化 Parcel 数据中没有类型信息(除了方法号本身),因此它会愉快地将新方法调用参数缓冲区反序列化为旧参数缓冲区并尝试调用实现。

关于java - Android中如何正确升级AIDL接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16817030/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com