刷到了 b 站小白评测的视频,他们每次检测手机后台应用存活,都是个体力活,要一轮又一轮启动应用,再次启动来检测是否存活。
我觉得他们花的一些力气,以手工思维做,投入产出比太低,有很大的改进空间。检测应用状态,应当以程序思维做事。
对于智能手机,应该是有更简单的方法获得各个应用的状态的。安卓手机可以使用 adb 执行 shell 代码,获得系统状态。
但是苹果,权限太封闭,暂时没办法用代码收集系统状态(或许开发者、越狱可以?)
要在以前,我肯定弄不了,查文档就要累死我。但现在有了 ChatGPT 了,许多细节的小问题问它就能解决了。
动态监控前台 App
首先,是要得到手机的前台 App,可以在 adb shell 中用这条命令:
dumpsys window displays | grep mFocusedApp
得到这样的输出:
mFocusedApp=ActivityRecord{3223fe1 u0 com.android.browser/.BrowserActivity t24131}
也就是目前的前台应用是浏览器,进程 id 为 24131。如果要持续监听写入到文件,就可以用:
while true; do echo "$(date) $(dumpsys window displays | grep mFocusedApp)" >> /sdcard/fg_log.txt; sleep 1; done
动态监控所有 App 进程
其次,就是要得到后台进程的信息,用到了 top
命令。
在 top
的输出中,不同的应用程序进程具有不同的用户标识(USER)。在 Android 系统中,用户标识通常以 u0_aXXX 的形式表示,每个应用程序进程在 Android 系统中都有自己的用户标识,这是为了实现应用程序之间的隔离和安全性。
除了 App 的进程,top
的输出还包括一些用户标识为 system
和 user
的进程,应当使用 grep 排除掉。通过下面的 adb shell 命令,可以得到所有的 App 进程状态:
top -b -d 1 -n 10 -s 12 | grep -v -e '^ *[0-9]* [a-tv-z]'
# top:
# -b batch mode,易于输出写入文件
# -H 显示线程
# -d 1 1秒刷新一次
# -n 10 刷新1次后退出
# -s 12 以第12列(即包名)排序输出
# grep:
# -v 反转,匹配的不输出,筛选掉 system 和 root 的进程,只留下 user 的进程
# -e 表达式
得到这样的输出:
Tasks: 764 total, 1 running, 763 sleeping, 0 stopped, 0 zombie
Mem: 5633892K total, 5129488K used, 504404K free, 197612K buffers
Swap: 4194300K total, 925376K used, 3268924K free, 1724040K cached
800%cpu 11%user 0%nice 33%sys 750%idle 0%iow 5%irq 1%sirq 0%host
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+[ARGS]
4510 u0_a71 20 0 4.9G 48M 30M S 0.0 0.8 0:00.57 system
2906 u0_a203 20 0 5.3G 44M 38M S 0.0 0.7 0:05.54 org.codeaurora.ims
24964 u0_a312 10 -10 5.6G 169M 128M S 2.0 3.0 0:24.91 mark.via
4703 u0_a117 20 0 4.9G 48M 31M S 0.0 0.8 0:00.54 com.xiaomi.xmsfkeeper
6011 u0_a160 20 0 5.1G 50M 36M S 0.0 0.9 0:03.28 com.xiaomi.xmsf:services
5276 u0_a160 20 0 5.3G 55M 49M S 0.0 0.9 0:15.60 com.xiaomi.xmsf
27552 u0_a143 20 0 5.0G 78M 61M S 0.0 1.4 0:02.22 com.xiaomi.simactivate.service
4672 u0_a104 20 0 4.9G 56M 37M S 0.0 1.0 0:00.71 com.xiaomi.mircs
...
参数解释:
Tasks: 764 total, 1 running, 763 sleeping, 0 stopped, 0 zombie
共有764个进程,一个在运行,763个在休眠,0个已停止,0个僵尸进程
Mem: 5633892K total, 5129488K used, 504404K free, 197612K buffers
物理内存总共 5633892K,已使用 5129488K,剩余 504404K,另有 197612K 用作缓冲区
Swap: 4194300K total, 925376K used, 3268924K free, 1724040K cached
交换空间总共 4194300K,已使用 925376K,剩余 3268924K,另有 1724040K 用作缓冲区
800%cpu 11%user 0%nice 33%sys 750%idle 0%iow 5%irq 1%sirq 0%host
CPU共有800%负载,用户占11%,高优先级进程占0%,系统占33%,空闲750%,IO等待占0%,硬中断占5%,软中断占1%,其它占0%
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ [ARGS]
进程ID 用户名 优先级 NICE值 虚拟空间大小 常驻内存用量 共享内存用量 进程状态 CPU使用率 内存使用率 CPU时间 进程参数
24964 u0_a312 10 -10 5.6G 169M 128M S 2.0 3.0 0:24.91 mark.via
NI(Nice 值)表示进程的优先级。Nice 值是一个用于调整进程优先级的参数,取值范围从 -20 到 19,其中 -20 表示最高优先级,19 表示最低优先级。
TIME+ 显示的进程自启动以来累计使用的 CPU 时间,包括用户态和内核态的时间。
在 top
的输出中,我们就可以得到所有 App 的优先级、内存占用、CPU 使用时间,并且能每秒刷新一次,这可以给我们许多信息!
例如,当「百度地图」切换到后台,top
的输出显示,「百度地图」的进程仍在后台长时间占用 CPU 资源,我都已经锁屏 5 分钟了,它还在占着 4% 的 CPU。不愧是大厂作风。
此外,还可以观察到进程占用内存的动态减少过程,以此,就可以得知系统杀了哪些后台进程。
在 adb shell
中,通过管道,可以将 top
的输出写到文件:
# 先把此刻的时间写入 log
date > /sdcard/log.txt
# 间隔1秒,输出120次,即持续监控2分钟,结果追加到 log
top -b -d 1 -n 120 -s 12 | grep -v -e '^ *[0-9]* [a-tv-z]' >> /sdcard/log.txt
然后把日志文件拉到电脑;
adb pull /sdcard/log.txt log.txt
综合分析
结合前台 App、后台进程的动态 log 数据,就可以得到更多的信息,如:
- 在前台打开某个 App 时,后台哪几个 App 进程的内存占用显著减少,疑似被系统强制杀死,这就可以精确到某 App 是在哪个时刻被杀死的
- 哪些 App 切换到后台时,还在一直疯狂占用 CPU,彰显大厂作风
- 制作进程状态的动态视频
不过这些分析不是我的强项,就不进一步做了(我还没学 Python 数据制图)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于