安卓项目实战之Android 6.0运行时权限请求框架PermissionsDispatcher的使用

版权声明:转载必须注明本文转自郭子轩的博客 https://blog.csdn.net/gpf1320253667/article/details/82810425

前言

Android6.0(API 级别 23)版本的一个重大改动就是增加了运行时权限(动态权限):一些危险的权限不止要在AndroidMainifest文件中声明,还要在运行的时候使用代码来提醒用户去开通,让用户同意才能进行授权,这样做增加了安全性,但是给开发人员带来了麻烦,于是就出现了一些用于简化运行时权限的处理框架,如 PermissionsDispatcher,RxPermissions,easypermissions 等,而我们今天要讲的就是大多数人都在用的PermissionsDispatcher开源库。

GitHub开源地址:https://github.com/hotchemi/PermissionsDispatcher

PermissionsDispatcher简介

PermissionsDispatcher是一个用注解方式来处理Android6.0运行时权限的库,旨在高效处理权限问题。

PermissionsDispatcher使用

1、添加依赖

  • 当你项目中使用的Android Gradle Plugin版本大于2.2时,只需一步引入:

app的gradle文件中添加:

ependencies { 
     compile 'com.github.hotchemi:permissionsdispatcher:2.4.0' 
     annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.4.0' 
}
  • 当Android Gradle Plugin版本小于2.2时,需如下两步引入:

project的gradle文件中添加:(当前Gradle Plugin版本2.1.2 < 2.2)

dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }

app的gradle文件中添加:

apply plugin: 'com.android.application'
apply plugin: 'android-apt'
   
dependencies {
      compile 'com.github.hotchemi:permissionsdispatcher:2.4.0'
      apt 'com.github.hotchemi:permissionsdispatcher-processor:2.4.0'
}

2、在AndroidManifest.xml文件中配置应用所需要的权限

3、添加注解

3.1、@RuntimePermissions注解:必需的注解,它用来注册一个Activity或者Fragment,使他们可以处理权限:

@RuntimePermissions
public class MainActivity extends AppCompatActivity { }

3.2、@NeedsPermission注解:必需的注解,在需要获取权限才能执行的方法上添加注释,用来获取权限:

单个权限的写法

@NeedsPermission(Manifest.permission.CALL_PHONE) 
void siglePermission(){

}

多个权限的写法

@NeedsPermission({Manifest.permission.CALL_PHONE,Manifest.permission.WRITE_EXTERNAL_STORAGE}) 
void mulPermission(){ 

}

3.3、@OnShowRationale注解:这个不是必须的注解,用于标注申请权限前需要执行的方法,注解
括号里面有参数,传入想要申请的权限,而且这个方法还要传入一个PermissionRequest对象,这个对象有两种方法:proceed()让权限请求继续,cancel()让请求中断。也就是说,这个方法会拦截你发出的请求,这个方法用于告诉用户你接下来申请的权限是干嘛的,说服用户给你权限。

@OnShowRationale({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})
    //给用户解释要请求什么权限,为什么需要此权限
    void showRationale(final PermissionRequest request) {
        new AlertDialog.Builder(this)
                .setMessage("使用此功能需要WRITE_EXTERNAL_STORAGE和RECORD_AUDIO权限,下一步将继续请求权限")
                .setPositiveButton("下一步", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        request.proceed();//继续执行请求
                    }
                }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        request.cancel();//取消执行请求
                    }
                })
                .show();
    }
 
    @OnShowRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        //给用户解释要请求什么权限,为什么需要此权限
    void showSingleRationale(final PermissionRequest request) {
        new AlertDialog.Builder(this)
                .setMessage("使用此功能需要WRITE_EXTERNAL_STORAGE,下一步将继续请求权限")
                .setPositiveButton("下一步", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        request.proceed();//继续执行请求
                    }
                }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                request.cancel();//取消执行请求
            }
        })
                .show();
    }

3.4、@OnPermissionDenied注解:这个也不是必须的注解,用于标注如果权限请求失败,但是用户没有勾选不再询问的时候执行的方法,注解括号里面有参数,传入想要申请的权限。也就是说,我们可以在这个方法做申请权限失败之后的处理,如像用户解释为什么要申请,或者重新申请操作等。

    @OnPermissionDenied({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})//一旦用户拒绝了
    public void multiDenied() {
        Toast.makeText(this, "已拒绝一个或以上权限", Toast.LENGTH_SHORT).show();
    }
 
 
    @OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)//一旦用户拒绝了
    public void StorageDenied() {
        Toast.makeText(this, "已拒绝WRITE_EXTERNAL_STORAGE权限", Toast.LENGTH_SHORT).show();
    }

3.5、@OnNeverAskAgain注解:这个也不是必须的注解,用于标注如果权限请求失败,而且用户勾选不再询问的时候执行的方法,注解括号里面有参数,传入想要申请的权限。也就是说,我们可以在这个方法做申请权限失败并选择不再询问之后的处理。例如,可以告诉作者想开启权限的就从手机设置里面开启。

    @OnNeverAskAgain({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})//用户选择的不再询问
    public void multiNeverAsk() {
        Toast.makeText(this, "已拒绝一个或以上权限,并不再询问", Toast.LENGTH_SHORT).show();
    }
    @OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)//用户选择的不再询问
    public void StorageNeverAsk() {
        Toast.makeText(this, "已拒绝WRITE_EXTERNAL_STORAGE权限,并不再询问", Toast.LENGTH_SHORT).show();
    }

注意,以上所有被注解的方法都不能是被private修饰的

4、make project自动生成辅助类

自动生成的辅助类的名称为: 被注解的Activity的名称+PermissionsDispatcher
只要我们实现了@RuntimePermissions和@NeedsPermission这两个必须的注解之后,再build一次project之后,编译器就会在在app\build\intermediates\classes\debug目录下与被注解的Activity同一个包下生成一个辅助类,用来调用被注解的Activity的方法(就是因为这个所以被注解的方法不能private,private方法的作用域不在其他的类)

5、重写Activity的onRequestPermissionsResult()方法

重写该方法之后,当弹出授权对话框时,我们点击允许授权成功时,会自动执行注解@NeedsPermission所标注的方法里面的逻辑。

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
      // 执行回调
      PermissionsDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}

6、最后,申请权限的时候,调用辅助类的方法

当要调用使用权限的方法的时候,不直接调用我们直接添加了@NeedsPermission的方法,而是调用这个辅助类中自动生成的方法,名字从下面可以看出是被@NeedsPermission注解的方法加上WithCheck,参数是这个Activity或者Fragment:

 //申请单个权限
PermissionsDispatcherActivityPermissionsDispatcher.siglePermissionWithCheck(this);
 //申请多个权限
PermissionsDispatcherActivityPermissionsDispatcher.mulPermissionWithCheck(this);

到此,PermissionsDispatcher的使用步骤就介绍完了。

使用示例:

@RuntimePermissions
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // 执行该方法需要权限 -- 录音权限
    @NeedsPermission(Manifest.permission.RECORD_AUDIO)
    void startRecord(String msg) {
        Toast.makeText(MainActivity.this, msg+"222222222222222222222", Toast.LENGTH_SHORT).show();
    }

	// 该方法用于开启权限之后自动执行接下来的逻辑
	@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        SplashActivity3PermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);//将回调交给代理类处理
    }
	
    // 向用户解释为什么需要该权限,,,在第一次弹出权限申请时拒绝之后,再次申请权限时触发
    @OnShowRationale(Manifest.permission.RECORD_AUDIO)
    void showRationaleForRecord(final PermissionRequest request){
        new AlertDialog.Builder(this)
                .setPositiveButton("好的", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 调出系统申请权限的弹窗会执行@NeedsPermissio对应的方法
                        request.proceed();
                    }
                })
                .setNegativeButton("不给", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 会执行@OnPermissionDenied对应的方法
                        request.cancel();
                    }
                })
                .setCancelable(false)
                .setMessage("挑战需要录音权限,应用将要申请录音权限")
                .show();
    }

    // 没有赋予权限时执行
    @OnPermissionDenied(Manifest.permission.RECORD_AUDIO)
    void showRecordDenied(){
        Toast.makeText(MainActivity.this, "拒绝录音权限将无法进行挑战", Toast.LENGTH_SHORT).show();
    }

    // 如果在系统申请弹窗中勾选了不在提示并且拒绝,会调用@OnNeverAskAgain的方法
    @OnNeverAskAgain(Manifest.permission.RECORD_AUDIO)
    void onRecordNeverAskAgain() {
        new AlertDialog.Builder(this)
                .setPositiveButton("好的", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 打开系统设置权限
                        dialog.cancel();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                })
                .setCancelable(false)
                .setMessage("您已经禁止了录音权限,是否现在去开启")
                .show();
    }

    public void order(View view) {
       MainActivityPermissionsDispatcher.startRecordWithCheck(this,"我是通过权限验证之后的!");
    }
}

PermissionsDispatcher插件的使用

觉得这么多注解要自己一个一个弄不够方便,PermissionsDispatcher还在AndroidStudio做了插件,只要在setting设置里的plugins界面里搜索PermissionsDispatcher就可以安装了,安装完重启一下就能使用:
在这里插入图片描述
在所需的Activity或者Fragment的代码里面右键,选择Generate,然后就可以选择Generate Runtime Permissions…(生成动态权限的生成)。
在这里插入图片描述
点击Generate Runtime Permissions…出现如下界面,输入方法名字就能生成:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/gpf1320253667/article/details/82810425