问题:客户反馈内置的应用升级成功后立刻断电重启,应用的版本被恢复。
使用adb命令升级客户应用,查看版本显示已更新,/data/system目录下packages.xml和packages.xml中应用版本信息均已更新
C:\Users\dell>adb shell dumpsys package com.xxx.xxx | findstr version
versionCode=85 minSdk=21 targetSdk=28
versionName=1.0.1.0
signatures=PackageSignatures{d02434f version:2, signatures:[b414bf3f], past signatures:[]}
versionCode=6 minSdk=21 targetSdk=28
versionName=1.0.0.5
signatures=PackageSignatures{9ec2ba version:0, signatures:[], past signatures:[]}
C:\Users\dell>
立刻断电重启,结果是应用版本恢复为升级前,packages.xml和packages.xml中应用版本也恢复为升级前。
抓取开机时的部分log
D PackageManager: Scanning app dir /system/app scanFlags=66064 flags=0x10
D PackageParser2: Parse times for '/system/app/Huaxinan': parse=103ms, update_cache=16 ms
D PackageManager: updatedPkg = PackageSetting{dd36952 com.hxa.liquorDetection/10072}
W PackageManager: Failed to scan /system/app/Huaxinan: Package com.hxa.liquorDetection at /system/app/Huaxinan ignored: updated version 85 better than this 6
D PackageParsing: Scanning base APK: /system/app/SimAppDialog/SimAppDialog.apk
...
D PackageManager: Scanning app dir /data/app scanFlags=656 flags=0x0
D ziparchive: Zip: EOCD not found, /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk is not zip
E system_server: Failed to open APK '/data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk' Invalid file
W PackageManager: Failed to parse /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==: Failed to parse /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk
W PackageManager: Deleting invalid package at /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==
D PackageParsing: Scanning base APK: /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==/base.apk
D PackageManager: updatedPkg = PackageSetting{dd36952 com.hxa.liquorDetection/10072}
I PackageManager: /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A== changed; collecting certs
W PackageManager: Relax SCAN_REQUIRE_KNOWN requirement for package com.hxa.liquorDetection
I PackageManager: Update system package com.hxa.liquorDetection code path from /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw== to /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==; Retain data and using new
I PackageManager: Update system package com.hxa.liquorDetection resource path from /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw== to /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==; Retain data and using new
I PackageManager: Finished scanning non-system apps. Time: 172 ms, packageCount: 2 , timePerPackage: 86 , cached: 0
- 源码:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
// The version of the application on the /system partition is less than or
// equal to the version on the /data partition. Throw an exception and use
// the application already installed on the /data partition.
throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName()
+ " at " + parsedPackage.getCodePath() + " ignored: updated version "
+ pkgSetting.versionCode + " better than this "
+ parsedPackage.getLongVersionCode());
}
...
if (throwable == null) {
// TODO(toddke): move lower in the scan chain
// Static shared libraries have synthetic package names
if (parseResult.parsedPackage.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.parsedPackage);
}
try {
addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
currentTime, null);
} catch (PackageManagerException e) {
errorCode = e.error;
Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
}
} else if (throwable instanceof PackageParserException) {
PackageParserException e = (PackageParserException)throwable;
errorCode = e.error;
Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage())
} else {
throw new IllegalStateException("Unexpected exception occurred while parsing "
+ parseResult.scanFile, throwable);
}
结合log和源码 看是解析/system/app/Huaxinan下的apk时,发现有新的版本85比6版本更好,然后抛出一个PackageManagerException异常,选择使用/data分区上的版本;
接着到扫描/data/app目录,log显示解析文件失败抛出一个PackageParserException的异常,错误码是INSTALL_PARSE_FAILED_NOT_APK,接着扫描/data/app下应用另一个版本目录。
看到此处的log有点怀疑是不是应用缓存没有清除或者哪里没有同步,在应用升级成功后/data/app下只看到当前版本的相关文件,并没有第二个此应用目录文件。
验证是否是缓存没有清除导致
①命令重启设备
adb install -r new.apk
adb reboot
设备重启后应用版本显示正常
②清除应用缓存
adb install -r new.apk
adb shell
pm clear com.hxa.liquorDetection
直接断电重启设备,应用版本显示正常。
最佳方式是使用同步,在应用安装成功后直接调用sync同步。
- 源码:frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
boolean showNotification, int userId, String basePackageName, int returnCode,
String msg, Bundle extras) {
if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
Notification notification = PackageInstallerService.buildSuccessNotification(context,
context.getResources()
.getString(update ? R.string.package_updated_device_owner :
R.string.package_installed_device_owner),
basePackageName,
userId);
if (notification != null) {
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(basePackageName,
SystemMessageProto.SystemMessage.NOTE_PACKAGE_STATE,
notification);
}
}
// add start
fileSync();
// add end
...
}
// add start
private static void fileSync(){
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("sync");
} catch (IOException e) {
e.printStackTrace();
android.util.Log.e(TAG, "fileSync");
}
}
// add end
编译后刷机,升级应用直接断电重启设备,应用版本显示正常.
android 设备写入文件,立即断电重启后,文件丢失,数据没有保存问题
apk安装提示 Zip: EOCD not found, /storage/emulated/0/Download/*.apk is not zip