Android 6.0 权限管理(permission)

来源:互联网 发布:java oop编程题 编辑:程序博客网 时间:2024/05/22 02:13

       大家知道android应用程序开发的时候都需要申请很多权限,比如发起网络请求需要网络权限,在安装应用程序的时候,在6.0之前的手机会列出当前应用程序都申请了哪些权限,并且需要用户点击同意才能使用,这样其实是有一个弊端的,就是如果应用申请了某些权限,但是这个权限对应使用该应用程序不是必须的(有权限更好,没有权限也能玩),这样用户如果不愿意授予该权限,则会导致用户流失。

       Andorid系统在6.0升级了对权限的管理,将权限分级,分成了普通权限与危险权限,比如获取网络状态android.permission.ACCESS_NETWORK_STATE就是一个普通权限,系统是怎么来定义什么是普通权限和危险权限的呐?是按照授予该权限是否会对系统带来危害来区分的,比如读写权限,该权限可能会造成你写入病毒,或者读取不该读取的内容。系统定义了如下的9组危险权限。类似的权限分在同一组。参考链接

       如果你的应用程序被使用在6.0上,且该应用程序build targetSdkVersion=23, 如果在你的应用中使用了上诉的危险权限,每一个权限,都会弹窗询问用户是否授予权限,但是如果你的编译版本小于23,是不会弹窗的,这样就兼容了以前的版本,当前手机更新换代很快,系统升级将会越来越多,因此建议早做支持。目前很多应用程序已经支持了。

       在申请权限的时候,如果是同一组的权限其实是可以只申请其中一个,比如在应用程序需要使用读写权限,其实你可以只申请读权限,通过规则是一组中,只要有一个权限被授予,则整组权限都被授予。

在程序开发中我们又要做些什么呐?

       当应用需要使用danger权限时,你可以采用context.checkSelfPermission(permission)方法来检测当前是否已经拥有该权限,

       参数permission为你需要请求的权限,所有的权限都定义在Manifest.permission中,普通权限也定义在这个地方,怎么才知道是否已经拥有该权限,根据返回值为PackageManager.PERMISSION_GRANTED, PackageManager.PERMISSION_DENIED中的一个来进行判断.

PackageManager.PERMISSION_GRANTED表示已拥有该权限
PackageManager.PERMISSION_DENIED表示未拥有该权限

       需要注意的是,因为该方法是6.0加入的,因此需要在6.0+的系统才能使用,如果使用该方法,这样就导致了每次使用都需要判断版本号,太麻烦,系统很人性化的在surpport包中添加了ContextCompat.checkSelfPermission(Context context, String permission),这样在6.0以前的版本,默认赋予权限,在6.0之后的版本才需要进行处理,对程序员隐藏了版本的判断。

官方给出样例如下:参考链接

// Here, thisActivity is the current activityif(ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {    // Should we show an explanation?    if(ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,            Manifest.permission.READ_CONTACTS)) {        // Show an expanation to the user *asynchronously* -- don't block        // this 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_CONTACTS},                MY_PERMISSIONS_REQUEST_READ_CONTACTS);        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an        // app-defined int constant. The callback method gets the        // result of the request.    }}

       可以请求一个权限,或者多个权限,一个权限和多个权限的区别是弹窗样式稍稍有点区别,多个权限弹窗会显示第一个权限,共多少权限,(note:requestCode存在长度限制,过长的 requestCode 会导致如下异常:Can only use lower 8 bits for requestCode),请求后会收到回调,

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {    // reject    if (requestCode != REQUEST_CODE) {       return;    }    if (grantResults[0]==PackageManager.PERMISSION_GRANTED){        //do something    }else {            // denied do something    } }

       grantResults[0]就是表示请求权限返回的结果为PackageManager.PERMISSION_GRANTED,PackageManager.PERMISSION_DENIED中的一个,如果为PackageManager.PERMISSION_GRANTED,表示用户点击了允许,如果为PackageManager.PERMISSION_DENIED则表示用户点击了拒绝。因此可以根据回调结果来继续响应程序执行路径。

弹窗规则如下:

       第一次请求权限,如果没有权限,会弹窗确认,如果用户点击了拒绝,在第二次请求是,会再次弹窗确认,同时会多出一个勾选项“不再提醒”,如果不勾选,继续选择拒绝,下一次请求权限还是会弹窗提醒,但是如果勾选了,则下次不再提醒,这样后面的操作不会对用户进行任何提醒。

       如果选择了不在提醒,则在使用过程中,如果不处理,体验太差,如何才能改善这种情况,还有如何才能知道该次请求是否会弹窗呐?可以用下面的方法进行判断:ActivityCompat.shouldShowRequestPermissionRationale的返回值进行判断,如果是false,表示勾选了不再提醒,如果是true,则下次请求权限还是会弹窗提醒,但是该方法有一个很坑的地方,就是第一次不做任何设置,返回值也是false,这样如果按照系统给的样例就要区分是第一次请求还是后面几次请求。(经过试验发现,如果去设置手动开启关闭一次权限,所有的条件又跟初始条件一样了)。

实际操作

if(ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED)){    ActivityCompat.requestPermissions(thisActivity, new String[]{ Manifest.permission.READ_CONTACTS},REQUEST_READ_CONTACTS);}public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {    // reject    if (requestCode != REQUEST_CODE) {        return;     }    if (grantResults[0] == PackageManager.PERMISSION_GRANTED){        //do something    }else   if(!ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)){       // show tips  go to set        // or  Toast / dialog     }}

       在实际开发过程中,可以全局定义全局的权限管理类,统一进行权限处理,这样就不需要在每一个页面都添加请求权限的代码。

1 0