6、应用管理(下):启动、强杀与查底牌

上一节我们把应用的安装、卸载和清除数据聊透了。今天咱们继续往下挖,聊聊怎么用 ADB 命令去操控一个应用的“生死”和“底细”。说白了,就是三个核心动作:启动 Activity强制停止查看应用详情

这三个命令,我几乎每天都会用到。调试的时候,启动一个特定的 Activity 能帮你跳过一堆启动页;遇到应用卡死,强杀比点“强制停止”快得多;而 dumpsys package 简直就是应用的“体检报告”,什么权限、组件、版本号,一目了然。

好,咱们一个一个来。

6.1 启动 Activity:adb shell am start

这个命令,说白了就是“用命令行打开一个界面”。你平时点图标启动应用,本质上也是启动了一个 Activity。但用 ADB 启动,你可以指定启动哪个 Activity,甚至可以带上参数。

基本用法长这样:

adb shell am start -n 包名/Activity全路径

举个例子,我想直接打开微信的聊天列表:

adb shell am start -n com.tencent.mm/.ui.LauncherUI

这里 -n 参数后面跟的就是“包名/Activity名”。注意 Activity 名前面有个点,表示是包名下的相对路径。如果你不知道 Activity 的全名,可以用 dumpsys package 去查,咱们后面会讲。

小技巧: 如果你只想启动应用默认的入口 Activity(就是点图标的那个),可以不用 -n,改用 -p 参数:
adb shell am start -p com.tencent.mm
这样系统会自动找到该包的主 Activity 并启动。我个人习惯用 -p,省得记 Activity 名。

有时候你需要给 Activity 传数据,比如打开一个网页:

adb shell am start -a android.intent.action.VIEW -d "https://www.example.com"

这里 -a 指定 Action,-d 指定数据 URI。这招在调试 Deep Link 时特别有用。我记得有一次测试一个支付页面的跳转,就是用这个命令直接拉起目标页面,省去了在 App 里点来点去的麻烦。

再复杂一点,你还可以加 --es 传字符串,--ei 传整数。比如:

adb shell am start -n com.example.app/.MainActivity --es "key" "value" --ei "count" 10

嗯,这里要注意:参数名和值之间用空格隔开,不要加等号。

6.2 强制停止:adb shell am force-stop

应用卡死了?后台服务抽风了?别慌,用这个命令直接“物理断电”。

adb shell am force-stop 包名

比如:

adb shell am force-stop com.example.app

这个命令的效果,等同于你在系统设置里找到应用,然后点“强制停止”。它会杀掉该应用的所有进程,包括后台服务、广播接收器等等。而且,它不会像 kill 命令那样只杀一个进程,而是把整个应用的所有进程都干掉。

注意: 强制停止后,应用的所有状态都会被清空。下次启动时,它会像第一次打开一样,重新走一遍 Application 的 onCreate。所以,如果你在调试某个需要保持状态的功能,慎用这个命令。

我曾经在调试一个推送服务时,发现推送总是收不到。查了半天,原来是我之前用 force-stop 把应用杀了,而推送服务需要在后台运行。后来我改用 adb shell am kill 只杀前台进程,才解决问题。所以,force-stop 是核武器,别乱用

另外,这个命令不需要 root 权限,普通用户就能执行。但要注意,它只能停止你调试的应用(即 debuggable 的应用),或者系统应用。对于普通第三方应用,你可能没有权限去强杀。

6.3 查看应用详情:adb shell dumpsys package

这个命令,是我认为 ADB 里最强大的命令之一。它能把一个应用的所有信息都 dump 出来,简直就是应用的“户口本”。

基本用法:

adb shell dumpsys package 包名

比如:

adb shell dumpsys package com.example.app

输出内容会非常长,包含几十个字段。我挑几个最常用的给你说说:

字段 说明 示例
versionName 应用的版本号(给用户看的) 2.3.1
versionCode 应用的版本号(给系统看的,整数) 231
firstInstallTime 首次安装时间 2024-01-15 10:30:00
lastUpdateTime 最近更新时间 2024-03-20 14:22:00
signatures 应用的签名信息(用于校验包是否被篡改) [B@1a2b3c4d
requestedPermissions 应用声明的所有权限 android.permission.CAMERA
activities 应用所有的 Activity 列表 .MainActivity, .SettingsActivity

你可能会问:这么多信息,我怎么快速找到我想要的?

我的习惯是,用 grep 过滤。比如我只想看版本信息:

adb shell dumpsys package com.example.app | grep -E "versionName|versionCode"

或者只看权限:

adb shell dumpsys package com.example.app | grep "permission"

嗯,这里有个坑:dumpsys package 的输出里,权限列表是分两块的——requestedPermissions(声明的权限)和 grantedPermissions(已授予的权限)。有时候你明明在清单里写了权限,但系统没给,那就要看 grantedPermissions 里有没有。我曾经遇到过一个问题:应用在 Android 12 上闪退,查了半天发现是 BLUETOOTH_SCAN 权限虽然声明了,但没动态申请,导致 grantedPermissions 里没有它。用 dumpsys package 一眼就发现了。

另外,如果你想看应用的所有 Activity 列表(方便前面 am start 用),可以这样:

adb shell dumpsys package com.example.app | grep -A 100 "Activity Resolver Table"

或者更直接:

adb shell dumpsys package com.example.app | grep "ActivityInfo"

这样就能拿到所有 Activity 的全路径了。

核心逻辑图: 下面这张图展示了这三个命令在应用管理中的位置和关系。
应用管理核心命令关系图 Android 应用 am start 启动 Activity am force-stop 强制停止进程 dumpsys package 查看应用详情 三个命令分别对应:启动、停止、查信息 am start 可指定 Activity 和参数 am force-stop 会杀掉所有进程 dumpsys package 输出权限、组件、签名等

好了,这三个命令你掌握了吗?启动 Activity 让你能精准打开某个界面;强制停止是应急用的“大杀器”;而 dumpsys package 则是你排查问题的“照妖镜”。

我个人建议,你可以在自己的测试机上多试试。比如先 dumpsys package 查到一个 Activity 名,然后用 am start 启动它,最后再用 force-stop 关掉。走一遍流程,印象会深很多。

避坑指南: 我曾经在调试一个第三方应用时,用 am start 启动它的一个非公开 Activity,结果直接崩溃。后来发现那个 Activity 需要特定的权限,而我的调试机没有。所以,启动前最好先用 dumpsys package 看看它的 exported 属性——只有 exported=true 的 Activity 才能被外部启动。

嗯,今天就到这里。记住,命令是死的,人是活的。多练、多试,你就能找到最适合自己的用法。

公众号:蓝海资料掘金营,微信deep3321