关于 installing-and-managing-apps
这项 Android 开发技能指南介绍如何通过 adb 和 pm 管理 APK、包及应用状态,面向编写测试和维护 Android CI 的开发者。重点说明用 pm clear 清理测试数据,并涵盖安装选项、权限和常见错误排查。
主要功能
- 01安装及更新 APK
- 02用 pm clear 重置应用数据
- 03查询和检查已安装包
- 04授予、撤销运行时权限
- 05启用、停用及卸载应用
- 06排查安装失败原因
适用场景
- 01在重复测试前清除应用数据
- 02安装测试 APK 或拆分 APK
- 03为测试配置运行时权限
- 04诊断版本降级或签名错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill installing-and-managing-apps安装后在 Claude Code 中输入/installing-and-managing-apps确认已加载。
详细介绍
安装和管理应用 — adb install 和 pm
从主机管理应用生命周期。adb install 用于推送 APK;pm 是设备端 PackageManager 的前端,可列出应用、查看路径、清除数据、启用或停用应用,以及授予权限。测试脚手架中最常见的隐蔽 bug,是在测试之间用 am force-stop 来“重置”应用——该命令会终止进程,但不会清除 SharedPreferences、Room 数据库和磁盘上的文件。要实现隔离环境下的重置,应使用 pm clear。
适用场景
- 用户想从主机安装 APK,或在每次测试运行之间推送调试构建。
- 用户询问“如何在测试之间重置应用状态?”,或发现数据在不同测试之间残留。
- 用户遇到
INSTALL_FAILED_VERSION_DOWNGRADE、INSTALL_FAILED_USER_RESTRICTED或签名不匹配错误。 - 用户想在安装时授予所有运行时权限(
-g),或在安装后授予或撤销单项权限。 - 用户想只列出第三方软件包、查找磁盘上的 APK,或导出基准配置文件。
不适用场景
- 用户想针对已安装的应用实际运行插桩测试——请使用
../../tests/running-instrumented-tests-via-adb/SKILL.md。 - 用户想选择设备或等待启动完成——请使用
../../devices/connecting-to-devices/SKILL.md。 - 用户想了解架构、环境或身份验证概况——请使用
../../architecture/understanding-adb-architecture/SKILL.md。
先决条件
- 已连接且状态为
device的设备(参见../../devices/connecting-to-devices/SKILL.md)。 - APK 已使用开发者控制的调试密钥或发布密钥签名。
- 对于测试 APK,清单需设置
android:testOnly="true"(Gradle 会为androidTest构建设置此项),且安装时需要-t。 - 对于运行时权限,设备运行的 API 级别需为 23 或更高。
工作流
-
1. 使用正确的标志安装。
pm install(以及adb install封装命令)的选项表:标志 含义 -r“重新安装现有应用,并保留其数据。”当软件包已安装时必须使用;否则 adb install会返回INSTALL_FAILED_ALREADY_EXISTS。CI 脚本在重复运行时必须始终传入-r。-d“允许版本代码降级。”当新 APK 的 versionCode较低时需要。注意:根据adb help,在原生系统构建中,此标志仅适用于可调试软件包。-t“允许安装测试 APK。”任何清单包含 android:testOnly="true"的 APK(即所有 GradleandroidTest构建)都必须使用此标志。-g“授予应用清单中列出的所有权限。”最适合隔离环境下的测试运行。 -l对应用启用前向锁定(旧版 DRM)。如今几乎不会用到。 -s安装到 SD 卡/外部存储(设备支持时)。 --user <id>为指定用户配置文件安装。默认:所有用户。 current会解析为前台用户。`--install-location 0 1 -f安装到系统内部存储。 -i <installer_pkg>为安装标记安装程序软件包名称。 --fastdeploy仅安装补丁(只更新 APK 中已更改的部分)。 --incremental/--no-incremental流式安装;需要 APK Signature Scheme v4 的附属文件 .idsig。--wait会阻塞,直到完整 APK 可用。常用示例:
adb install -r app-debug.apk # 普通重新安装 adb install -r -d app-debug.apk # 允许降级 adb install -r -t -g app-androidTest.apk # 安装测试 APK 并授予所有权限 adb install -r -d --user current app-debug.apk # 强制为前台用户安装 -
2. 对于拆分 APK,请使用
adb install-multiple。 现代 App Bundle 会生成一个基础 APK,以及按功能/配置拆分的 APK;只用adb install安装其中一个会失败:adb install-multiple -r -t -g \ base-master.apk base-arm64_v8a.apk base-xxhdpi.apk -
3. 在测试之间使用
pm clear重置应用状态。切勿使用am force-stop实现隔离。am force-stop <pkg>:“强制停止与package关联的所有内容。”——只会终止进程。SharedPreferences、Room/SQLite 数据库、/data/data/<pkg>中的文件和缓存都会保留。pm clear <pkg>:“删除与软件包关联的所有数据。”——会清除用户数据和缓存。下次启动时,应用将处于全新安装状态。 要在测试之间实现真正的隔离(仪器测试套件的默认设置),请使用pm clear。只有在明确需要终止进程并保留状态时(例如测试“从进程被终止后恢复”的流程),才适合使用am force-stop。
adb shell pm clear com.example.app大多数流水线会通过 Test Orchestrator 的
clearPackageData仪器测试参数来配置此项——参见../../tests/running-instrumented-tests-via-adb/SKILL.md。 -
4. 使用
pm list packages和pm path列出、查找和检查软件包。pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user <id>] [<filter>]标志 含义 -f“查看关联文件。” -d“仅显示已停用的软件包。” -e“仅显示已启用的软件包。” -s“仅显示系统软件包。” -3“仅显示第三方软件包。” -i“查看软件包的安装程序。” -u“包含已卸载的软件包。” --user <id>“要查询的用户空间。” 示例:
adb shell pm list packages -3 | sort # 所有侧载应用 adb shell pm list packages -f com.example # 匹配软件包的 APK 路径 adb shell pm path com.example.app # package:/data/app/.../base.apk adb shell dumpsys package com.example.app | head -200 # 详细的安装/权限信息 -
5. 使用
pm grant/pm revoke管理运行时权限(API 23+)。“向应用授予权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,该权限可以是应用清单中声明的任意权限。”
adb shell pm grant com.example.app android.permission.CAMERA adb shell pm revoke com.example.app android.permission.CAMERA adb shell pm reset-permissions # 将所有应用重置为默认设置在安装时指定
-g标志,可一次性授予清单中声明的所有运行时权限——这也是运行隔离测试的首选方式。 -
6. 启用/停用软件包或特定组件。
adb shell pm disable com.example.app # 整个软件包 adb shell pm disable-user --user 0 com.example.app # 按用户停用(保留数据) adb shell pm enable com.example.app adb shell pm enable com.example.app/.MyTestActivity # 特定组件这可用于在测试中强制设置已知的无障碍服务/IME 状态,或通过停用竞品来安排 A/B 对比。
-
7. 正确卸载。
pm uninstall [-k] [--user <id>] [--versionCode <vc>] <package>-k“移除软件包后保留数据和缓存目录。”适用于从干净状态升级的测试,此时用户数据可模拟已有安装。--user <id>按用户移除。--versionCode <vc>“仅当应用具有指定版本代码时才卸载。”可在 CI 脚本中实现幂等卸载。
adb uninstall com.example.app # 等价于:pm uninstall <pkg> adb shell pm uninstall -k com.example.app # 卸载但保留数据 adb shell pm uninstall --user 0 com.example.app # 仅对主用户卸载 -
8. 按需转储基准配置文件。
“从 Android 7.0(API 级别 24)开始,Android Runtime(ART)会收集已安装应用的执行配置文件……运行
adb shell cmd package dump-profiles <package>,然后运行adb pull /data/misc/profman/<package>.prof.txt。” 文档警告:“只有拥有文件系统的 root 访问权限时,才可能获取执行配置文件名,例如在模拟器上。”对于没有 root 权限的用户版本,请使用androidx.benchmarkMacrobenchmark 以编程方式提取配置文件。 -
9. 诊断常见安装失败问题:
错误 原因 修复方法 INSTALL_FAILED_VERSION_DOWNGRADE新 APK 的 versionCode低于已安装版本。添加 -d。INSTALL_FAILED_USER_RESTRICTED多用户设备:安装用户(通常是次要用户或工作资料)禁止安装。 使用 --user 0或--user current;让用户在自己的资料中停用“通过 USB 安装”限制。INSTALL_FAILED_UPDATE_INCOMPATIBLE(签名不匹配)新 APK 使用的签名密钥与已安装版本不同。 先卸载( adb uninstall <pkg>);使用相同密钥重新签名。INSTALL_FAILED_TEST_ONLYAPK 设置了 android:testOnly="true",但省略了-t。添加 -t(常见于app-androidTest.apk)。INSTALL_FAILED_INVALID_APK(仅限拆分 APK)尝试安装拆分 APK 集中的一个 APK。 使用 adb install-multiple。INSTALL_FAILED_INSUFFICIENT_STORAGE存储空间不足。 运行 adb shell df /data并清理空间。 -
10. 正确引用 Shell 参数(Platform Tools 23+ 规则)。 adb 页面原文:
“使用 Android Platform Tools 23 及更高版本时,
adb处理参数的方式与ssh(1)命令相同。……现在,adb shell setprop key 'two words'会报错……要让命令正常运行,需要像使用ssh(1)一样引用两次,一次用于本地 Shell,一次用于远程 Shell。例如,adb shell setprop key \"'two words'\"可以正常运行,因为本地 Shell 会处理外层引号,而设备仍会看到内层引号。” 同一规则也适用于任何包含空格、特殊字符或 Shell 元字符的pm参数。
模式
模式:错误与正确 — 在测试之间重置应用状态
# WRONG
adb shell am force-stop com.example.app
# Run next test...
# WRONG because: force-stop kills the process but leaves SharedPreferences,
# Room DB, files in /data/data/<pkg>, and cache. Tests that read any of those
# carry stale state into the next case. Flake follows.
# RIGHT
adb shell pm clear com.example.app
# Run next test against fresh-install state.
对于测试运行,运行器本身执行的等效操作是向 AndroidX Test Orchestrator 传入 -e clearPackageData true — 请参阅 ../../tests/running-instrumented-tests-via-adb/SKILL.md。
模式:错误与正确 — 安装 androidTest APK
# WRONG
adb install app-androidTest.apk
# adb: failed to install app-androidTest.apk: Failure [INSTALL_FAILED_TEST_ONLY:
# installPackageLI]
# WRONG because: any APK with android:testOnly="true" (every Gradle-built test
# APK) requires `-t`.
# RIGHT
adb install -r -t -g app-androidTest.apk
# -r: reinstall keeping data (or overwriting); -t: allow test packages;
# -g: grant all runtime permissions for hermetic tests.
模式:错误与正确 — 调试安装后降级版本
# WRONG
adb install -r app-release.apk
# adb: failed to install app-release.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE]
# WRONG because: the installed debug APK has a higher versionCode than the
# release APK being installed.
# RIGHT
adb install -r -d app-release.apk # allow downgrade
# Or, when signature also changes:
adb uninstall com.example.app
adb install app-release.apk
模式:错误与正确 — 仅列出第三方软件包
# WRONG
adb shell pm list packages | grep -v 'com.android'
# WRONG because: many third-party packages also have names containing
# "com.android" (e.g. third-party Android library demos), and Google's own
# pre-installed apps carry varied prefixes (com.google.android.*).
# RIGHT
adb shell pm list packages -3
# `-3` filters to third-party (non-system) packages only.
强制规则
- 必须在测试之间使用
pm clear <pkg>重置应用状态;am force-stop不会清除数据。 - 必须在安装任何测试 APK(
android:testOnly="true")时添加-t;降级时添加-d;添加-g以授予所有清单中的运行时权限。 - 必须对拆分 APK(App Bundles)使用
adb install-multiple。单独安装一个拆分 APK 会失败,并报错INSTALL_FAILED_INVALID_APK。 - 不得假设使用
adb install安装刚构建的调试 APK 能替换已安装的发布版签名 APK——签名冲突错误需要先卸载。 - 不得依赖
pm list packages | grep启发式筛选;应使用文档中列出的筛选项(-3、-s、-d、-e、-u)。 - **首选:**通过 Test Orchestrator 配置
clearPackageData true(../../tests/running-instrumented-tests-via-adb/SKILL.md),而不是在每次测试前手动运行pm clear。 - **首选:**当字符串参数包含空格或 shell 元字符时,使用双重引号括起(Platform Tools 23+ 要求如此,即 SSH 风格的引号)。
验证
-
adb install -r -t -g app-androidTest.apk返回Success。 -
adb shell pm path com.example.app会为刚安装的软件包输出一行package:/data/app/...base.apk。 -
adb shell pm clear com.example.app返回Success,且adb shell run-as com.example.app ls /data/data/com.example.app仅显示新建的cache/和code_cache/条目。 - 安装后,
adb shell pm list packages -3 | grep com.example.app会列出该软件包。 - 执行
adb shell pm grant com.example.app android.permission.CAMERA后,adb shell dumpsys package com.example.app | grep CAMERA会显示该权限已授予。 -
adb uninstall com.example.app返回Success,且pm list packages com.example不再显示该应用。 - CI 运行会通过 Orchestrator(
-e clearPackageData true)或@Before/@After中明确的pm clear步骤,在测试之间清除应用状态。
参考资料
- ADB 用户指南(
pm install、pm uninstall、pm clear、pm grant、pm list packages):https://developer.android.com/tools/adb#pm - AGP/Studio 命令行测试(
am instrument和 Orchestrator 配置):https://developer.android.com/studio/test/command-line - 通过
cmd package dump-profiles转储 Baseline Profile:https://developer.android.com/topic/performance/baselineprofiles - App Bundle / 拆分 APK 安装:https://developer.android.com/studio/build/build-variants
tasks/research/A2-adb-shell-commands.md—pm install/pm list/pm clear标志表原文、force-stop与pm clear的区别,以及 Platform Tools 23 起的 SSH 风格双重 shell 引号。docs/CORPUS.md§I.10 — “force-stop 不会清除数据——应配合pm clear进行独立重置。”- 相关技能:
- 高层架构:
../../architecture/understanding-adb-architecture/SKILL.md - 连接设备:
../../devices/connecting-to-devices/SKILL.md - 无线 ADB:
../../devices/connecting-over-wifi/SKILL.md - 通过
am instrument运行测试(以及 Orchestrator 的clearPackageData):../../tests/running-instrumented-tests-via-adb/SKILL.md
- 高层架构:
- 跨类别相关内容:
- 使用
AndroidJUnit4运行插桩测试:../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md - 在 Android 上配置 JUnit4:
../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.md - 源集策略:
../../../fundamentals/strategies/organizing-test-source-sets/SKILL.md
- 使用