简体   繁体   English

如何在Android中正确升级AIDL接口?

[英]How to properly upgrade AIDL interfaces in Android?

I have two apps: One is called my-app.apk , the other my-service.apk . 我有两个应用程序:一个叫做my-app.apk ,另一个叫做my-service.apk The service app just defines a single Android Service , which can be bound by the primary app to execute some methods. 服务应用程序仅定义了一个Android Service ,该服务可以与主应用程序绑定以执行某些方法。 This is done using Androids AIDL interface, and it works great - so far. 这是使用Android的AIDL界面完成的,到目前为止效果很好。

Now I want to change the interface of the service, and I am wondering what I have to watch out for. 现在,我想更改服务的接口,我想知道我需要注意什么。 I changed the file IRemote.aidl of my-service.apk to the following: 我将my-service.apk的文件IRemote.aidl更改为以下内容:

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

And just out of curiosity I changed the IRemote.aidl of my-app.apk to the following (note the differences!): 出于好奇,我将my-app.apk的IRemote.aidl更改为以下内容(请注意区别!):

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

Now I got a completely unexpected result: The call to 现在,我得到了一个完全出乎意料的结果:

printYeahThisHasADifferentNameAndParam("hello world");

from my application resulted in the log output "11". 从我的应用程序导致日志输出“ 11”。 Why?? 为什么??

  1. I would not have expected a SecurityException at the bindService() call, although this would be adequate in a situation with completely different interfaces. 我不希望在bindService()调用时出现SecurityException ,尽管在接口完全不同的情况下这是足够的。
  2. What I would have expected would have been a RemoteException when executing the call, telling me that the method is not available. 在执行调用时,我本来希望得到的是RemoteException ,告诉我该方法不可用。
  3. What I didn't expect entirely was that it will just call a different method with different data as parameters. 完全没想到的是,它只会调用具有不同数据作为参数的不同方法。 Although I can understand it from a low-level point of view. 尽管我可以从低层次的角度理解它。 Maybe they did it to ensure this interface is performant... 也许他们这样做是为了确保此界面性能良好...

So here are my questions: 所以这是我的问题:

  1. What is the best upgrade-strategy? 最佳的升级策略是什么? Simply do not delete/alter old methods and order? 根本不删除/更改旧的方法和顺序?
  2. I noticed when my-service.apk is upgraded (re-installed) the service gets lost for my-app.apk . 我注意到升级(重新安装) my-service.apk时,该服务对于my-app.apk丢失了。 Normally the service gets re-scheduled by the system, which it typically does on crashes. 通常,服务会由系统重新安排,通常在崩溃时执行。 How do I ensure my-app.apk aquires the service again? 如何确保my-app.apk再次获得服务? Watch out for newly installed packages? 当心新安装的软件包吗?

Thank you in advance for your help! 预先感谢您的帮助! :-) :-)

Cheers, Marc 干杯,马克

If you take a look at the code generated by the AIDL compiler, you will see that RPC via Binder calls methods by sequential number. 如果看一下AIDL编译器生成的代码,您将看到RPC通过Binder通过顺序号调用方法。 Every method in the interface gets number assigned, like: 接口中的每个方法都会分配编号,例如:

       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,

This number is then used by the calling side to map called method to flat Parcel buffer and by receiving side of IPC to select the generated method to unmarshall the serialized parameters data and finally call the real implementation. 然后,调用方使用此编号将调用的方法映射到平坦的Parcel缓冲区,IPC的接收方使用此编号选择生成的方法以解组序列化的参数数据,最后调用实际实现。

Thus if you replace the method number 1 definition on the calling side, but still have old implementation on the receiving side, you will call the old implementation with completely bogus data. 因此,如果在调用方替换了方法1定义,但在接收方仍然有旧的实现,则将使用完全伪造的数据来调用旧的实现。 There is no type information in the serialized Parcel data of method arguments (besides the method number itself), so it will happily deserialize new method call parameters buffer as old ones and try to call implementation. 方法参数的序列化Parcel数据中没有类型信息(除了方法号本身),因此它将愉快地将新方法调用参数缓冲区反序列化为旧参数,并尝试调用实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM