在 Jetpack Compose 动态申请权限可以使用两种方法
- rememberLancherForActivityResult
- Accompanist 的 Permissions
接下来分贝展示一下两种用法
- 代码环境如下:
- 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】)