Android 6.0+ 权限申请

Android 6.0+ 权限申请

前言

安卓系统权限(Runtime Permissions)分为两种:普通权限高危权限。对于普通权限的申请,只在APP安装的时候询问一次,而对于高危权限,从Android M(API.23)开始,将会在APP运行时动态申请,这样就可以使用户选择是否授予APP该权限,从而保护用户安全。

运行时权限官方文档解释:https://developer.android.com/training/permissions/requesting.html

注:
- 如果设备系统低于6.0,权限只会在APP安装时询问
- 如果targetSdkVersion小于23,权限只会在APP安装时询问


需要动态申请的权限包括以下几种。

注意:同一个组内一个权限被授权了,同组内其他权限也自动被授权

Permission GroupPermissions
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. 如果没有申请该权限,则申请权限
  3. 第一次申请被拒绝(用户也未点击不再询问),如果再次申请权限,需要给用户提示,为什么需要申请该权限,并在用户点击允许后,申请该权限
1.权限判断
    int checkSelfPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA);
        if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
            // 没有权限,需要申请
        } else {
            // 有权限了
        }
2.权限申请
ActivityCompat.requestPermissions(MainActivity.this,new String[] { Manifest.permission.CAMERA }, REQUEST_STORAGE_PERMISSION);

申请权限的时候,第二个参数为数组格式,也就是说,可以同时申请多个权限,但不建议这么做。REQUEST_STORAGE_PERMISSION为自定义的请求码。

如果在Fragment中申请权限的话,需要调用Fragment的requestPermissions(...)方法,把ActivityCompat.requestPermissions改为requestPermissions。否则会回调到Activity的 onRequestPermissionsResult方法。

3.处理权限申请回调-onRequestPermissionsResult

权限申请的成功或失败之后的操作需要在此回调方法中实现。

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        switch (requestCode) {
        case REQUEST_STORAGE_PERMISSION:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限获得成功
            } else {
                // 权限没有获得
            }
            break;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
  • 因为权限可以同时申请多个,所以回调结果也是以数组的方式返回。此处我们以只请求一个权限为例,如果用户授予权限,则
    grantResults[0] = PackageManager.PERMISSION_GRANTED;
4.shouldShowRequestPermissionRationale(…)

1.第一次申请权限的时候,该方法返回false
2.第一次申请权限失败,用户点击拒绝授权后,如果再次申请权限,则该方法返回true
3.如果用户拒绝授权并选择[不再提醒]之后,该方法返回false
4.设备系统禁止APP使用该权限后,返回false

用户拒绝授权权限的时候,系统会提供一个方法让我们解释为什么要申请该权限。因此,我们可以显示一个Dialog向用户再次申请权限。

if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
            //向用户解释权限申请原因
                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setTitle("二维码扫描需要使用相机权限");
                builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        // 权限申请
                    }
                });
                builder.setNegativeButton("Cancle", null);
                builder.show();
            } else {
               // 权限申请
            }
        } else {
            // 有权限了
        }

第三方库 EasyPermissions

EasyPermissions简化了Android运行时权限申请、判断、处理的操作步骤
官方文档 https://github.com/googlesamples/easypermissions

1.build.gradle添加依赖
dependencies {
    compile 'pub.devrel:easypermissions:0.3.0'

注:如果提示Error:Failed to resolve: com.android.support:appcompat-v7:25.1.0,就是需要你升级你的SDK了。

2.检查权限
String[] perms = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
        if (!EasyPermissions.hasPermissions(this, perms)) {
           // 没有权限
        }
3.申请权限
@AfterPermissionGranted(REQUEST_CODE_QRCODE_PERMISSIONS)
    private void requestCodeQRCodePermissions() {
        String[] perms = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
        if (!EasyPermissions.hasPermissions(this, perms)) {
            EasyPermissions.requestPermissions(this, "扫描二维码需要打开相机和散光灯的权限", REQUEST_CODE_QRCODE_PERMISSIONS, perms);
        }else {
            // 权限已经有了,可以进行其他操作
        }
    }

在第一次申请失败后,如果需要再次申请,会自动弹出Dialog对话框,第二个参数即为对话框的Message,向用户解释为什么申请该权限,提高用户授权的可能性。

AfterPermissionGranted是一个可选的注解,如果有此标签,那么当request值对应的权限申请通过的话会自动调用该方法。

4.实现EasyPermissions.PermissionCallbacks接口,直接处理权限申请的成功或失败
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Forward results to EasyPermissions
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }
    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        // 权限申请成功
    }
    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        // 权限申请失败
    }
5.用户点击“不在询问”

如果用户点击了”不在询问“,就无法在通过APP获取权限了,权限只能在设置界面重新授予。这种情况下,你可以使用EasyPermissions.somePermissionPermanentlyDenied(...)方法来显示一个系统对话框,用以打开系统设置界面。

@Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        // 权限申请失败
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this).build().show();
        }
    }

当用户从设置界面返回到APP界面的时候,在onActivityResult(...)方法中就可以再次判断权限的授权情况了。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE){
            String[] perms = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
            if (EasyPermissions.hasPermissions(this, perms)) {
                Toast.makeText(MainActivity.this,"权限被用户通过设置界面重新授予了",Toast.LENGTH_SHORT).show();
            }
        }
    }

这里写图片描述

最后

附上demo地址:
http://download.csdn.net/download/u014527323/9762717

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值