前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你搭建android模块化项目框架(五)权限工具封装

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

原创
作者头像
支离破碎_superLee
发布2023-09-01 14:02:19
1790
发布2023-09-01 14:02:19
举报

废话不多说,先看效果

代码语言:text
复制
  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库,代码如下:

代码语言:text
复制
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库拥有自带的生命周期处理,因此我们仅需要写出申请权限的回调即可。

代码如下:

代码语言:text
复制
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扩展方法来使用,我们封装一个更方便的扩展方法以便调用,代码如下:

代码语言:text
复制
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())
    }
}

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

代码语言:text
复制
//单个权限申请
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已经能达到文章开头的使用效果。

//本代码均未完整测试,建议自行测试后使用。

项目地址

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档