Android6.0权限申请源码解析及其注意事项

来源:互联网 发布:头号共谍常凯申 知乎 编辑:程序博客网 时间:2024/05/21 09:09

一、概述

随着android版本的不断升级,现在开发App肯定都是需要适配6.0及其以上的版本了,Google对手机安全的越来越重视,我们开发者所要应对的主要就是新版本SDK带来的一些变化,首先关注的就是权限机制的变化。关于权限机制的变化网上的内容很多参考android6.0运行权限处理本篇文章主要根据源码来分析申请权限时一些注意的事项。

二、权限申请流程

1、Activity.checkSelfPermission(String permission)
2、Activity.requestPermissions(@NonNull String[] permissions, int requestCode)
3、Activity.shouldShowRequestPermissionRationale(@NonNull String permission)
4、Activity.onRequestPermissionsResult(int requestCode, @NonNull String[] permissions@NonNull int[] grantResults)

第一个方法是解析你当前需要申请的权限是否是被通过的,如果是允许的就返回 PERMISSION_GRANTED,第二个方法是请求权限,第三个方法是判断当前的权限状态是否是已经被拒过一次了,它在你第一次拒绝请求权限之后永远拒绝权限之前这段时间内全部返回true,所以当用户第一次拒绝权限之后再次请求时给用户提示为什么app需要这个权限、打消用户的顾虑。第四个方法就不多说了,返回的是请求的结果。

本文主要分析的是requestPermissions这个 函数及其一些注意事项!

  */    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {        if (mHasCurrentPermissionsRequest) {            Log.w(TAG, "Can reqeust only one set of permissions at a time");            // Dispatch the callback with empty arrays which means a cancellation.            onRequestPermissionsResult(requestCode, new String[0], new int[0]);            return;        }        Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);        mHasCurrentPermissionsRequest = true;    }

这是android7.0的源码里面的。mHasCurrentPermissionsRequest这个是一个布尔值的flag,标记当前是否有正在请求的权限。因为方法是异步执行的,所以如果你在申请权限的时候连续两次执行此方法,你会在方法第二次请求的时候他会直接执行onRequestPermissionsResult方法,返回的 permissions和grantResults都是长度为0的空数组,这是如果你在onRequestPermissionsResult不判断长度直接取值会奔溃报数组越位,所以大家在返回结果处理的时候最好做一下长度不为0的判断,最好不要在上次请求结果没有返回的时候就再次执行新的权限请求,因为这样是没有意义的!

    private void dispatchRequestPermissionsResult(int requestCode, Intent data) {        mHasCurrentPermissionsRequest = false;        // If the package installer crashed we may have not data - best effort.        String[] permissions = (data != null) ? data.getStringArrayExtra(                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];        final int[] grantResults = (data != null) ? data.getIntArrayExtra(                PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0];        onRequestPermissionsResult(requestCode, permissions, grantResults);    }

dispatchRequestPermissionsResult方法分发处理的结果,这时mHasCurrentPermissionsRequest重新置为false,表示当前没有正在请求的权限!所以为了防止同时多次调用requestPermissions方法可以添加一个布尔值作判断,实现代码如下

    private isRequesting=false;    //做请求的统一入口    private void requestMyPermission(String[] permissions, int requestCode) {        if (!isRequesting) {            isRequesting = true;            ActivityCompat.requestPermissions(this, permissions, requestCode);        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        if(isRequesting&&permissions.length!=0){            isRequesting=false;            //do you want        }    }

这样就能避免连续多次请求导致无效请求和处理出错的情况!

还有一点的是对于Fragment内的权限请求,最好用v4包中的Fragment,因为android.app.Fragment内的requestPermissions方法

Added in API level 23
void requestPermissions (String[] permissions, int requestCode),需要api23及其之上才能使用的。而v4包中的requestPermissions方法没有版本要求,end~

0 0
原创粉丝点击