资讯专栏INFORMATION COLUMN

解读Android官方开发指导 - 运行时权限

stackvoid / 1870人阅读

摘要:权限申请官方开发指导上使用在中已经申明的危险权限时需要用户授权。下面结合官方的开发指导对这几个做下说明。检查是否已经具有了相关权限。如,和权限就是属于组的。分门别类不仅仅是为了方便容易阅读,组内权限在申请上也是有关联的。

系统权限简介

Android出于系统稳定性以及用户隐私方面的考虑,将应用程序访问权限限制在各自的沙盒内。程序可以随意访问所在沙盒内部的资源或者信息,访问沙盒外部的则必须明确的申请相关访问权限。应用程序所需要的权限需要在AndroidManifest.xml文件中申明。如:



    
      

        
    ...  
    


(本文出处:http://www.jianshu.com/p/0beb...

系统权限根据敏感程度分为普通权限和危险权限两类。两类权限都需要在AndroidManifest.xml文件中申明。在Android 5.1 (API level 22) 及其以下版本上,系统在APP安装时要求用户授权所有权限,否则APP不能安装;而在Android 6.0及其以上版本上,系统在APP安装时授权所有普通权限,危险权限需要在使用时动态让用户授权。这使得Android的权限管理更加灵活,用户可以根据需要在设置应用中对应用的各个危险权限授予不同的权限。Android系统的权限管理不知道被多少人吐槽过,这一改进无疑是加分项。

权限申请官方开发指导

Android 6.0上使用在AndroidManifest.xml中已经申明的危险权限时需要用户授权。针对权限请求相关操作系统提供了三个API。下面结合Android官方的开发指导对这几个API做下说明。

checkSelfPermission() 检查是否已经具有了相关权限。任何时候APP都要在执行需要危险权限的操作前去检查是否具有相关权限,即使刚刚执行过这项操作,因为用户很有可能去设置应用中关闭了相关权限。

shouldShowRequestPermissionRationale() 判断是否需要向用户解释,为什么需要这些权限。有时候用户会不理解应用程序为什么需要这些权限。如,相机应用申请摄像头使用权限用户容易理解,但是相机应用申请地理位置使用权限可能会让用户产生疑惑,因为用户很有能不知道相机需要保存每张照片的拍摄地点。这时候我们就需要做适当的解释说明了。这个方法只有在APP请求过某一权限且用户禁止APP使用该权限的时候返回true。在用户授权了权限和禁止权限时勾选了“Don"t ask again”选项的情况下都会返回false。Android官方开发指导还提到一点,为避免给用户带来糟糕的用户体验,这里的解释说明应该是异步的,不要阻塞用户的操作。时下很多适配了6.0的APP在这点上处理的都不尽如人意,有的根本没有解释说明,有的是弹出对话框,用户体验都不是很好。下文会给出了一个完美的解决方案。

requestPermissions() 申请相关权限。调用这个方法后会弹出一个系统对话框来向用户申请权限,APP不能自定义这个对话框的内容,这也就增加了上面提到的解释说明的必要性。这里还有一点也需要交代一下。从上面危险权限列表中也可以看出,这些权限都是有分组的。如,READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE权限就是属于STORAGE组的。分门别类不仅仅是为了方便容易阅读,组内权限在申请上也是有关联的。

在申请组内某个权限时,弹出的系统对话框会显示组名,而不是指明所申请的权限名。如,申请READ_EXTERNAL_STORAGE权限时,系统对话框提示请求“访问sd卡”权限,但不会说明是请求的sd卡读权限;

申请权限时,如果组内有别的权限已经获得了用户授权,系统不再弹出询问对话框,而是自动授权该权限。如,在申请WRITE_EXTERNAL_STORAGE权限时用户已经授权了READ_EXTERNAL_STORAGE权限,系统则会自动授权WRITE_EXTERNAL_STORAGE权限,不再询问用户;

即使有前一条规则存在,在使用每一条权限时都必须(不是应该)调用requestPermissions()方法来申请权限。如,在已经获取了READ_EXTERNAL_STORAGE权限的情况下,使用WRITE_EXTERNAL_STORAGE权限时依然需要调用requestPermissions()方法来申请,否则就会因为权限问题导致写sd卡失败。

注意:危险权限在AndroidManifest.xml文件中也必须申明,否则动态申请会失败。

下面代码是Android官方开发指导中权限申请大致框架。它使用了Android Support Library中的方法。虽然Android 6.0以后的framework中都有这些方法,但是对于开发者来说使用Android Support Library中的方法更简单,不用检查sdk版本可以兼容低版本。

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {  
    // Should we show an explanation?  
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_EXTERNAL_STORAGE)) {    

        // Show an expanation to the user *asynchronously* -- don"t blockthis thread waiting for the user"s response!     
        // After the user sees the explanation, try again to request the permission. 

    } else {    
        // No explanation needed, we can request the permission. 
        ActivityCompat.requestPermissions(thisActivity, new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);    
        // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is anapp-defined int constant.     
        // The callback method gets the result of the request.  
    }
}

requestPermissions()申请有结果后会回调onRequestPermissionsResult()方法,这种方式对于Android开发者一定不会陌生,因为与startActivityForResult()结果回调onActivityResult()方法类似。如下重载onRequestPermissionsResult()方法即可。

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {  
    switch (requestCode) {    
        case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {      
            // If request is cancelled, the result arrays are empty.      
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {        
                // permission was granted, yay! Do the contacts-related task you need to do.      
            } else {        
                // permission denied, boo! Disable the functionality that depends on this permission. 
            }      
            return;    
        }    
    
    // other "case" lines to check for other permissions this app might request  
    }
}

由于我们使用了AndroidSupport Library库记得在build.gradle文件中添加依赖。

dependencies {    
    ...
    compile "com.android.support:appcompat-v7:23.2.1"
}
动态权限申请封装类EasyPermissionsEx

以上就是Android官方开发指导关于动态权限申请的全部内容了。系统的API已经很简洁了,但是用在项目中时依然会出现很多重复代码,按惯例是要封装一下。在github上搜索"Android permissions"会有很多开源库。Google在github上也开源了一个关于动态权限的封装库easypermissions。看了几个库后,个人觉得easypermissions写的最好,但是也有不足的地方。如,解释为什么需要权限的地方这个库也弹出一个对话框阻塞了用户操作,不符合开发规范、还有用户禁止权限时勾选了“Don"t ask again”后依然会弹出对话框请求权限,用户体验不好。所以我在easypermissions库的基础封装了一个EasyPermissionsEx库。说是一个库,其实只有一个300行左右的类,你可以直接拷贝到你的项目中使用。

前文也提到过在解释为什么需要权限或者在用户永久禁止权限后引导用户去设置应用开启权限时,使用对话框会给用户带来不好的体验。EasyPermissionsEx采用的解决方案是使用snackbar来提醒用户。整体效果如下。snackbar是一种轻量级的用户交互,它不会阻塞用户当前的操作,是从底部弹出一个bar来提示用户,类似toast,但是snackbar又有一个button允许用户操作。关于snackbar更多信息可以跳转到官方文档了解。

Snackbar在Android Design Support Library库中记得在build.gradle文件中添加依赖。

dependencies {    
    ...
    compile "com.android.support:design:23.4.0"
}

EasyPermissionsEx权限请求逻辑如下。关于EasyPermissionsEx更多详情可以去github查看wiki,也可以直接看代码,因为它总共也就300行代码。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/13211.html

相关文章

  • Android 10系统新特性解读

    摘要:概述和往年一样,将于今年月日举办的谷歌大会上谷歌将发布首版系统。这意味着谷歌官方支持面部解锁系统。限制程序访问剪贴板包含了名为的新权限。顾名思义,新的权限将阻止随机的后台应用程序访问剪贴板内容。 概述 和往年一样,将于今年5月7日举办的谷歌 I/O 19大会上谷歌将发布首版Android Q Beta系统。按照惯例,Android Q Beta并非首个开发者预览版,可能是第二或者第三版...

    awokezhou 评论0 收藏0
  • 鹅厂专家详解Android N适配要点 | 腾讯优测干货分享

    摘要:无论是应用部分还是全部打盹限制,系统都会唤醒设备以提供简短的维护时间窗口,在此窗口期间,应用程序可以访问网络并执行任何被推迟的作业同步。此项优化会影响所有应用,而不仅仅是面向的应用。已弃用权限现已弃用。 1.Doze模式更加强大该模式是在Android6.0中引入的,当用户设备未插电源、处于静止状态屏幕关闭时,该模式会推迟CPU和网络活动,从而增加电池寿命。在Android_N中对这种...

    luffyZh 评论0 收藏0
  • 谷歌开发者大会传达的8条关键信息

    摘要:编者按本文作者为,主要介绍新一年的谷歌开发者大会为安卓开发者们带来的条关键讯息。然而谷歌仅给出了少部分细节,也没有开放针对开发者的权限。如果你想了解更多,可以查看谷歌开发者大会官方博文。 【编者按】本文作者为 Chris Ward,主要介绍新一年的谷歌开发者大会为安卓开发者们带来的8条关键讯息。本文系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正文。 又是一年的谷歌开发者大...

    voidking 评论0 收藏0
  • android知识总结 - 收藏集 - 掘金

    摘要:阿里巴巴的,美团的,自定义合集掘金自定义控件学习小良自定义控件合集自定义控件三部曲运行时权限简洁封装掘金运行时权限简洁封装本文原创,转载请注明出处。无论是下载模块,还是换肤模块,还是炫丽的界面。 『Material Design入门学习笔记』动画(含demo) - 掘金之前对Material Design的风格有了一些大体的了解,从这篇文章开始就要介绍代码了。这次文章介绍的代码是比较杂...

    WalkerXu 评论0 收藏0
  • JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS

    摘要:欢迎来我的博客阅读开发者所需要知道的一是一款拥有自动垃圾回收功能的编程语言。它随着的第一版发布而发布以及开源。年月,基金宣布和合并,合并版本在未来发布。年月日,官方公布又一个新的名为的优化编译器,主要提供的新语法,以及提高性能。 欢迎来我的博客阅读:「JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS」 Motivation JavaScript 是一款拥有...

    Lemon_95 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<