Android M Runtime Permission 介绍

  本文旨在全面介绍Android M 上新发布的runtime permission的相关功能,与之相关的app编程以及一些相关重要API,并对framework部分作了简单介绍。

一、什么是runtime permission

    先了解一下什么叫install time permission model。 在app安装过程中要求用户授予app相应权限,否则不能安装,这叫install time permission. 在android M以前的版本都是installtime permission。app安装以后用户不能修改permission的授权情况,也不允许对单项permission进行单独授权和撤回操作。

   在android M版本上,对permission的管理作了部分改进,针对dangerous permission, 不在安装时候给予授权,而是在运行过程中咨询用户是否给予app相应权限, 这叫runtime permission model。注意只是针对dangerous permission. 其他类型的permission,例如normal或者signature 和signatureOrSystem,仍然在安装时给予授权。

·         默认情况下,app安装后,所有的dangerous permission 都是deny状态。

·         app运行过程中, app必须主动询问用户是否允许app拥有这些权限。用户可以选择允许或者不允许。

·         用户也可以在系统settings里面,对某个app的某项permission单独给予权限或撤销权限。

·         运营商或者厂商可以预安装app,但是不会预先给与dangerous permission权限。

·         只有activity可以申请相应的permission. Service不再能直接申请dangerous permission,如果service想要申请相应的permission, 有两种方式:

a)           添加一个activity去请求相应的permission

b)           通过share UID的方式获取与其UID相同的application的权限。后一种方式通常使用在多个apk需要运行在同一个application中的情况。  

注意:有一些permission 可以预先授权给相应的系统默认的一些基础功能的app。比如ACTION_CALLL就会预先授权给系统默认的打电话app.而短信相关的一些permmisions会预先授权给短信app.预授权功能通过packagemanager中的新类DefaultPermissionGrantPolicy实现。

同时注意,在M 机器上,必须安装Google 签发的PackageInstaller,这是google强制要求的。该app负责授权相关的界面显示和操作等相关功能。


二、 兼容性问题

1.      如果target 不是M的app 安装在M 版的机器上,那么所有的permission 按照以前的旧的方式管理,也就是install time permission model.

  需要注意的是,在M的机器上,用户可以在settings里面撤销对permission的授权,app 运行中因为没有相应授权,可能会出现crash或者其他意外情况。

2.      如果app使用了新的M上的permission model, 但是运行在非M的机器上,那么所有的permission 还是按照install time permission去管理。

    注意:如果一个app 是针对M 的preview release开发的,那么它的manifest文件必须指明minimum SDK 版本为MNC, 这种情况下, 该APP是不能运行在M以下的机器上的。

三、受影响的permissions。

只有dangerous permission 被要求采用新的runtime permission 管理方式。

其他的,如normal、signature 和signatureOrSystem permission 还是按照以前的permission 管理方式,在安装时给与授权。

1.      dangerous permission定义。

用户可以定义自己的dangerous permission。 manifest文件中,permission 定义:


  
  
  1. <permission android:description="string resource"  
  2.             android:icon="drawable resource"  
  3.             android:label="string resource"  
  4.             android:name="string"  
  5.             android:permissionGroup="string"  
  6.             android:protectionLevel=["normal" | "dangerous" |   
  7.                                      "signature" | "signatureOrSystem"] />  
2.      关于permissionGroup

注意上面的定义中有一项permissionGroup。 相关的一些permission可以归类为到一个permission Group, 比如CONTACTS 组包括读联系人和写联系人等相关permission.对于一个permission group, app只要获得该组内任意一个permission的授权,就可以拥有该组下的所有permission的授权。例如一个app 要求SEND_SMS 和 RECEIVE_SMS两个permission, 当app要使用SEND_SMS相关功能时,需要请求用户給予SEND_SMS权限,稍后app要使用RECEIVE_SMS相关功能时,RECEIVE_SMS就已经自动授权给了app,不需要app再申请一次。

3.      新增adb命令

配合runtime permission, 也新增了一些相关的adb 命令:

1)     查看所有的dangerous permissions:

                 adb shell pm list permissions –g –d

2)     安装app并且对所有列在app manifest文件下的所有permission给予授权:

                 adb install -g <path_to_apk>

3)     授权给某个app某个permission:

                adb pm grant <package_name> <permission_name>

4)     撤销授权:

                 adb pm revoke <package_name> <permission_name>

下表列出了目前M上的所有的dangerous permission 和相应组:



四、app如何编写适用于runtime permission的代码

如果APP想要在M上运行,并且使用新的permission model, 除了在manifest 里声明需要的permission, APP还要在运行阶段去检查是否拥有相应的permission, 如果没有该permission,则要咨询用户是否给予相应的permissin。

1.      Manifest 中SDK版本声明

要声明该app适用于M新的permission model,需要在manifest文件中声明:targetSdkVersion等于MNC 并且compileSdkVersion等于android-MNC。

如果这个app是针对M的preview release开发的,必须声明minSdkVersion等于MNC。

2.      定义M preview release上特有的permission.

在manifest文件中,app可以使用<uses-permission-sdk-m>来声明所需要的permission只适用于M版本。那么如果app 是被安装在M以下的版本,这个permission会被忽略——不提示用户需要这个permission,也不会授权给app这个permission. 而当app在M版本上运行时,<uses-permission-sdk-m>等同于<uses-permission>,会按照新的permission管理方式管理。用这种方式可以在app升级的时候声明需要新的permission

例如,如果新增需要READ_CONTACTS permission,可以在manifest文件中添加以下声明:

<uses-permission-sdk-m android:name="android.permission.READ_CONTACTS" />

3.      app 如何编程

使用了dangerous permissionapp,在运行过程中,要检查是否有相应的权限,如果没有,要在适当的时候提醒用户为什么需要这个权限,并且请求用户给予相应的权限。这涉及到四个基本API

1)      检查是否有权限:checkSelfPermission(String)

2)      是否需要提示用户为什么需要这个权限:shouldShowRequestPermissionRationale (String permission)

 returns true 如果app以前要求过这个权限,但是用户拒绝了。

 returns false 如果以前用户拒绝给予这个权限并且在系统对话框中选择了“Don't ask again ”选项。

returns false 如果device policy 禁止app拥有这个权限。这种通常都是在DevicePolicyManager中设置的。

3)      请求权限: requestPermissions (String[] permissions, int requestCode)

调用该函数,系统会调出一个对话框,提示用户是否要给予相应权限。用户允许或拒绝相应的权限后,apponRequestPermissionsResult(int, String[], int[])会被调用,告诉app相应的permission是被授权或者拒绝。

4)      处理回调:onRequestPermissionsResult(int, String[], int[])

请求permission后系统调用该函数,通知app permission是被允许还是拒绝。

编码范例:app想要显示contactsFrom android developer.


    private void showContacts() {  
         if (checkSelfPermission(Manifest.permission.READ_CONTACTS)  
                != PackageManager.PERMISSION_GRANTED) {  
      
            // Should we show an explanation?  
            if (shouldShowRequestPermissionRationale(  
                    Manifest.permission.READ_CONTACTS)) {  
                // Explain to the user why we need to read the contacts  
             }  
      
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},  
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);  
      
               // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an  
            // app-defined int constant  
      
            return;  
         }  
    }  
      
     @Override  
     public void onRequestPermissionsResult(int requestCode, String[] permissions,  
             int[] grantResults) {  
         if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS  
                 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
             showContacts();  
         }  
     }  

五、关于自动授权

·         带有PRIVATE_FLAG_PRIVILEGED & FLAG_PERSISTENT flagapp会被自动给予授权。

·         系统默认的基础app会被自动给予相应的permission.比如默认的电话本app自动会拥有CONTACT相关的permission.

自动授权是通过函数grantDefaultPermissions() @DefaultPermissionFrantPolicy.java实现的。该函数会在system ready和创建新用户时调用。DefaultPermissionFrantPolicy.java文件是PMpackage manager service)中在M上新增的一个类,用于实现自动授权的相关功能。

六、framework实现介绍:

Apppermission状态在PM中统一管理维护。PM提供了一些相应的APIPackageInstaller 负责permission管理的相关UI,并通过PM的相关接口设置permission状态。DevicePolicyManager也会根据device的要求对某些app设置一些permission的状态。PM中关于permission管理的代码实现并不复杂,不做详细介绍,只指出下面关键的几点,知道以下几点会非常有助于理解相应的代码。

v  在PM中新增了几个新类:  

·         DefaultPermissionGrantPolicy:这个在自动授权中说过负责自动授权的相关功能。

·         PermissionsState: 每个app在package manager service 里面维护一个该实例,记录该app的所有permission的状态。

·         PermissionData:在PermissionsState 中管理了一组PermissionData , 记录app的每个permission 的状态信息。

·         SettingBase: PM中某个App的相关基本的Setting信息

PM中permission相关类图:

 

v  Permission flag: PM中,会用到这些flag判断permisssion状态。

·         PackageManager.FLAG_PERMISSION_USER_SET: user 选择允许或者拒绝的授权。

·         PackageManager.FLAG_PERMISSION_USER_FIXEDuser选择允许或者拒绝授权同时购选了“never ask again”选项。

·         PackageManager.FLAG_PERMISSION_POLICY_FIXEDdevice policy设定的权限。

·         PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE:如果permission被标记了这个flag,那么表示,app升级后被denypermission,会依然是deny的状态。这个flag会在下面的情况中用到。适用于L以前版本的app,安装得到Mdevice上,如果它的dangerous permission被撤销了,比如通过settings里面的permission管理撤销或者device policy中设定,那么该APP升级到适用于M新的permission模式后,那么升级后这个permission依然是撤销的状态。也就是dangerous permission如果在升级之前被撤销过,升级后依然是撤销的状态。

·         PackageManager.FLAG_PERMISSION_SYSTEM_FIXED 系统app获得的自动授权的permission

·         PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT  默认的系统基本功能app获得的自动授权的permission.

      Framework 部分permission 管理逻辑相对简单,理解以上内容后看相关代码会很容易。

七、其他API.

revokeRuntimePermission()

addOnPermissionsChangeListener()

removeOnpermissionsChangeListener()

grantRuntimePermission()

isPermissionRevokedByPolicy()

getPermissionControllerPackageName()

getPermissionFlags()

updatePermissionFlags()

BuildRequestPermissionsIntent()


http://blog.csdn.net/april_12345/article/details/49025813



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值