Android动态权限申请(Kotlin版)

4,922 阅读3分钟

Android6.0之后,APP有些用到的权限需要动态申请,虽然这个功能已经出来好久了,但一直没有研究过,只知道用法简单,到时候copy一下就好了,github上也有许多开源的框架供大家使用。本篇博客先介绍一下Android动态权限申请的使用方法(虽然可以copy,但还是要研究一下的),接着分析一下RxPermissions的源码,然后博主自己也写了一个开源lib,Kotlin版的,如果项目使用Kotlin作为开发语言的,可以考虑使用一下。

Android动态权限申请

Android6.0之后,权限级别分为正常权限和危险权限:
正常权限对用户隐私或其他应用操作风险较小,只需要在应用声明中声明即可使用。
危险权限涉及到用户隐私信息的数据或资源,因此,在应用声明之后,还需要用户动态向应用赋予该权限。
危险权限详见:Android系统权限

这里的使用方法直接介绍v4包里集成的:

检查权限

请求权限之前,先要检查是否具有该权限


                                                
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
	//无权限时执行此处
}


                                            

用户历史权限操作

当用户拒绝权限,再次打开APP,需要再次向用户需要申请改权限时,可以向用户说明该权限的重要性,拒绝权限可能会影响使用


                                                
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission, requestCode)) {
	//用户拒绝过改权限时,执行此处
}


                                            

请求权限

向用户请求所使用的权限,这里的permissions可以是多少权限。


                                                
ActivityCompat.requestPermissions(activity, permissions)


                                            

请求权限回调结果

在Activity中实现以下方法,其中requestCode为请求权限是所传的请求码,permissions为所请求权限的数组,grantResults为对应的权限请求结果。


                                                
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}


                                            

RxPermissions源码分析

RxPermissions一共有三个类,Permission、RxPermissions、RxPermissionFragment。

Permission类

Permission类为权限类,name、granted、shouldShowRequestPermissionRationale分别对应权限名称、请求权限结果和用户是否拒绝过权限。

RxPermissions类

RxPermissions类提供了初始化、请求权限的接口、提供Transformer的一些接口,并持有一个RxPermissionsFragment实例,在RxPermissionsFragment实现请求权限。

优点:
本框架可以提供对RxJava的支持,也可以支持查看每项权限的申请结果。

缺点:
想开始用的时候还有些疑惑,为什么google给出的请求权限的方法都需要去实现回调,而这个框架就不需要呢?
之后仔细看了一下源码,发现在新建RxPermissions类的时候,框架会悄悄的新建一个RxPermissionsFragment类,也就是说框架在内部封装了一个没有界面的fragment,这样做的好处是请求权限的回调可以在Fragment中实现,不需要用户再去调用,不过我总是觉得这样做对android性能优化不是很好,源码如下:


                                                
private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {
    RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity);
    boolean isNewInstance = rxPermissionsFragment == null;
    if (isNewInstance) {
        rxPermissionsFragment = new RxPermissionsFragment();
        FragmentManager fragmentManager = activity.getFragmentManager();
        fragmentManager
                .beginTransaction()
                .add(rxPermissionsFragment, TAG)
                .commitAllowingStateLoss();
        fragmentManager.executePendingTransactions();
    }
    return rxPermissionsFragment;
}


                                            

KPermissions

这是博主自己封装的一个请求权限lib,使用kotlin语言编写,采用android v4包提供的权限请求方法,源码以放在了github:KPermissions,欢迎star,也希望路过的大神可以多加指点,下面说一下框架的用法及功能。

集成

在APP build.gradle中,minSdkVersion必须大于等于14.
build.gradle配置如下:


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

dependencies {
    compile 'cn.hchstudio:kpermissions:1.0.8'
}


                                                

用法

创建KPermissions实例:


                                                    
var kPermission: KPermission = KPermission(this)


                                                

请求权限:


                                                    
kPermission.requestPermission(arrayOf(Manifest.permission.CAMERA), {
    Log.i(TAG, "isAllow---$it")
}, {
    Log.i(TAG, "permission---$it")
})


                                                

第一个参数为需要请求权限的数组,第二个为是否全部请求成功的回调,第三个为请求每项权限时的回调。

实现onRequestPermissionsResult回调:


                                                    
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    kPermission.onRequestPermissionsResult(requestCode, permissions, grantResults)
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}


                                                

框架也支持在java中使用,详细见JavaActivity