mcpField
I
installing-and-managing-apps

installing-and-managing-apps

github.com/skydoves开发33975 次安装22 周前更新
代码仓库

关于 installing-and-managing-apps

这项 Android 开发技能指南介绍如何通过 adb 和 pm 管理 APK、包及应用状态,面向编写测试和维护 Android CI 的开发者。重点说明用 pm clear 清理测试数据,并涵盖安装选项、权限和常见错误排查。

主要功能

  1. 01安装及更新 APK
  2. 02用 pm clear 重置应用数据
  3. 03查询和检查已安装包
  4. 04授予、撤销运行时权限
  5. 05启用、停用及卸载应用
  6. 06排查安装失败原因

适用场景

  1. 01在重复测试前清除应用数据
  2. 02安装测试 APK 或拆分 APK
  3. 03为测试配置运行时权限
  4. 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(即所有 Gradle androidTest 构建)都必须使用此标志。
    -g“授予应用清单中列出的所有权限。”最适合隔离环境下的测试运行。
    -l对应用启用前向锁定(旧版 DRM)。如今几乎不会用到。
    -s安装到 SD 卡/外部存储(设备支持时)。
    --user <id>为指定用户配置文件安装。默认:所有用户。current 会解析为前台用户。
    `--install-location 01
    -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.benchmark Macrobenchmark 以编程方式提取配置文件。

  • 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

评论

支持 Markdown