Android 8.0 PKMS新变化之多线程扫描APK

本文分析了Android 8.0中PKMS的改进,特别是引入了多线程扫描APK以提高效率。对比Android 7.0,8.0通过ExecutorService启动线程池,使用ArrayBlockingQueue确保线程安全。虽然默认只有4个线程,但在特定情况下可以考虑增加线程数以优化开机速度。

这里主要针对Android 8.0 在PKMS这块的新变化进行分析,会不断更新
如果发现有错误或者不到位的地方,请指出,谢谢!

回忆一下在Android 7.0是如何扫描APK的:

private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
        long currentTime, UserHandle user) throws PackageManagerException {
    ......
    PackageParser pp = new PackageParser();
    ......
    final PackageParser.Package pkg;
    try {
        pkg = pp.parsePackage(scanFile, parseFlags);
    } 
    ......
    return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}

这样,如果在系统预置APK较多的情况下,必然会导致开机时间变慢
在之前的项目中,我们都是自己加一个简单的多线程来扫描APK
在阅读8.0的代码时发现,google已经为我们添加了这个功能,而且比之前的方案更高端,详细看看
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime)方法中:

private void scanDirLI(File dir, int parseFlags, int scanFlags, 
<think>我们正在处理一个关于Android系统APK卸载的问题,特别是与包管理服务(PKMS)相关的问题。用户可能遇到了卸载问题,或者想了解卸载过程。 根据Android系统的工作原理,APK的卸载是由PackageManagerService(PKMS)管理的。卸载过程涉及多个步骤,包括删除应用程序的数据目录、从包管理器中移除应用信息、发送广播通知等。 我们将按照以下步骤回答: 1. 解释Android APK卸载的基本流程。 2. 讨论可能遇到的问题及其原因。 3. 提供一些解决方案和调试方法。 注意:由于Android系统的复杂性,不同版本可能有所差异,但核心原理相似。 首先,我们来描述卸载流程: 当用户通过系统设置或adb命令卸载一个应用时,系统会触发以下过程: - 系统PKMS发送卸载请求。 - PKMS会检查该应用是否已安装,以及调用者是否有权限卸载。 - 如果应用正在运行,系统会先停止该应用(包括进程和所有服务)。 - PKMS会删除应用的以下部分: - 应用程序的安装目录(如`/data/app/<package-name>`) - 应用程序的数据目录(如`/data/data/<package-name>`) - 如果用户选择,还会删除SD卡上的数据(如`/sdcard/Android/data/<package-name>`) - 更包管理器的数据库(从`packages.xml`和`packages.list`等文件中移除该应用的信息) - 发送广播(如`ACTION_PACKAGE_REMOVED`)通知其他应用该应用已被卸载。 然而,在实际操作中,可能会遇到各种问题,例如: 1. 卸载后应用仍然出现在应用列表中(幽灵应用)。 2. 卸载不彻底,残留文件或数据。 3. 卸载过程中出现错误(如权限不足、存储空间不足等)。 针对这些问题,我们可以提供以下建议: **解决方案:** 1. **重启设备**:有时系统需要重启才能完成卸载后的清理工作。 2. **使用adb命令卸载**:对于通过adb安装的应用,可以使用`adb uninstall <package-name>`来卸载。如果遇到问题,可以尝试`adb uninstall -k <package-name>`(保留数据和缓存目录)然后再手动删除,或者使用`adb shell pm uninstall <package-name>`。 3. **手动删除残留文件**:如果卸载后仍有残留,可以尝试手动删除(需要root权限): - 进入`/data/app/`,删除对应包名的目录。 - 进入`/data/data/`,删除对应包名的目录。 - 检查`/data/dalvik-cache/`目录下是否有残留的dex文件(如`data@app@<package-name>...`),并删除。 - 检查SD卡上的数据目录(`/sdcard/Android/data/<package-name>`和`/sdcard/Android/obb/<package-name>`)并删除。 4. **清除包管理器的缓存信息**:有时包管理器的数据库可能出现问题,可以尝试清除包管理器的缓存: - 进入设置->应用->显示系统应用->找到“包管理器”或“Android系统”->清除缓存和数据(注意:这可能会重置所有应用的偏好设置)。 5. **使用第三方工具**:如Titanium Backup等,可以强制卸载应用。 另外,对于系统应用,卸载可能需要root权限,并且步骤更复杂,通常需要从`/system/app`或`/system/priv-app`中删除对应的apk文件。 如果以上方法都无法解决,可能是系统分区损坏,需要重刷机。 最后,我们生成几个相关问题,以帮助用户进一步了解: §§相关问题§§ 1. 如何通过adb命令卸载Android应用? 2. 卸载系统预装应用的方法是什么? 3. Android包管理器(PackageManager)的工作原理是什么? 4. 如何解决Android应用卸载后重出现的问题?</think>### Android PKMS APK卸载机制与问题解析 Android系统APK卸载由**包管理服务(Package Manager Service, PKMS)** 负责,其核心流程如下: 1. **卸载触发阶段** - 用户通过系统设置或`adb uninstall`发起卸载请求 - PKMS校验调用者权限(需`DELETE_PACKAGES`权限)[^1] 2. **数据清理阶段** PKMS依次删除: - 应用安装目录:`/data/app/<package_name>-xxx` - 私有数据目录:`/data/data/<package_name>` - 外部存储数据:`/sdcard/Android/data/<package_name>` - 优化后的dex文件:`/data/dalvik-cache/*<package_name>*.dex` 3. **数据库更阶段** - 从`/data/system/packages.xml`移除包信息 - 更`/data/system/packages.list`应用列表 - 删除包管理数据库相关记录 4. **系统通知阶段** 发送广播: ```java Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); intent.putExtra(Intent.EXTRA_UID, packageUid); sendBroadcast(intent); ``` #### 常见问题及解决方案 **问题1:残留文件未删除** **原因**:卸载时应用进程未完全终止 **解决**: ```bash adb shell pm disable <package_name> # 先禁用应用 adb shell am force-stop <package_name> # 强制停止进程 adb uninstall <package_name> ``` **问题2:系统应用卸载失败** **原因**:预装应用受系统保护 **解决**(需root): ```bash adb shell su mount -o rw,remount /system rm /system/priv-app/<app_dir>/base.apk ``` **问题3:卸载后图标仍存在** **原因**:启动器缓存未更 **解决**: ```java // 发送强制刷广播 adb shell am broadcast -a android.intent.action.PACKAGE_NEEDS_VERIFICATION -d package:<package_name> ``` **问题4:INSTALL_FAILED_UID_CHANGED错误** **原因**:`/data/system/uiderrors.txt`存在残留记录 **解决**: ```bash adb shell rm /data/system/uiderrors.txt adb reboot ``` #### 调试建议 1. 检查PKMS日志: `adb logcat | grep "PackageManager"` 2. 验证文件系统权限: `adb shell ls -lZ /data/app/` 3. 查看包管理状态: `adb shell dumpsys package <package_name>` > 注:Android 10+引入的**作用域存储**机制可能导致卸载后媒体文件残留,需手动清理`/sdcard/`目录[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值