Skip to content

Instantly share code, notes, and snippets.

@decodeandroid
Last active December 2, 2024 06:11
Show Gist options
  • Save decodeandroid/7d7761300589c732174d0865352a1264 to your computer and use it in GitHub Desktop.
Save decodeandroid/7d7761300589c732174d0865352a1264 to your computer and use it in GitHub Desktop.
Permission Handling in Jetpack Compose | Android Kotlin
val permissionManager = PermissionManager(this@MainActivity)
setContent {
var permissionResults by remember {
mutableStateOf<Map<String, Boolean>>(emptyMap())
}
var showSettingsDialogForPermission by remember { mutableStateOf<String?>(null) }
val permissions = listOf(
android.Manifest.permission.POST_NOTIFICATIONS,
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.READ_CONTACTS
)
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
val grantedPermissions =
permissionResults.filterValues { it }.keys.joinToString(", ")
val deniedPermissions =
permissionResults.filterValues { !it }.keys.joinToString(", ")
val message = buildAnnotatedString {
if (grantedPermissions.isNotEmpty()) withStyle(style = SpanStyle(color = Color.Green)) {
append("Granted: \n $grantedPermissions. \n \n")
}
if (deniedPermissions.isNotEmpty()) withStyle(style = SpanStyle(color = Color.Red)) {
append("Denied: \n $deniedPermissions.")
}
}
Text(
message,
Modifier.fillMaxWidth(),
fontSize = 20.sp,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = {
permissionManager.requestPermissions(permissions) { results ->
permissionResults = results
val permanentlyDenied = permissionManager.getPermanentlyDeniedPermissions()
if (permanentlyDenied.isNotEmpty()) {
showSettingsDialogForPermission = permanentlyDenied.joinToString(", ")
}
}
}) {
Text("Request Permissions")
}
// Show dialog for permanently denied permissions
showSettingsDialogForPermission?.let { permission ->
GoToSettingsDialog(
context = this@MainActivity,
permission = permission,
onDismiss = { showSettingsDialogForPermission = null }
)
}
}
}
import android.content.Context
import android.content.Intent
import android.provider.Settings
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
class PermissionManager(
private val activity: ComponentActivity
) {
private var permissionResults: (Map<String, Boolean>) -> Unit = {}
private val permanentlyDeniedPermissions = mutableListOf<String>()
private val permissionLauncher =
activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { results ->
val permanentlyDenied = results.filter { !it.value && !activity.shouldShowRequestPermissionRationale(it.key) }
permanentlyDeniedPermissions.clear()
permanentlyDeniedPermissions.addAll(permanentlyDenied.keys)
permissionResults(results)
}
fun requestPermissions(
permissions: List<String>,
onResults: (Map<String, Boolean>) -> Unit
) {
permissionResults = onResults
permissionLauncher.launch(permissions.toTypedArray())
}
fun getPermanentlyDeniedPermissions(): List<String> = permanentlyDeniedPermissions
}
@Composable
fun GoToSettingsDialog(
context: Context,
permission: String,
onDismiss: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(text = "Permission Required")
},
text = {
Text(text = "The following permission(s) are permanently denied: $permission. Please enable them in the app settings to use this feature.")
},
confirmButton = {
TextButton(onClick = {
onDismiss()
context.startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = android.net.Uri.fromParts("package", context.packageName, null)
})
}) {
Text("Open Settings")
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text("Cancel")
}
}
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment