一文搞懂Android权限的各种类型

科技   2024-11-06 17:26   浙江  

戳蓝字“牛晓伟”关注我哦!

用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章,技术文章也可以有温度。


本文摘要

本文主要介绍Android中权限的各种类型,通过本文您将了解到 权限分为哪些类型normal权限、dangerous权限、privileged权限、signature权限等这些权限的分类和区别。(文中代码基于Android13)

本文同样采用对话的方式,人物小昱大牛,小昱是Android新人,为了能进入大厂,利用工作之余恶补Android知识。大牛是具有多年开发经验的老手。小昱有问题就会向大牛请教。

本文大纲

image

1. 权限的分类

小昱经过向大牛请教后,已经对Android中Apk的各种类型了然于胸了,于是他把学习经历放在了Android中的权限上,由于自己的经验不是很丰富,同样被权限的各种类型搞的云里雾里的。于是买了些礼物给大牛并向他请教。

小昱:“大牛啊,我又开始我的下个学习之旅了,现在正在学习权限相关的内容,但是被权限的各种类型搞的是晕头转向,还请大佬帮帮我。”

大牛:“你咋这么客气啊,还带礼物,那我就笑纳了啊,我们开始梳理吧,请看下图。”

image

如上图,权限主要分为normal权限dangerous权限signature权限internal权限这四类。

小昱:“大牛,你这个分类对吗?我咋没有看到privileged权限的身影啊。”

大牛:“这个分类绝对不用质疑,那我就拿出铁证来让你看看,如下代码:”

public class PermissionInfo extends PackageItemInfo implements Parcelable {
    
    //normal权限对应的值
    public static final int PROTECTION_NORMAL = 0;

    //dangerous权限对应的值
    public static final int PROTECTION_DANGEROUS = 1;

    //signature权限对应的值
    public static final int PROTECTION_SIGNATURE = 2;

    //该权限已经过时了,被signature权限和privileged权限代替了
    @Deprecated
    public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;

    //internal权限对应的值
    public static final int PROTECTION_INTERNAL = 4;

小昱:“大牛,我信你了,那就依照上面的分类来帮我讲讲它们吧。”

2. normal权限

normal权限是指那些对用户隐私或系统安全影响较小的权限,因此这类权限在Apk安装后就会自动授予。常见的Normal权限有ACCESS_NETWORK_STATE (访问网络连接状态)、ACCESS_WIFI_STATE (访问Wi-Fi连接状态)、INTERNET (允许应用访问网络)等。

2.1 使用normal权限

一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的

小昱:“大牛,你稍等这里的用户指啥啊?还有上面这句话该咋理解呢?”

大牛:“莫着急小昱,那我详细的讲讲。”

其中权限状态指的是该权限被授予或者拒绝,因为Android设备是支持多用户的,因此在一个Android设备上是可能会存在多个用户的,而一个Apk是有可能被安装在多个用户上的。不同用户下,同一Apk使用的权限状态应该是不一样的。

我举个例子更好理解比如一个Apk使用了RECORD_AUDIO权限,并且该Apk被安装在了userid 0userid 10的两个用户下,假如在userid 0用户下,Apk使用者给该Apk授予RECORD_AUDIO权限,那在userid 10用户下,该Apk的RECORD_AUDIO权限肯定不能是授予状态。

从上面的例子可以看出对于一些权限来说它的权限状态是与Android设备用户有关系的,而对于使用normal权限的Apk来说,该类型的权限状态是与Android设备的用户没关系的,因为Apk被安装后,对于所有Android设备的用户该类型权限都是授予状态。

大牛:“为了有一个更直观的感受,我用adb shell dumpsys package p 命令把某个Apk的normal权限状态信息显示出来了,如下:”

Package [com.example.myapplication] (4da63ab):
    userId=10108
    pkg=Package{b4f3b30 com.example.myapplication}
    
    //install permissions代表安装后,授予的权限
    install permissions:
      //下面两个权限都是normal类型的,granted为true 代表该权限是授予状态
      android.permission.RECEIVE_BOOT_COMPLETED: granted=true
      android.permission.INTERNET: granted=true

2.2 权限normal声明

在声明normal权限时,还可以为它增加instantappopruntime这三种子权限,当然了在声明normal权限的时候一般是不需要增加它们的。如下是一个例子:

//下面标签位于AndroidManifest.xml文件

<permission android:name="com.niu.normal.permission" android:protectionLevel="normal|runtime|appop"/>

如上,声明了namecom.niu.normal.permission的权限,它的大类是normal类型,小类是runtimeappop两种类型。

3. dangerous权限

dangerous权限是指可能会侵犯用户隐私或设备安全的权限,应用在使用这些权限之前必须获得用户的明确授权,像录音使用相机定位等都属于危险权限。

一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户有强烈关系的

大牛:“小昱,关于上面这句话能理解吧,因为在上面的normal权限中已经介绍过了。”

小昱:“能理解,因为该类型权限的权限状态在安装后是没有确定下来的,只有等着Apk的使用者授予或者拒绝。因此该类型权限的权限状态与用户有关系。”

大牛:“同样为了有一个直观的感受,我用adb shell dumpsys package p 命令把某个Apk的dangerous权限状态信息显示出来了,如下:”

Package [com.example.myapplication] (4da63ab):
    userId=10108
    pkg=Package{b4f3b30 com.example.myapplication}
    省略其他······
    
    //User 0代表 userid为0的Android设备用户
    User 0: ceDataInode=84690 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
      //在每个user下都存在着自己的运行时权限
      runtime permissions:
        android.permission.READ_MEDIA_IMAGES: granted=false, flags=[ USER_SET|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
        android.permission.READ_MEDIA_AUDIO: granted=false, flags=[ USER_SET|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
        android.permission.READ_MEDIA_VIDEO: granted=false, flags=[ USER_SET|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
        android.permission.RECORD_AUDIO: granted=true, flags=[ USER_SET|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]

3.1 声明dangerous权限

同样在声明dangerous权限时,还可以为它增加instantappopruntime这三种子权限,当然了在声明dangerous权限的时候一般是不需要增加它们的。

4. signature权限

signature权限是指在满足以下任意一个条件时,在安装Apk后,就会授予该权限,如下两个条件:

  1. 使用signature权限的Apk的签名信息与signature权限的声明者的签名信息一致或者兼容
  2. signature权限的任意子权限满足一定条件

大牛:“上面的两个条件是不是不好理解啊,那我来好好讲讲。”

第一个条件相对比较容易理解,正如signature权限中的signature (签名),其实指的就是一个Apk使用了某个signature权限,在安装该Apk的时候会去验证该Apk的签名信息是否与signature权限的声明者的签名信息一致或者兼容,如果一致或兼容的话则在安装该Apk后,就会授予该权限;否则会把该权限抛弃掉。

在介绍第二个条件之前,需要介绍下子权限,与dangerous权限一样,signature权限也有它自己的子权限,它的子权限主要有privilegeddevelopmentrecentsinstaller等。

privileged权限

该类型的权限只能给privileged Apk使用 (关于Apk各种类型可以看这篇文章),其他类型Apk是不能使用的。

recents权限

该类型的权限只能授予给拥有最近任务功能的Apk (其实就是launcher)

installer权限

该类型的权限只能授予给包名为com.android.packageinstaller的Apk (Apk安装器)或者包名为com.android.permissioncontroller的Apk (权限控制器Apk)

当然上面只是介绍了几个子权限,signature权限还有一些其他的子权限就不在这赘述了。那就来解释下第二个条件。

第二个条件就是依次检查signature权限的子权限是否满足该子权限对应的条件,如果满足则授予该权限,比如某signature权限包含了recentsInstaller子权限,则验证规则如下:

  1. 如果该子权限是recents,则验证当前使用该权限的Apk是不是launcher,是的话则授予该权限,并且返回;否则进入下一步
  2. 如果该子权限是installer,则验证当前使用该权限的Apk是不是Apk安装器或者权限控制器Apk,是的话则授予该权限,并且返回;否则进入下一步

小昱:“大牛,我大概理解了这两个条件了,能把相应代码展示出来,让我看看吗?”

大牛:“代码实在是太多了,代码主要在PermissionManagerServiceImpl类的restorePermissionState方法中,你可以自己研究研究。还有一点非常重要的事情要交代下。”

可以使用signature权限的Apk分为两类与权限声明者签名信息兼容或者一样的Apk系统Apk (上面的第二个条件是可以看出来的,比如launcher、Apk安装器Apk等)。

因为在安装Apk的时候,如果条件满足的话,就已经授予了该权限,因此一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的

4.1 声明signature权限

虽然对于使用signature权限的使用者做了上述规定,但是对于声明signature权限的声明者来说并没有规定,任意一个Apk都是可以声明该类型权限的,如下例子:

//下面标签位于AndroidManifest.xml文件

<permission android:name="com.niu.signature.permission" android:protectionLevel="signature|recents|installer"/>

如上,声明了namecom.niu.signature.permission的权限,它的大类是signature类型,小类是recentsinstaller两种类型。

5. internal权限

internal权限其实可以理解为是signature权限的子集,internal权限是指该权限的任意子权限满足一定条件时,在安装Apk后,就会授予该权限

也就是说internal权限也是可以包含子权限的,并且它包含的子权限与signature权限包含的子权限是完全一样的,只不过使用internal权限的使用者只能是系统Apk

因为在安装Apk的时候,如果条件满足的话,就已经授予了该权限,因此一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的

因为internal权限和signature权限很相似,关于internal权限的声明就不细说了。

6. 总结

大牛:“关于权限各种类型就已经结束了,我用一张图来做下总结吧,如下图:”

image

如上图列出了Android权限的各种类型,大类型上主要分为:

  1. normal权限,该类型权限对用户隐私或系统安全影响较小,因此在Apk安装后就自动授予了该类型的权限。正因如此一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的
  2. dangerous权限,该类型权限是指可能会侵犯用户隐私或设备安全的权限,因此应用在使用这些权限之前必须获得用户的明确授权。一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户有关系的。该类型权限可以包含的子权限有instantappopruntime
  3. signature权限,该类型权限要不满足权限使用者签名信息与权限声明者签名信息兼容或者一样,要不满足它的子权限符合一定条件,这两个条件中的任意一个条件,即可在Apk安装后就会授予该权限,一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的。可以使用signature权限的Apk分为两类与权限声明者签名信息兼容或者一样的Apk系统Apk,它的子权限有很多。
  4. internal权限,该类型权限是signature权限的子集,只要它的子权限符合一定条件,即可在Apk安装后就会授予该权限。一个Apk使用该类型的权限,该类型权限的权限状态可是与Android设备的用户没有关系的。可以使用该权限的Apk主要系统Apk,它与signature权限拥有相同的子权限。

“小昱,关于权限的各种类型就介绍到此,下次有问题问我的时候,可不要带礼物了啊。”


欢迎关注我的公众号,里面有非常多精彩内容等着您哦

下面是我的知识星球,可以在星球内向我提问,同时我也会把Android framework和App方面更详细的知识分享给大家


虎哥Lovedroid
Android技术达人 近10年一线开发经验 关注并分享Android、Kotlin新技术,新框架 多年Android底层框架修改经验,对Framework、Server、Binder等架构有深入理解
 最新文章