Android运行时权限

前言:

 Android 6.0(api23)引入了运行时权限,它允许应用程序在运行的时候请求权限而不像5.1及更低版本一样在安装的时候请求权限。这样一来,需要请求危险权限(涉及到用户隐私…)的应用在安装的时候就不需要请求权限了,而5.1以前如果安装的时候请求的权限没有通过的话应用就安装不了。同时,这种运行时权限可以由用户随时在设置->应用信息中开启或关闭某项权限,即使某个应用刚才还拥有读取联系人的权限,下一秒可能就没了(用户关闭了)。

1. 权限的分类

权限分为:

  1. 普通权限:没有涉及到用户隐私的权限,在清单文件中声明的这种权限会被系统自动授予。
  2. 危险权限:涉及到用户隐私的权限,如读取联系人,定位,拨打电话…,这种权限必须经过用户授予才能得到。

Android共有上百种权限,但危险权限不多,共9组24个,剩下的都是普通权限:

危险权限表:

权限组权限
CALENDARREAD_CALENDAR、WRITE_CALENDAR
CAMERACAMERA
CONTACTSREAD_CONTACTS、WRITE_CONTACTS 、GET_ACCOUNTS
LOCATIONACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION
MICROPHONERECORD_AUDIO
PHONEREAD_PHONE_STATE、CALL_PHONE、READ_CALL_LOG、WRITE_CALL_LOG、ADD_VOICEMAIL、USE_SIP、PROCESS_OUTGOING_CALLS
SENSORSBODY_SENSORS
SMSSEND_SMS、RECEIVE_SMS、READ_SMS、RECEIVE_WAP_PUSH、RECEIVE_MMS
STORAGEREAD_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE

注意:

  1. 不管是哪种权限,不管在哪个系统版本中权限都需要在清单文件中声明;
  2. 当用户授予同组中其中一个权限时,系统会自动授予同组中的其他权限(清单列出的)。

2. 运行时权限的申请

运行时权限的申请是在程序中通过代码控制的,首先需要检查应用是否具有相应的权限:


int permissionCheck = ContextCompat.checkSelfPermission(this,
        Manifest.permission.READ_CONTACTS);

使用support-v4包的ContextCompat的checkSelfPermission方法检查权限可以兼容低版本,这样在低版本上也不会出错,这样就没必要在使用前判断sdk版本了,这个方法的返回值有PackageManager.PERMISSION_GRANTEDPERMISSION_DENIED两种,前者权限被授予,后者表示权限被拒绝。

检查完是否具有相应的权限就可以进行相应的逻辑操作了,如果已经具有该权限则直接执行相应的逻辑,否则就需要先申请权限。

private void getReadContactsAuthority() {
    // 使用ContextCompat可以兼容低版本
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {
        // 如果没有该权限,判断是否需要解释
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.READ_CONTACTS)) {
            // 显示解释为什么需要该权限的对话框
            showExpanationDialog();
        } else {
            // 请求权限
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);
        }
    }else{
        // 已经具有该权限了
        // ...
    }
}


/**
 * 显示解释权限的对话框
 */
private void showExpanationDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("请求权限");
    builder.setMessage("应用需要访问联系人权限以便得到手机通讯录");
    builder.setNegativeButton("取消", null);
    builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            // 请求读取通讯录权限
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);
        }
    });
    builder.create().show();
}

请求运行时权限可能存在的一种情况是应用第一次请求权限的时候被用户拒绝了,下次再需要使用该权限下的功能的时候可以给用户解释一下为什么需要该权限然后再继续请求权限,这样会比较人性化,这时就需要使用shouldShowRequestPermissionRationale方法判断是否需要解释权限的使用,如图:

这里写图片描述

注:

  1. 如果应用之前请求过此权限但用户拒绝了请求(没有勾选Don’t ask agai),此方法将返回 true;
  2. 如果用户之前拒绝了权限请求,并在权限请求系统对话框中选择了 Don’t ask again 选项,shouldShowRequestPermissionRationale方法将返回 false;
  3. 如果设备规范禁止应用具有该权限,此方法也会返回 false。

点击确定后会弹出请求权限对话框,如图:

这里写图片描述

这个窗口是由requestPermissions方法弹出来的。

3. 权限申请的结果

 调用requestPermissions方法后程序就会向系统申请权限,申请权限的结果会通过onRequestPermissionsResult方法反馈给我们。

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                Toast.makeText(this,"获得了权限", Toast.LENGTH_SHORT).show();

            } else {
                Toast.makeText(this,"权限被拒绝", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
}

MY_PERMISSIONS_REQUEST_READ_CONTACTS类似于startActivityForResults的请求码,当grantResults(结果)长度大于0并且grantResults中申请的第一个权限结果是通过时(PERMISSION_GRANTED)表示我们的应用获得了这项权限,否则被用户拒绝了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值