android6.0新权限申请以及RxPermissions库的使用

RxPermission

运行时权限介绍

Android 6.0在我们原有的AndroidManifest.xml声明权限的基础上,
又新增了运行时权限动态检测,以下权限都需要在运行时判断:

  • 身体传感器
  • 日历
  • 摄像头
  • 通讯录
  • 地理位置
  • 麦克风
  • 电话
  • 短信
  • 存储空间
  • 运行时权限处理

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

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

android {
 compileSdkVersion 23
 buildToolsVersion "23.0.1"
 }
}

检查并申请权限

我们需要在用到权限的地方,每次都检查是否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

android6.0新权限申请以及RxPermissions库的使用_第1张图片

用户选择允许或拒绝后,会回调onRequestPermissionsResult方法, 该方法类似于onActivityResult

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

我们接着需要根据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);
              }
          }
      }
  }

RxPermission:

用于适配Android 6.0新的权限模型的开源框架。

github地址:https://github.com/tbruyelle/RxPermissions

具体使用

  1. To use this library your minSdkVersion must be >= 11.

In your build.gradle :

repositories {
    jcenter() // If not already there
}

dependencies {
    compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.3@aar'
}

2.具体代码

必须在初始化阶段调用,例如onCreate()方法中

这个例子是在项目的启动页设置的,一次性请求了多个权限。
多个权限是用“ , ”分割开来的。
同时请求多个权限(分别获取结果)如果想要在同时请求多个权限,又想分别获取授权结果的话,可以调用requestEach方法或者ensureEach方法。

 private void requestPermissionList(final StartActivity activity) {
        new RxPermissions(activity)
                .requestEach(Manifest.permission.CALL_PHONE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_PHONE_STATE,
                        Manifest.permission.PROCESS_OUTGOING_CALLS,
                        Manifest.permission.SEND_SMS
                        )
                .subscribe(new Action1() {
                    @Override
                    public void call(Permission permission) {
                        if(permission.granted){
                            // 获得授权
                            isGrantedAll = true;
                            Log.d(TAG,"isGrantedAll = " +isGrantedAll);

                            //AppUtil.showShortToast(activity,"您已经授权该权限");

                        }else{
                            isGrantedAll = false;
                            Log.d(TAG,"i///sGrantedAll = " +isGrantedAll);
                            //未获得授权
                            //AppUtil.showShortToast(activity,"您没有授权该权限,请在设置中打开授权");

                        }

                    }
                });
     }

以下是我从网上找的两个例子。主要的区别是在同时请求多个的情况下,处理不同的结果。
同时请求多个权限(合并结果)

比如同时申请拍照和录音权限

RxPermissions.getInstance(MainActivity.this).request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
    .subscribe(new Action1() {
        @Override
        public void call(Boolean granted) {
        if (granted) { // 在android 6.0之前会默认返回true
            // 已经获取权限
            String jpgPath = getCacheDir() + "test.jpg";
            takePhotoByPath(jpgPath, 2);
        } else {
            // 未获取权限
            Toast.makeText(MainActivity.this, "您没有授权该权限,请在设置中打开授权", Toast.LENGTH_SHORT).show();
        }
        }
    });

同时请求多个权限(分别获取结果)

如果想要在同时请求多个权限,又想分别获取授权结果的话,可以调用requestEach方法或者ensureEach方法

RxPermissions.getInstance(MainActivity.this).requestEach(Manifest.permission.CAMERA,
        Manifest.permission.RECORD_AUDIO)
        .subscribe(new Action1() {
            @Override
            public void call(Permission permission) {
            if (permission.name.equals(Manifest.permission.CAMERA)) {
                if (permission.granted) {
                String jpgPath = getCacheDir() + "test.jpg";
                takePhotoByPath(jpgPath, 2);
                } else {
                //  未获取权限
                Toast.makeText(MainActivity.this, "您没有授权该权限,请在设置中打开授权", Toast.LENGTH_SHORT).show();
                }

            } else if (permission.name.equals(Manifest.permission.RECORD_AUDIO)) {

            }
            }
        });

你可能感兴趣的:(android基础知识)