我在一个基于AOSP 8.1的自定义操作系统上工作。我有一个系统应用(在systempriv-app中),它有一个导出的广播接收器。这意味着它可以接受来自应用程序外部的Intents。如果我对广播接收器进行重构,例如更改其包的位置或类名,并使用 "adb install -r ... "安装更新后的APK,一切都很好,广播接收器可以接收意图。
然而,如果我用新的应用程序(APK + VDEX + ODEX)制作一个OTP图像,并从恢复中闪现它,应用程序就会崩溃,因为Android仍然试图引用旧的广播接收器类。
AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.example.app.receiver.ExampleReceiver: java.lang.ClassNotFoundException: Didn't find class "com.example.app.receiver.ExampleReceiver" on path: DexPathList[[zip file "/system/priv-app/ExampleApp/ExampleApp.apk"],nativeLibraryDirectories=[/system/priv-app/ExampleApp/lib/arm, /system/lib, /vendor/lib, /system/lib, /vendor/lib]]
它试图引用 com.example.app.receiver.ExampleReceiver
但新的班级是 com.example.app.receiver.NewReceiver
. 旧的在某个地方 "缓存 "了。
我可以模拟同样的问题,重新挂载系统分区RW,然后使用 adb push ...
来替换新的APK、ODEX和VDEX文件。奇怪的是,如果我 删去 从系统中取出ODEX和VDEX文件,一切都很好,因为显然这个行为迫使Android再次解析APK。
据我所知 PackageManager
系统应用程序应该能够检测到应用程序何时更新,并解析导出的部分(如广播接收器和活动的类)。不幸的是,这并没有发生。
我也猜测这是在OTA后Android显示 "优化应用xxx "时发生的事情,但这在这里没有发生。这个过程应该怎么触发呢?
包管理器服务的安卓源码 有以下几行。
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
... some other code
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
... cache clearing logic
ver.fingerprint = Build.FINGERPRINT;
}
也就是说,如果改变了构建指纹,代码缓存将被清除。出现这个问题的原因可能是你的 OTA 软件包的指纹和它所安装的系统相同。
检查你的makefile,并确保你为每次编译生成了一个唯一的指纹。
指纹值可以在 "systembuildprops "文件中找到。所以你可以检查是否是这个问题。