美文网首页
权限问题

权限问题

作者: 路小茜 | 来源:发表于2020-08-06 09:35 被阅读0次

    关于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的系统上只弹出了位置权限的获取申请,猜想是第二个权限申请把前一个盖掉了。这是两个系统版本的不同点。

    相关文章

      网友评论

          本文标题:权限问题

          本文链接:https://www.haomeiwen.com/subject/ippzlktx.html