23、安全与权限:adb shell pm grant(授予权限)、adb shell pm revoke(撤销权限)、adb shell dumpsys permission(查看权限)
权限管理,说白了就是 Android 系统的看门狗。它决定了一个 App 能做什么,不能做什么。我刚开始做调试时,总觉得权限这东西很烦人——动不动就弹窗,还得手动点同意。后来我才明白,没有这套机制,你的手机早被各种流氓 App 掏空了。
今天咱们就聊聊怎么用 ADB 来操控权限。嗯,这里要注意,我们不是要绕过安全机制,而是为了开发和测试方便。
23.1 权限体系速览
Android 的权限分好几层。普通权限、危险权限、特殊权限……但对我们调试来说,最常打交道的是 运行时权限(Runtime Permissions)。
从 Android 6.0(API 23)开始,App 在运行时才能申请危险权限。用户可以选择同意或拒绝。但作为开发者,你总不能每次都手动点吧?这时候 ADB 就派上用场了。
核心命令三件套:
pm grant— 授予权限pm revoke— 撤销权限dumpsys permission— 查看权限状态
这三条命令,基本覆盖了权限调试的日常需求。我个人习惯把它们记成「给权限、收权限、查权限」。
23.2 pm grant — 授予权限
先说说怎么给权限。命令格式很简单:
adb shell pm grant <包名> <权限名>
举个例子,给微信授予定位权限:
adb shell pm grant com.tencent.mm android.permission.ACCESS_FINE_LOCATION
执行完这条命令,微信的定位权限就被打开了。你想想看,这在测试定位功能时有多方便?不用去设置里翻半天。
小技巧: 权限名可以在 Android SDK 的 Manifest.permission 类里找到。常用的有:
android.permission.CAMERA— 相机android.permission.RECORD_AUDIO— 录音android.permission.READ_CONTACTS— 读取联系人android.permission.ACCESS_FINE_LOCATION— 精确定位
我在项目中遇到过一个问题:明明执行了 grant 命令,但 App 还是提示没有权限。后来发现,原来是 App 的 targetSdkVersion 低于 23,它根本不走运行时权限流程。嗯,这个坑踩过一次就记住了。
23.3 pm revoke — 撤销权限
有给就有收。撤销权限的命令是对称的:
adb shell pm revoke <包名> <权限名>
比如撤销微信的相机权限:
adb shell pm revoke com.tencent.mm android.permission.CAMERA
执行后,微信再想打开相机就会弹窗申请权限。这招在测试「权限被拒绝后 App 是否崩溃」时特别好用。
注意: 不是所有权限都能用 grant/revoke 操作。比如 SYSTEM_ALERT_WINDOW(悬浮窗)和 WRITE_SETTINGS(修改系统设置)这类特殊权限,需要走 Settings 界面手动授权。ADB 命令对它们无效。
我曾经在测试一个悬浮窗功能时,反复执行 revoke 都没反应。查了半天文档才发现,特殊权限根本不吃这一套。所以,遇到搞不定的权限,先查查它是不是「特殊权限」。
23.4 dumpsys permission — 查看权限状态
光会给和收还不够,你得能查。dumpsys permission 就是干这个的。
基本用法:
adb shell dumpsys permission
这条命令会输出一大堆信息。说实话,第一次看的时候我头都大了。但别慌,我们只关注几个关键部分。
23.4.1 查看某个 App 的权限列表
用 grep 过滤包名:
adb shell dumpsys permission | grep -A 50 "com.example.myapp"
输出大概长这样:
Packages:
Package [com.example.myapp] (UID 10123):
User 0: state=INSTALLED
granted permissions:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_FINE_LOCATION
denied permissions:
android.permission.CAMERA
android.permission.RECORD_AUDIO
一目了然。哪些权限给了,哪些没给,清清楚楚。
23.4.2 查看权限组
Android 把权限分成了组。比如定位权限组包含 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION。你想想看,如果 App 申请了精确定位,系统会自动授予粗略定位吗?答案是:会。因为它们在同一个组里。
用 dumpsys 可以查看权限组信息:
adb shell dumpsys permission | grep "Permission group"
实用技巧: 我经常用这条命令来验证权限是否真的生效了。有时候 grant 命令执行成功,但 dumpsys 一看还是 denied,那说明有问题。可能是包名写错了,或者权限名不对。
23.5 实战:权限调试三板斧
光说不练假把式。咱们来个完整的实战场景。
场景: 测试一个地图 App 的定位功能。
- 先查当前权限状态:
adb shell dumpsys permission | grep -A 30 "com.example.mapapp" - 授予定位权限:
adb shell pm grant com.example.mapapp android.permission.ACCESS_FINE_LOCATION - 验证是否生效:
如果看到adb shell dumpsys permission | grep -A 30 "com.example.mapapp" | grep "ACCESS_FINE_LOCATION"granted,说明成功了。 - 测试权限被拒绝的情况:
然后打开 App,看看它有没有正确处理权限被拒绝的情况。adb shell pm revoke com.example.mapapp android.permission.ACCESS_FINE_LOCATION
我的习惯: 写自动化测试脚本时,我会在测试用例开始前用 grant 确保权限到位,测试结束后用 revoke 清理现场。这样每个用例都是独立的环境,不会互相影响。
23.6 常见问题与避坑
最后聊聊我踩过的几个坑。
坑一:权限名写错
命令执行成功,但权限没变。为什么?因为权限名写错了。比如 ACCESS_FINE_LOCATION 少写了一个字母,系统不会报错,只是默默忽略。所以,执行完 grant 一定要用 dumpsys 验证。
坑二:包名不对
这个更常见。包名大小写敏感,多一个点少一个点都不行。我曾经把 com.tencent.mm 写成了 com.tencent.mm.debug,结果折腾了半天。
坑三:系统权限不能乱动
别去尝试 grant 系统权限(比如 android.permission.INSTALL_PACKAGES)。普通 App 根本用不了,而且可能会引发奇怪的问题。我见过有人给第三方 App 授予了系统权限,结果手机重启后一直报错。
安全提醒: 生产环境的设备不要随意用 grant/revoke 修改权限。这些命令是为开发和测试准备的。在用户手机上乱改权限,轻则 App 崩溃,重则隐私泄露。
好了,关于权限的 ADB 操作就聊这么多。记住三个命令:grant 给权限,revoke 收权限,dumpsys 查权限。配合起来用,调试效率能提升不少。
公众号:蓝海资料掘金营,微信deep3321