美文网首页Android开发Android开发Android技术知识
手把手教你搭建android项目框架(五)权限工具封装

手把手教你搭建android项目框架(五)权限工具封装

作者: 支离破碎_SuperLee | 来源:发表于2023-08-25 12:19 被阅读0次

    废话不多说,先看效果

      override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.main_act)
            //单个权限
            requestPermission(Manifest.permission.READ_PHONE_STATE) { g, d, ad ->
                Log.v("granted", "READ_PHONE_STATEis granted $g")
            }
            //组合权限
            requestPermission(
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.READ_CONTACTS
            ) { g, d, ad ->
                Log.v("granted", "READ_PHONE_STATE READ_CONTACTS is granted $g")
            }
        }
    

    android6.0以上需要动态请求权限,这里不多废话了,想达到一个简单高效的权限使用方式,就跟我一步一步去封装。
    之前比较好用的权限库是rxPermissions,但是由于目前的项目都不太想引入rxjava使用,因此我们用Kotlin封装一个属于自己的权限库。
    首先我们可以参考下rxPermissions库,代码如下:

    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;
        }
    

    这里我们发现他使用了一个fragment作为媒介接收请求结果,无论在activity或者在fragment中请求时,都会将这个fragment添加到当前页面进行处理,这个思路有点类似glide的生命周期监控,我们可以参考这个思路也创建一个fragment进行操作。
    整个fragment中代码部分仅有权限申请回调处理和对rxjava的生命周期处理,这里我们借用这个思路创建自己的permissionFragment即可。
    由于lifecycle库拥有自带的生命周期处理,因此我们仅需要写出申请权限的回调即可。
    代码如下:

    class PermissionFragment : Fragment() {
        companion object {
            private const val TAG = "PermissionFragment"
            fun getPermissionFragment(
                activity: FragmentActivity,
                block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit
            ): PermissionFragment {
                var permissionFragment = findPermissionsFragment(activity)
                if (permissionFragment == null) {
                    permissionFragment = PermissionFragment()
                    activity.supportFragmentManager.commit(true) {
                        add(permissionFragment, TAG)
                    }
                }
                permissionFragment.block = block
                return permissionFragment
            }
    
            private fun findPermissionsFragment(activity: FragmentActivity): PermissionFragment? {
                return activity.supportFragmentManager.findFragmentByTag(TAG) as? PermissionFragment
            }
        }
    
        //参数说明
        //granted :申请的权限是否都成功了
       //deniedList:被拒绝的权限
      //alwaysDeniedList:被点了不再询问并拒绝的权限
       //这里的参数回调可以根据需求自行封装。
        private var block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit =
            { _, _, _ -> }
    
        private val launcher = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { result ->
            lifecycleScope.launchWhenResumed {
                dealResult(requireActivity(), result, block)
                requireActivity().supportFragmentManager.commit(true) {
                    remove(this@PermissionFragment)
                }
            }
        }
    
        fun requestPermission(
            permissions: Array<String>
        ) {
            lifecycleScope.launchWhenResumed {
                launcher.launch(permissions)
            }
        }
    
        /**
         * 处理请求权限结果
         */
        private suspend fun dealResult(
            activity: FragmentActivity,
            result: Map<String, Boolean>,
            block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit,
        ) = withContext(Dispatchers.IO) {
            val allDeniedList = result.filterValues { !it }.mapNotNull { it.key }
            val alwaysDeniedList =
                allDeniedList.filter {
                    ActivityCompat.shouldShowRequestPermissionRationale(
                        activity,
                        it
                    )
                }
            val deniedList = allDeniedList - alwaysDeniedList.toSet()
            var granted = true
            if (allDeniedList.isNotEmpty()) {
                granted = false
            }
            withContext(Dispatchers.Main) {
                block(granted, deniedList.toTypedArray(), alwaysDeniedList.toTypedArray())
            }
        }
    }
    

    到这一步,我们完成了fragment的开发,但是想要更简单的使用,我们需要借助kotlin扩展方法来使用,我们封装一个更方便的扩展方法以便调用,代码如下:

    fun LifecycleOwner.requestPermission(
        block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit,
        permissions: Array<String>
    ) {
        runCatching {
            when (this@requestPermission) {
                is FragmentActivity -> {
                    PermissionFragment.getPermissionFragment(this@requestPermission, block)
                        .requestPermission(permissions)
                }
    
                is Fragment -> {
                    PermissionFragment.getPermissionFragment(
                        this@requestPermission.requireActivity(),
                        block
                    )
                        .requestPermission(permissions)
                }
    
                else -> {
                    throw RuntimeException("requestPermission LifecycleOwner必须是activity或fragment")
                }
            }
        }.onFailure {
            block(false, permissions, arrayOf())
        }
    }
    

    上述封装了一个初步可用的扩展方法,但是为了更方便使用,我们进一步封装,单个,两个组合,三个组合的方法,更方便使用,代码如下:

    //单个权限申请
    fun LifecycleOwner.requestPermission(
        p1: String,
        block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit
    ) {
        requestPermission(block, arrayOf(p1))
    }
    //两个个权限组合申请
    fun LifecycleOwner.requestPermission(
        p1: String,
        p2: String,
        block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit
    ) {
        requestPermission(block, arrayOf(p1, p2))
    }
    
    //三个权限组合申请
    fun LifecycleOwner.requestPermission(
        p1: String,
        p2: String,
        p3: String,
        block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit
    ) {
        requestPermission(block, arrayOf(p1, p2, p3))
    }
    //四个权限组合申请
    fun LifecycleOwner.requestPermission(
        p1: String,
        p2: String,
        p3: String,
        p4: String,
        block: (granted: Boolean, deniedList: Array<String>, alwaysDeniedList: Array<String>) -> Unit
    ) {
        requestPermission(block, arrayOf(p1, p2, p3, p4))
    }
    

    至此,权限Util已经能达到文章开头的使用效果。
    //本代码均未完整测试,建议自行测试后使用。
    项目地址

    相关文章

      网友评论

        本文标题:手把手教你搭建android项目框架(五)权限工具封装

        本文链接:https://www.haomeiwen.com/subject/qhwmmdtx.html