Jetpack Compose 的最佳处理运行时权限的方法

Jetpack Compose 的最佳处理运行时权限的方法

android permission in Jetpack compose
如果您的应用安装在运行Android 6.0(API级别23)或更高版本的设备上,则必须按照本指南中的步骤为用户请求运行时权限。

在Jetpack Compose中获取运行时权限有两种方法。

  • 使用Activity Result
  • 使用Accompanist Permissions库

接下来,让我们仔细研究上述两种方法,并附有示例。

使用Activity Result进行运行时权限

第一步是在manifest.xml文件中定义权限。


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera"/>

在这个示例应用程序中,我使用相机权限示例来捕获图像。请查看我的其他示例,以了解如何使用相机捕获图像。

如何在 jetpack compose 中使用相机捕获图像 (howtodoandroid.com)

https://www.howtodoandroid.com/capture-image-in-jetpack-compose/

如何在 jetpack compose 中从图库选择图像 (howtodoandroid.com)

https://www.howtodoandroid.com/pick-image-from-gallery-jetpack-compose/

创建一个活动结果启动器来请求我们定义的权限。一旦启动,它将返回结果,无论该权限是否被授予。

val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) {
    
    
        if (it) {
    
    
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
            cameraLauncher.launch(uri)
        } else {
    
    
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }

    }

检查权限

在请求权限之前,我们需要检查权限是否已经被授予。如果已经授予,我们可以继续正常流程。如果权限未被授予,那么我们需要使用我们需要的权限来发起权限请求。

val permissionCheckResult = ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA)

            if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
    
    
                cameraLauncher.launch(uri)
            } else {
    
    
  permissionLauncher.launch(android.Manifest.permission.CAMERA)
            }

最后,使用活动结果实现运行时权限的代码将如下所示:


val context = LocalContext.current
    val file = context.createImageFile()
    val uri = FileProvider.getUriForFile(
        Objects.requireNonNull(context),
        BuildConfig.APPLICATION_ID + ".provider", file
    )

    var capturedImageUri by remember {
    
    
        mutableStateOf<Uri>(Uri.EMPTY)
    }

    val cameraLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
    
    
            capturedImageUri = uri
        }
    val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) {
    
    
        if (it) {
    
    
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
            cameraLauncher.launch(uri)
        } else {
    
    
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }

    }

    Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
    
    
        Button(onClick = {
    
    
            val permissionCheckResult = ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA)

            if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
    
    
                cameraLauncher.launch(uri)
            } else {
    
    
                // Request a permission
                permissionLauncher.launch(android.Manifest.permission.CAMERA)
            }

        }) {
    
    
            Text(text = "Open Camera")
        }

        if (capturedImageUri.path?.isNotEmpty() == true) {
    
    
            Image(
                modifier = Modifier
                    .padding(16.dp, 8.dp)
                    .fillMaxWidth()
                    .size(400.dp),
                painter = rememberImagePainter(capturedImageUri),
                contentDescription = null
            )
        }
    }

上面的效果如下:
在这里插入图片描述

请求多个权限

在某些情况下,我们需要一次请求多个权限,例如,位置权限。为此,我们需要使用不同的启动器方法和权限检查。我们来详细看看。

像往常一样,我们需要在 manifest.xml 文件中定义所需的权限。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

需要的第一步是创建包含我们要请求的权限列表。

val permissions = arrayOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )

使用ActivityResultContracts.RequestMultiplePermissions() 方法一次性请求多个权限。使用此函数并创建权限启动器。

val launcherMultiplePermissions = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) {
    
     permissionsMap ->
        val areGranted = permissionsMap.values.reduce {
    
     acc, next -> acc && next }
        if (areGranted) {
    
    
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
        } else {
    
    
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }
    }

现在,启动器已准备好进行多个权限。下一步是检查权限是否已经授予。如果没有授予,则使用权限列表启动权限启动器。

if(permissions.all {
    
    
    ContextCompat.checkSelfPermission(
        context,
        it
    ) == PackageManager.PERMISSION_GRANTED
}) {
    
    
    // Get the location
} else {
    
    
    launcherMultiplePermissions.launch(permissions)
}

请求多个运行时权限的最终代码将是:

val permissions = arrayOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )

    val launcherMultiplePermissions = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) {
    
     permissionsMap ->
        val areGranted = permissionsMap.values.reduce {
    
     acc, next -> acc && next }
        if (areGranted) {
    
    
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
        } else {
    
    
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }
    }

    Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
    
    
        Button(onClick = {
    
    

            if(permissions.all {
    
    
                ContextCompat.checkSelfPermission(
                    context,
                    it
                ) == PackageManager.PERMISSION_GRANTED
            }) {
    
    
                // Get the location
            } else {
    
    
                launcherMultiplePermissions.launch(permissions)
            }

        }) {
    
    
            Text(text = "Get Current Location")
        }
      
    }

使用accompanist permissions库

与第一种使用方法相比,使用accompanist permission库是一种更容易获得运行时权限的方法。在build.gradle文件中添加该库。

implementation "com.google.accompanist:accompanist-permissions:0.23.1"

添加依赖项后,需要使用rememberPermissionState()方法来维护我们传递给它的权限状态。同时使用PermissionRequired()来观察运行时的权限状态。它包含所有权限状态的视图,比如允许或拒绝的视图。

val permissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)

    PermissionRequired(
        permissionState = permissionState,
        permissionNotGrantedContent = {
    
    
            Toast.makeText(context, "Permission not granted", Toast.LENGTH_SHORT).show()
        },
        permissionNotAvailableContent = {
    
    
            Toast.makeText(context, "Permission not available", Toast.LENGTH_SHORT).show()
        }) {
    
    
        if (isShowCamera) {
    
    
            cameraLauncher.launch(uri)
            isShowCamera = false
        }
    }

由于在这个示例中使用相机,需要创建相机启动器来从活动结果中捕获图像。

val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
    
    
            isShowCamera = false
            capturedImageUri = uri
        }

现在我们已经完成了权限状态和相机启动器的设置。下一步是使用权限。点击任何按钮或操作时,我们需要调用permissionState.hasPermission来检查权限是否被授予。 如果没有被授予,我们需要调用权限状态启动器以显示运行时权限对话框。

Button(onClick = {
    
    
    if(permissionState.hasPermission) {
    
    
        cameraLauncher.launch(uri)
    } else {
    
    
        isShowCamera = true
        permissionState.launchPermissionRequest()
    }
}) {
    
    
    Text(text = "Open Camera")
}

同样地,您可以使用Accompanist库请求多个权限。查看以下代码以获取使用Accompanist请求多个权限的示例。

val permissionsState = rememberMultiplePermissionsState(
    permissions = listOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
)

PermissionsRequired(
multiplePermissionsState = permissionsState,
permissionsNotGrantedContent = {
    
    
    Toast.makeText(context, "Permission not granted", Toast.LENGTH_SHORT).show()
},
permissionsNotAvailableContent = {
    
    
    Toast.makeText(context, "Permission not available", Toast.LENGTH_SHORT).show()
}) {
    
    
    //content

}
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
    
    
    Button(onClick = {
    
    

        if(permissionsState.permissions.all {
    
    
                ContextCompat.checkSelfPermission(
                    context,
                    it.permission
                ) == PackageManager.PERMISSION_GRANTED
            }) {
    
    
            // access location

        } else {
    
    

            permissionsState.launchMultiplePermissionRequest()
        }
    }) {
    
    
        Text(text = "Location Permission")
    }

}

效果如下
demo effect

完整代码地址

https://github.com/velmurugan-murugesan/JetpackCompose/tree/master/RuntimePermissionJetpackCompose

猜你喜欢

转载自blog.csdn.net/u011897062/article/details/131006129