Android 6.0 以及上运行时权限处理

原文地址:https://www.jianshu.com/p/b4a8b3d4f587
解决方法2:https://www.jianshu.com/p/31cf0cd9cbd1
Android 6.0在我们原有的AndroidManifest.xml声明权限的基础上,
又新增了运行时权限动态检测,以下权限都需要在运行时判断:

Android6.0系统默认为targetSdkVersion小于23的应用默认授予了所申请的所有权限,
所以如果你以前的APP设置的targetSdkVersion低于23,在运行时也不会崩溃,
但这也只是一个临时的救急策略,用户还是可以在设置中取消授予的权限。

声明目标SDK版本
我们需要在build.gradle中声明targetSdkVersion为23

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.yourcomany.app
        minSdkVersion 18
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

检查并申请权限
我们需要在用到权限的地方,每次都检查是否APP已经拥有权限,
比如我们有一个下载功能,需要写SD卡的权限,
我们在写入之前检查是否有WRITE_EXTERNAL_STORAGE权限,没有则申请权限

  if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    WRITE_EXTERNAL_STORAGE_REQUEST_CODE);
        }

请求权限后,系统会弹出请求权限的Dialog
Android 6.0 以及上运行时权限处理_第1张图片

Android 6.0 以及上运行时权限处理_第2张图片
两段代码如下:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    doNext(requestCode,grantResults);
}

 private void doNext(int requestCode, int[] grantResults) {
        if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted
            } else {
                // Permission Denied
            }
        }
    }

Fragment中运行时权限的特殊处理

在Fragment中申请权限,不要使用ActivityCompat.requestPermissions, 直接使用Fragment的requestPermissions方法,否则会回调到Activity的onRequestPermissionsResult
如果在Fragment中嵌套Fragment,在子Fragment中使用requestPermissions方法,onRequestPermissionsResult不会回调回来,建议使用getParentFragment().requestPermissions方法,
这个方法会回调到父Fragment中的onRequestPermissionsResult,加入以下代码可以把回调透传到子Fragment

 @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        List fragments = getChildFragmentManager().getFragments();
        if (fragments != null) {
            for (Fragment fragment : fragments) {
                if (fragment != null) {
                    fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
                }
            }
        }
    }

第二种方法:
第一种:简单粗暴最有效的是在工程下的build.gradle中的 targetSdkVersion 改为21或22,因为Android6.0系统或以上默认为targetSdkVersion小于23的应用默认授予了所申请的所有权限,
如果不想这么简单粗暴的话,则:
首先我们要声明权限

然后我的build.gradle 中targetSdkVersion 为25

然后针对一个API>=23的手机,
然后在代码中动态申请权限:
private static final int WRITE_EXTERNAL_STORAGE_REQUEST_CODE = 127;//这个值是自定义的一个int值,在申请多个权限时要保证这个值不重复,才能在回调时进行判断

    @Override
    protected void onResume() {
        super.onResume();
        getPersimmion();
     }
   
    @TargetApi(23)
    private void getPersimmion() {
        // 如果应用没有获得对应权限
        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
            //申请WRITE_EXTERNAL_STORAGE权限
//第一个字符串列是预申请的权限,第三個int是本次请求的辨认编号
            requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST_CODE);

        }
    }

此时重新运行程序:
Android 6.0 以及上运行时权限处理_第3张图片

但是用户要点击拒绝呢?如果程序不做处理,还是和没有申请权限一样!都会在写入sd卡时程序崩溃,所以要做后续的处理,此时我们要重写一个方法onRequestPermissionsResult,用户选择允许或拒绝后,会回调onRequestPermissionsResult方法, 该方法类似于onActivityResult,

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        dealWithResult(requestCode,grantResults);
    }
    //我们接着需要根据requestCode和grantResults(授权结果)做相应的后续处理
    private void dealWithResult(int requestCode, int[] grantResults) {
        if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted 用户允许
            } else {
                // Permission Denied 用户拒绝
            }
        }
    }

你可能感兴趣的:(学习生活)