Jetpack Compose 动态权限申请(Permission Request)

Posted fundroid_方卓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jetpack Compose 动态权限申请(Permission Request)相关的知识,希望对你有一定的参考价值。

在 Jetpack Compose 动态申请权限可以使用两种方法

接下来分贝展示一下两种用法

  • 代码环境如下:
    • Kotlin 1.5.2
    • Jetpack Compose 1.0.2
    • android Studio Chipmunk | 2021.2.1

要使用 Accompanist 需要额外引入

dependencies {
	...
    implementation "com.google.accompanist:accompanist-permissions:0.16.1"
	...
}

1. rememberLauncherForActivityResult 方式

rememberLauncherForActivityResult 是基于 Activity 的 ResultAPI 获取动态权限。例如我们可以在新打开一个 Activity 时通过这种方式获取权限:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RequestPermission()
        }
    }
}

@Composable
private fun RequestPermission() {
    // 基于 LocalComposition 获取 Context
    val context = LocalContext.current

    // 基于 LocalLifecycleOwner 获取 Lifecycle
    val lifecycle = LocalLifecycleOwner.current.lifecycle

    // 定义需要动态获取的 Permission 类型
    val permission = Manifest.permission.READ_EXTERNAL_STORAGE

    // Result API 调用时的 launcher
    val launcher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestPermission(),
        onResult = { isGranted -> 
        	//判断权限申请结果,并根据结果侠士不同画面,由于 onResult 不是一个 @Composable lambda,所以不能直接显示 Composalbe 需要通过修改 state 等方式间接显示 Composable
        }
    )

    // 在 Activity onStart 时,发起权限事情,如果权限已经获得则跳过
    val lifecycleObserver = remember {
        LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_START) {
                if (!permission.isGrantedPermission(context)) {
                    launcher.launch(permission)
                }
            }
        }
    }

    // 当 Lifecycle 或者 LifecycleObserver 变化时注册回调,注意 onDispose 中的注销处理避免泄露
      DisposableEffect(lifecycle, lifecycleObserver) {
        lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycle.removeObserver(lifecycleObserver)
        }
    }
}

private fun String.isGrantedPermission(context: Context): Boolean {
    // 判断是否已经后的状态
    return context.checkSelfPermission(this) == PackageManager.PERMISSION_GRANTED
}

当进入 MainActivity 时请求权限的效果

2. Accompanist Permissions方式

Accompanist Permission 将权限申请结果以一个 Composable State 的形式返回,调用形式相较于第一种更加易用 。比如,我们通过该点击按钮动态申请权限

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RequestPermissionUsingAccompanist()
        }
    }
}

@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun RequestPermissionUsingAccompanist() {
    val permission = Manifest.permission.READ_EXTERNAL_STORAGE

    // 定义 Permission State
    val permissionState = rememberPermissionState(permission)
    PermissionRequired(
        permissionState = permissionState,
        permissionNotAvailableContent = {
            // 权限获取失败
            Text("Permission Denied.")
        }, permissionNotGrantedContent = {
            // 尚未获取权限时
            Button(onClick = { permissionState.launchPermissionRequest() }) {
                Text("Request permission.")
            }
        }, content = {
            // 权限获取成功
            Text("Permission Granted.")
        }
    )
}

代码非常清晰,PermissionRequired 接收几个 Composable lambda 的参数,分别对应权限申请后,不同处理下的回调:

  • permissionNotGrantedContent:尚未获取权限或者获取失败(点击【Deny】)
  • permissionNotAvailableContent:点击【Deny & don’t ask again】时
  • content : 获取成功(点击【Allow】)


以上是关于Jetpack Compose 动态权限申请(Permission Request)的主要内容,如果未能解决你的问题,请参考以下文章

Jetpack Compose 中的动态加载插件化技术探索

Jetpack Compose 使用 SubcomposeLayout 动态地将兄弟 Composables 的宽度设置为最长的宽度

Jetpack Compose中的Accompanist

Jetpack Compose 与 Material You 常见问题解答

如何在 Jetpack Compose 的 LazyColumn/LazyRow 中禁用和启用滚动?

Jetpack All In Compose ?看各种Jetpack库在Compose中的使用