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 — 查看权限状态

这三条命令,基本覆盖了权限调试的日常需求。我个人习惯把它们记成「给权限、收权限、查权限」。

ADB 权限操作核心流程 pm grant 授予权限 pm revoke 撤销权限 dumpsys permission 查看权限状态 使用场景: • 开发测试:快速模拟用户授权/拒绝行为 • 自动化测试:无需手动点击弹窗 • 权限审计:检查 App 到底申请了哪些权限

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_LOCATIONACCESS_COARSE_LOCATION。你想想看,如果 App 申请了精确定位,系统会自动授予粗略定位吗?答案是:会。因为它们在同一个组里。

用 dumpsys 可以查看权限组信息:

adb shell dumpsys permission | grep "Permission group"

实用技巧: 我经常用这条命令来验证权限是否真的生效了。有时候 grant 命令执行成功,但 dumpsys 一看还是 denied,那说明有问题。可能是包名写错了,或者权限名不对。

23.5 实战:权限调试三板斧

光说不练假把式。咱们来个完整的实战场景。

场景: 测试一个地图 App 的定位功能。

  1. 先查当前权限状态:
    adb shell dumpsys permission | grep -A 30 "com.example.mapapp"
  2. 授予定位权限:
    adb shell pm grant com.example.mapapp android.permission.ACCESS_FINE_LOCATION
  3. 验证是否生效:
    adb shell dumpsys permission | grep -A 30 "com.example.mapapp" | grep "ACCESS_FINE_LOCATION"
    如果看到 granted,说明成功了。
  4. 测试权限被拒绝的情况:
    adb shell pm revoke com.example.mapapp android.permission.ACCESS_FINE_LOCATION
    然后打开 App,看看它有没有正确处理权限被拒绝的情况。

我的习惯: 写自动化测试脚本时,我会在测试用例开始前用 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