RxPermission 0.10.2 原理分析

本文深入解析Android6.0系统下运行时权限管理机制,包括普通权限与危险权限的区别,以及如何使用RxPermissions库进行权限申请。通过源码分析,揭示RxPermissions的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要进行权限申请?

Android 6.0 ( API23 MarshMallow 棉花糖):运行时权限

  • 在6.0之前,应用安装时,会提示APP所需要的权限列表,同意之后安装,该app就被赋予所有的权限。

  • 在6.0之后,google对权限进行了分类,普通权限和危险权限。无论是普通权限还是危险权限都需要在AndroidManifest中进行声明。普通权限在应用安装时就会被授予;而危险权限需要在应用安装之后进行动态申请,由用户进行管控。总共有9组危险权限,对于同一组内的危险权限,只要申请一个就行了,申请一个就相当于全家桶(全组许可)。
    在这里插入图片描述

系统提供的权限申请方式

申请单个相机权限:ContextCompat 、ActivityCompat 、

//设置requestCode
private val PERMISSION_REQUEST_CAMERA = 1
//判断是否已经授予相机权限,没有则进行申请; 否则do something you wanted
private fun requestPermissionNormal() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 
    != PackageManager.PERMISSION_GRANTED) {
    	//没有授予权限
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 
        PERMISSION_REQUEST_CAMERA)
    } else {
        //todo something you wanted
    }
}

//申请权限结果的回调 activity 和 fragment都有这个方法

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<outString>, grantResults: IntArray) {
    if (requestCode == PERMISSION_REQUEST_CAMERA) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //todo something you wanted
        } else {
            // Permission Denied
        }
        return
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

RxPermissions的实现方式

github地址 https://github.com/tbruyelle/RxPermissions
推荐在onCreate中使用

依赖引入:

project 的 build.gradle

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

module 的 build.gradle

implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
单个权限申请
val rxPermission = RxPermissions(this@MainActivity)
rxPermission.request(Manifest.permission.CAMERA)
        .subscribe(Consumer<Boolean> { granted ->
            if (granted) {
                Log.d(MyApplication.TAG, " is granted.")
            } else {
                Log.d(MyApplication.TAG, " is denied.")
            }
        })
多个权限申请
val rxPermission = RxPermissions(this@MainActivity)
rxPermission.requestEach(Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_CALENDAR,
        Manifest.permission.READ_CALL_LOG,
        Manifest.permission.READ_CONTACTS,
        Manifest.permission.READ_PHONE_STATE)
        .subscribe(Consumer<Permission> { permission ->
            if (permission.granted) {
                // 用户已经同意该权限
                Log.d(MyApplication.TAG, permission.name + " is granted.")
            } else if (permission.shouldShowRequestPermissionRationale) {
                // 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框
                Log.d(MyApplication.TAG, permission.name + " is denied. More info should be provided.")
            } else {
                // 用户拒绝了该权限,并且选中『不再询问』
                Log.d(MyApplication.TAG, permission.name + " is denied.")
            }
        })

那么RxPermissions是如何实现的呢?下面我们进入源码分析。

RxPermissions 就包含4个类,真正有用的是Permission/ RxPermissions/ RxPermissionsFragment

源码分析
创建RxPermissions的实例
  • 根据TAG找rxPermissionFragment,为空的话就new 一个rxPermissionFragment,并添加进来。
  • RxPermissionFragment 没有加载布局(用户无感知),在fragment中进行权限的申请和结果反馈。

RxPermissions.java

public RxPermissions(FragmentActivity activity) {
    this.mRxPermissionsFragment = this.getLazySingleton(activity.getSupportFragmentManager());
}
//支持在activity/fragment中使用
public RxPermissions(Fragment fragment) {
    this.mRxPermissionsFragment = this.getLazySingleton(fragment.getChildFragmentManager());
}

//单例,懒加载的方式返回一个RxPermissionFragment
private RxPermissions.Lazy<RxPermissionsFragment> getLazySingleton(final FragmentManager fragmentManager) {
    return new RxPermissions.Lazy<RxPermissionsFragment>() {
        private RxPermissionsFragment rxPermissionsFragment;

        public synchronized RxPermissionsFragment get() {
            if (this.rxPermissionsFragment == null) {
                this.rxPermissionsFragment = RxPermissions.this.getRxPermissionsFragment(fragmentManager);
            }
            return this.rxPermissionsFragment;
        }
    };
}
//fragmentManager添加进来
private RxPermissionsFragment getRxPermissionsFragment(FragmentManager fragmentManager) {
    RxPermissionsFragment rxPermissionsFragment = this.findRxPermissionsFragment(fragmentManager);
    boolean isNewInstance = rxPermissionsFragment == null;
    if (isNewInstance) {
        rxPermissionsFragment = new RxPermissionsFragment();
        fragmentManager.beginTransaction().add(rxPermissionsFragment, TAG).commitNow();
    }
    return rxPermissionsFragment;
}
//只加载一个fragment
private RxPermissionsFragment findRxPermissionsFragment(FragmentManager fragmentManager) {
    return (RxPermissionsFragment)fragmentManager.findFragmentByTag(TAG);
}


在fragment中进行权限的申请和结果反馈。
其它的就是RxJava的各种操作符了。

  • request() 请求权限列表,需要等所有权限请求都执行完后,才返回true/false,只要有一个失败,就返回false
  • requestEach(),分两部分返回,已经授权的先返回;没有授权的,等待所有权限请求都执行完后,才返回。每一个申请的权限,都有一个Permission类(name、granted、shouldShowRequestPermissionRationale(字段为false,即用户点击了禁止后不再询问,且拒绝了权限授予,以后不会再弹框))

需要在AndroidManifest.xml中,声明这些permission,否则就直接拒绝了,无法弹框处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值