权限问题

关于Android的权限问题一直都是一知半解,而且最近有一个关于权限的需求,因此想着借这个机会自己整理一下相关的东西,让自己清楚了解。不知道最后会写成什么样子,哈哈。

安卓系统的权限管理机制从API 23 (也就是Android 6.0 又叫做 Android M,)之后发生了比较大的改变,在一些比较危险的权限上要求必须申请动态权限,即使你在AndroidMainfest.xml文件中申请也没有任何用,或者可以将编译的目标版本设定这API 22,这样就可以了。但这并不是长久之计。

Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等。

在低于6.0的系统中,直接安装apk的时候在安装页面会有一个应用权限的直接申请,这里的权限是和manifest中添加的权限一致的。如果想修改可以在手机管家中进行修改。如下图

在手机版本高于6.0的系统中申请的权限会更加细致,同一个安装包,在10.0的系统上权限如下

10.0的系统安装完成以后在安装完成页还可以再对权限进行一次设置


当系统小于Android 6.0,只需要在AndroidManifest.xml注册权限即可使用(不包括某些手机厂商自定义的权限管理)。当系统大于等于Android 6.0时,既要在AndroidManifest.xml注册权限,又要去动态申请权限。

下面以摄像机权限为例写一下具体的代码实现以及页面上的效果。

1.6.0系统的手机上需要动态申请权限。

权限的申请分为3步:1.查看是否已获取权限;2.如果没有获取到权限,去申请权限;3.拿到申请权限结果。

而第一步中,在低于6.0的手机中查询需要的权限状态时一直是出于已有权限状态,即

不管在手机管理中将摄像头权限设置为允许还是禁止,上图中这行代码的结果一直是true。

另外,Android权限系统还提供了一种非常“恶心”的机制,叫拒绝并不再询问。

当某个权限被用户拒绝了一次,下次我们如果再申请这个权限的话,界面上会多出一个拒绝并不再询问的选项。只要用户选择了这一项,那么我们之后都不能再去请求这个权限了,因为系统会直接返回我们权限被拒绝。

点击拒绝和拒绝并不再询问选项都是拒绝,那么怎样区别他们呢?答案就是ActivityCompat.shouldShowRequestPermissionRationale方法。代码如下,

如果点击禁止按钮,ActivityCompat.shouldShowRequestPermissionRationale的结果为true,这时去弹一个框告诉用户这个功能需要开启权限,点击确定按钮后重新申请权限,引导用户同意权限。如果点击禁止并不再询问按钮,ActivityCompat.shouldShowRequestPermissionRationale的结果为false,这时也去弹一个框告诉用户这个功能需要开启权限,但是现在再去申请权限就不能再弹出申请权限的选项了,因此我们的做法是弹一个框告诉用户这个功能需要开启权限,在点击确认按钮后跳转到设置页去引导用户开启权限。

2.好了,现在一个整体上申请权限的例子就写完了。上面的是申请一个权限,那么在项目中我们也有可能要同时申请多个权限,那么该怎么做呢?难道要每个权限都写这么一串吗?那样显得代码太臃肿了,现在就来看看以两个权限为例改怎么做吧。

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)

{

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode){

    case 0: {

            List denied =new ArrayList();//存放拒绝的权限

            List deniedAndNotAllow =new ArrayList();//存放拒绝且不再询问的权限

            for (int i =0; i < grantResults.length; i++) {

                        if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {

                        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permissions[i])) {

                        //点击“禁止”

                        denied.add(permissions[i]);

                    }else {

                        //点击“拒绝并不再询问”

                        deniedAndNotAllow.add(permissions[i]);

                    }

        }

}

if (denied.size() ==0 && deniedAndNotAllow.size() ==0) {

Intent intent =new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                startActivityForResult(intent, REQUEST_CAMERA_CODE);

}else {

if (denied.size() !=0) {

new AlertDialog.Builder(getActivity()).setMessage("该功能需要您开启摄像头权限")

.setPositiveButton("确定", new DialogInterface.OnClickListener() {

@Override

 public void onClick(DialogInterface dialog, int which) {

requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION}, 0);

                                        }

}

).show();

                }else {

new AlertDialog.Builder(getActivity()).setMessage("该功能需要您开启摄像头权限,请去设置中统一摄像头权限")

.setPositiveButton("确定", new DialogInterface.OnClickListener() {

@Override

                                        public void onClick(DialogInterface dialog, int which) {

//打开app的设置页面,引导用户开启权限

                                            Intent intent =new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

                                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                                            Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);

                                            intent.setData(uri);

                                            startActivity(intent);

                                        }

}

).show();

                }

}

}

return;

    }

}

上面代码粘贴过来格式有点乱了,整体流程就是在onRequestPermissionsResult()方法中增加了denied和deniedAndNeverAskAgain两个集合,分别用于记录拒绝和拒绝并不再询问的权限。如果这两个集合都为空,那么说明所有权限都被授权了,这时就可以直接进行拍照了。

而如果denied集合不为空,则说明有权限被用户拒绝了,这时候我们还是弹出一个对话框来提醒用户,并重新申请权限。而如果deniedAndNeverAskAgain不为空,说明有权限被用户拒绝且不再询问,这时就只能提示用户去设置当中手动打开权限,我们编写了一个Intent来执行跳转逻辑。

在书写的过程中我认为有两点需要注意:1. 这里拍照功能是需要拍照权限和位置权限同时满足,在真是的项目中可能有变动,大家根据实际情况进行书写即可。2. 两个权限一起申请的时候我使用了两个手机,一个是8.0系统,另一个是10.0系统,在10.0系统手机上连续弹出拍照权限和位置权限的选择,而在8.0的系统上只弹出了位置权限的获取申请,猜想是第二个权限申请把前一个盖掉了。这是两个系统版本的不同点。

你可能感兴趣的:(权限问题)