最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

permission

旗下网站admin11浏览0评论

permission

permission

-

2023年4月12日发(作者:南京证券交易软件下载)

AndroidMPermission运⾏时权限学习笔记

AndroidMPermission运⾏时权限学习笔记

从Android6.0开始,⽤户需要在运⾏时请求权限,本⽂对运⾏时权限的申请和处理进⾏介绍,并讨论了使⽤运⾏时权限时新⽼版本的⼀些处理.

Android应⽤权限简要介绍

⼀个Android应⽤默认情况下是不拥有任何权限的,这即是说,在默认情况下,⼀个应⽤是没有权利去进⾏⼀些可能会造成不好影响的操作的.这些不好的

影响可能是对其它应⽤,操作系统,或者是⽤户.

如果应⽤需要⼀些额外的能⼒,则它需要在中静态地声明相应的权限.

如果应⽤没有在manifest中声明权限,却使⽤了相应的功能,在调⽤到相应功能的时候,将会抛出异常.

⽐如程序要发送⼀个请求,却忘记加Internet权限,那么在发送这个请求的时候程序就会抛出异常,⼀般不会catch这个异常,所以程序直接就崩溃了:

Causedby:tyException:Permissiondenied(missingINTERNETpermission?)

在Android6.0(API23)发布之前,所有的权限都在安装应⽤的时候显⽰给⽤户,⽤户选择安装则表⽰全部接受这些权限,之后⽆法撤销对这些权限的授权.

Android6.0开始,⼀部分⽐较危险的权限需要在程序运⾏时显式弹框,请求⽤户授权.

⾄于什么时候弹这个框,由应⽤程序⾃⼰决定.

对于其他权限,认为不是很危险,所以仍然保持原来的做法,在⽤户安装应⽤程序时就予以授权.

还需要注意的是,在设置中,对于应⽤的危险权限,⽤户可以选择性地进⾏授权或者关闭.

Permission的保护等级

permission的保护等级通过protectionLevel属性设置,共有4种:normal,dangerous,signature,signatureOrSystem.

具体可以参见介绍:

签名相关的⽐较不常⽤,剩下的两种是normal和dangerous.

Guides⾥⾯对这两种类型进⾏了讨论:官⽹Guides:

总结下来就是:所有的权限仍然在manifest中静态声明,normal权限的在安装的时候⾃动授权,⽽dangerous的权限需要应⽤明确地请求⽤户授权.

当然对于Android6.0以下的⼿机,或者以前开发的旧应⽤来说,dangerous权限也是安装时授权的,具体看下⼀节的讨论.

DangerousPermissions:

ouspermissionsandpermissiongroups.

PermissionGroupPermissions

想要查看所有dangerous的权限,也可以⽤命令:

adbshellpmlistpermissions-g-d

⼿机版本和程序版本的不同处理

这⾥引⽤⼀段Guides⾥⾯的原⽂:

IfthedeviceisrunningAndroid6.0(APIlevel23)orhigher,andtheapp'sis23orhigher,theapprequestspermissionsfromtheuseratrun-time.

Theusercanrevokethepermissionsatanytime,einformationaboutrequestingpermissionsinyourapp,seethetrainingguide.

IfthedeviceisrunningAndroid5.1(APIlevel22)orlower,ortheapp'sis22orlower,thesystemaskstheusertograntthepermissionswhenthe

ddanewpermissiontoanupdatedversionoftheapp,theuserinstallstheapp,theonlywaytheycanrevokethepermissionisbyuninstallingtheapp.

这⾥头要注意and和or的使⽤,说明了只有满⾜targetSdkVersion和实际使⽤设备的版本都在23及以上的时候,才会采⽤新的动态权限机制.其他情况,跟之

前⼀样,在安装和升级应⽤的时候就授权了所有的权限.

可以总结为:

1.所有的权限都在manifest中声明.

2.如果(1)你的app的targetSdkVersion是23及以上,并且(2)app运⾏在Android6.0及以上的设备,危险权限必须动态请求.

当权限被拒绝,app理应还是能够使⽤的,只不过权限相关的部分功能不能⽤.

3.上⼀条中的两个条件(1)(2)没有同时满⾜,即属于其他情况,所有权限在安装时请求,如果⽤户不接受,则不安装.

特别注意这种情况:旧应⽤新系统.

如果targetSdkVersion⼩于23,即被认为是Android6.0发布之前开发的应⽤,还没有兼容6.0.

这种应⽤即便是被装在Android6.0的机器上,也是采⽤原来的安装即授予权限逻辑,所有权限在应⽤安装时全部被授权.

在Android6.0的设备上安装targetSdkVersion⼩于23的应⽤之后,可以在应⽤的设置中查看,发现所有的dangerous权限状态都是打开.

所以不⽤担⼼⽼的应⽤在Android6.0上会各种乱崩.

但是⽤户仍然可以在系统设置中禁⽤权限:

在模拟器上点击授权开关的时候弹出了以下提⽰:

如果⽤户执意要取消授权,应⽤虽然不会直接崩溃,但是功能变为默默⽆作为状态,返回值可能变为null或者0,进⽽引起⽆法预料的⾏为或者崩溃.

为什么要及时升级targetSdkVersion

这是因为每⼀个版本的API有可能会产⽣新的权限,这些新增的权限,对于targetSdkVersion⽐该API低的应⽤是⾃动获取的.

所以targetSdkVersion最好是能及时写到最新,这样避免应⽤⾃动获取到新API新增的权限.

结论:对targetSdkVersion还不存在的权限是⾃动获取到的.

可以参见:APIGuides:

其中”Automaticpermissionadjustments”那段.

Permissiongroup

所有的权限都有⾃⼰的permissiongroup.

系统弹框请求某⼀个permission时也是只说明了它的类别,当⽤户同意,系统会给予它该条permission.(只有这⼀条).

但是如果app已经有了该group下的另⼀条permission,系统将会⾃动授予权限(也即请求权限的callback直接返回),这过程中不与⽤户交互.

动态权限请求的实现

原⽂:

因为权限动态检查相关的API是Android6.0才加⼊的,所以minSdkVersion不是23时,推荐使⽤SupportLibrary来实现,好处是:程序⾥不必加if来判断当前设

备的版本.

1.检查权限状态

如果执⾏的操作需要⼀个dangerouspermission,那么每次在执⾏操作的地⽅都必须check你是否有这个permission,因为⽤户可以在应⽤设置⾥随意地更

改授权情况,所以必须每次在使⽤前都检查是否有权限.

检查权限的⽅法:两个参数分别是Context和权限名.

返回值是:ifyouhavethepermission,orifnot.

⽐如:

if(SION_GRANTED==elfPermission(,_CONTACTS)){

//haspermission,dooperationdirectly

oneContacts(this);

Log.i(DEBUG_TAG,"userhasthepermissionalready!");

}else{

//donothavepermission

2.动态请求权限

如果上⾯权限检查的结果是DENIED,那么就需要显式地向⽤户请求这个权限了.

Android提供了⼏个⽅法来动态请求权限,调⽤这些⽅法会显⽰出⼀个标准的Dialog,这个Dialog⽬前是不能被定制的.

2.1有时候可能需要解释为什么需要这个权限

有时候你可能会需要跟⽤户解释⼀下权限的⽤途.

注意不是每条权限都需要解释,显⽽易见的那种可以不解释,太多的解释会降低⽤户体验.

⼀种⽅式是,当⽤户拒绝过这个权限,但是⼜⽤到了这个功能,那么很可能⽤户不是很明⽩为什么app需要这个权限,这时候就可以先向⽤户解释⼀下.

为了发现这种⽤户可能需要解释的情形,Android提供了⼀个⼯具类⽅法:

如果app之前请求过该权限,被⽤户拒绝,这个⽅法就会返回true.

如果⽤户之前拒绝权限的时候勾选了对话框中”Don’taskagain”的选项,那么这个⽅法会返回false.

如果设备策略禁⽌应⽤拥有这条权限,这个⽅法也返回false.

注意具体解释原因的这个dialog需要⾃⼰实现,系统没有提供.

2.2请求权限

请求权限的⽅法是:传⼊⼀个Activity,⼀个permission名字的数组,和⼀个整型的requestcode.

这个⽅法是异步的,它会⽴即返回,当⽤户和dialog交互完成之后,系统会调⽤回调⽅法,传回⽤户的选择结果和对应的requestcode.

代码:

if(SION_GRANTED==elfPermission(,_CONTACTS)){

//haspermission,dooperationdirectly

oneContacts(this);

Log.i(DEBUG_TAG,"userhasthepermissionalready!");

}else{

//donothavepermission

Log.i(DEBUG_TAG,"userdonothavethispermission!");

//Shouldweshowanexplanation?

if(ShowRequestPermissionRationale(,_CONTACTS)){

//Showanexplanationtotheuser*asynchronously*--don'tblock

//thisthreadwaitingfortheuser'sresponse!Aftertheuser//seestheexplanation,tryagaintorequestthepermission.

Log.i(DEBUG_TAG,"weshouldexplainwhyweneedthispermission!");

}else{

//Noexplanationneeded,wecanrequestthepermission.

Log.i(DEBUG_TAG,"==requestthepermission==");

tPermissions(,

newString[]{_CONTACTS},

MY_PERMISSIONS_REQUEST_READ_CONTACTS);

//MY_PERMISSIONS_REQUEST_READ_CONTACTSisan

//lbackmethodgetsthe

//resultoftherequest.

}

}

这个对话框是系统的,不能⾃定义.

经验证,请求权限对话框中的”Don’taskagain”的选项,只有该条权限之前的状态是Denied的时候,才会出现.

以前从未授权(即第⼀次弹框),或者之前的状态是Granted(当然这种情况⼀般不会弹框询问),出现的弹框都是不带该不再询问的选项的.

2.3处理请求权限的响应

当⽤户对请求权限的dialog做出响应之后,系统会调⽤⽅法,传回⽤户的响应.

这个回调中requestcode即为调⽤时传⼊的参数,是app⾃定义的⼀个整型值.

如果请求取消,返回的数组将会为空.

代码:@Override

publicvoidonRequestPermissionsResult(intrequestCode,

Stringpermissions[],int[]grantResults){

switch(requestCode){

caseMY_PERMISSIONS_REQUEST_READ_CONTACTS:{

//Ifrequestiscancelled,theresultarraysareempty.

if(>0

&&grantResults[0]==SION_GRANTED){

//permissionwasgranted,yay!Dothe

//contacts-relatedtaskyouneedtodo.

oneContacts(this);

Log.i(DEBUG_TAG,"usergrantedthepermission!");

}else{

//permissiondenied,boo!Disablethe

//functionalitythatdependsonthispermission.

Log.i(DEBUG_TAG,"userdeniedthepermission!");

}

return;}

//other'case'linestocheckforother

//permissionsthisappmightrequest

}

}

系统⾃动回调的情况:

有⼀些情形下,调⽤

1.⾃动授权:如果⽤户已经允许了permissiongroup中的⼀条A权限,那么当下次调⽤⽅法请求同⼀个group中的B权限时,系统会直接调⽤回调⽅法,并传

回的结果.

2.⾃动拒绝:如果⽤户选择了不再询问此条权限,那么app再次调⽤⽅法来请求同⼀条权限的时候,系统会直接调⽤回调,返回.

Demo地址:

BestPractices

原⽂:

BestPractices总结:

1.⽤Intent启动其他应⽤来完成功能.

2.只⽤真的需要的权限.

3.不要⼀次请求多个权限来烦⽤户,有的权限可以等到要⽤的时候再请求.

4.向⽤户解释为什么需要这个权限.

5.从Android6.0开始,每⼀条权限,都需要测试开关两种状态下是不是都能让应⽤正常运⾏,⽽不是崩溃.

并且相关的权限可能会需要测试不同的组合.

ADB命令

可以⽤命令⾏来管理权限:

Usethetooltomanagepermssionsfromthecommandline:

Listpermissionsandstatusbygroup:

$adbshellpmlistpermissions-d-gGrantorrevokeoneormorepermissions:

$adbshellpm[grant|revoke]...

参考资料:

APIGuides:Training:

Runtimepermissions:

permissionelement:

设计Patterns->Permissions:

博客⽂章:

第三⽅库:

PermissionsDispatcher:

RxPermissions:

Grant:

本⽂地址:

本⽂Demo地址:

-

permission

发布评论

评论列表(0)

  1. 暂无评论