I can't figure out the states in compose. It seems to me that I am missing something in the logic of the framework. (I am not an android expert and this is not my main language)
The task is as follows. The application requires rights to make calls, as well as permission to work on top of other applications and permission to disable battery optimization. For each type, you need to display a separate notification with a button (I use AlertDialog), by clicking on which the rights request will be executed by the system.
I can find out if a rights request is required or not, as well as request rights directly. It is necessary that the application checks for rights, and then displays a notification with rights IN ORDER and does not close if the user has not enabled permission.
A dialog opened - the user clicked on the open settings button - a system dialog opened - the user allowed or denied - upon returning to the application, check whether the user allowed, if yes - open the next dialog (or nothing, if all rights are allowed), if not - show the same dialog so that the user still allows access.
I can't figure out how to build logic in compose in this case. I do this dialog
@Composable
fun AlertNeedPermissionDialog(
explanationText: String, buttonText: String, buttonAction: Int
) {
val openDialog = remember { mutableStateOf(true) }
var confirmAction by remember { mutableStateOf(0) }
if (openDialog.value) {
AlertDialog(shape = RoundedCornerShape(10.dp), properties = DialogProperties(
dismissOnBackPress = false, dismissOnClickOutside = false
), backgroundColor = Color.Transparent, buttons = {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.shadow(
elevation = 32.dp,
spotColor = Color(0x14000000),
ambientColor = Color(0x14000000)
).fillMaxWidth().background(
color = Color(0xFFFFFFFF), shape = RoundedCornerShape(size = 16.dp)
).padding(start = 24.dp, top = 32.dp, end = 24.dp, bottom = 24.dp)
) {
Text(
text = explanationText, style = TextStyle(
fontSize = 17.sp,
lineHeight = 22.sp,
fontWeight = FontWeight(400),
color = Color(0xFF1C1C1E),
letterSpacing = 0.15.sp,
)
)
Row(
horizontalArrangement = Arrangement.spacedBy(
8.dp, Alignment.CenterHorizontally
),
verticalAlignment = Alignment.Top,
) {
Button(modifier = Modifier.height(54.dp).fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF369BFF)
),
shape = RoundedCornerShape(8.dp),
onClick = {
// openDialog.value = false
confirmAction = buttonAction
}) {
Text(
text = "Open settings", style = TextStyle(
fontSize = 17.sp,
lineHeight = 22.sp,
fontFamily = fontFamilyResource(MR.fonts.ProximaSoft.regular),
fontWeight = FontWeight(400),
color = Color(0xFFFFFFFF),
textAlign = TextAlign.Center,
letterSpacing = 0.15.sp,
)
)
}
}
}
}, onDismissRequest = {})
when (confirmAction) {
1 -> EnableOverlayMode()
2 -> DisableBatteryOptimisation()
3 -> askCallLog()
}
}
}
It works, but not really. If you click the "open settings" button for the first time, but do not allow the rights, then after returning to the application, the button will no longer work, because the confirmation does not change anymore.
Is there any way to force recomposition, for example?
It’s unlikely that my solution is optimal, but this is what I did for now
@Composable
fun AlertNeedPermissionDialog(
explanationText: String, buttonText: String, buttonAction: Int
) {
val openDialog = remember { mutableStateOf(true) }
var confirmAction by remember { mutableStateOf(0) }
if (openDialog.value) {
AlertDialog(shape = RoundedCornerShape(10.dp), properties = DialogProperties(
dismissOnBackPress = false, dismissOnClickOutside = false
), backgroundColor = Color.Transparent, buttons = {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.shadow(
elevation = 32.dp,
spotColor = Color(0x14000000),
ambientColor = Color(0x14000000)
).fillMaxWidth().background(
color = Color(0xFFFFFFFF), shape = RoundedCornerShape(size = 16.dp)
).padding(start = 24.dp, top = 32.dp, end = 24.dp, bottom = 24.dp)
) {
Text(
text = explanationText, style = TextStyle(
fontSize = 17.sp,
lineHeight = 22.sp,
fontWeight = FontWeight(400),
color = Color(0xFF1C1C1E),
letterSpacing = 0.15.sp,
)
)
Row(
horizontalArrangement = Arrangement.spacedBy(
8.dp, Alignment.CenterHorizontally
),
verticalAlignment = Alignment.Top,
) {
Button(modifier = Modifier.height(54.dp).fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF369BFF)
),
shape = RoundedCornerShape(8.dp),
onClick = {
if (confirmAction == buttonAction) {
confirmAction = -buttonAction
} else {
confirmAction = buttonAction
}
}) {
Text(
text = "Open settings", style = TextStyle(
fontSize = 17.sp,
lineHeight = 22.sp,
fontFamily = fontFamilyResource(MR.fonts.ProximaSoft.regular),
fontWeight = FontWeight(400),
color = Color(0xFFFFFFFF),
textAlign = TextAlign.Center,
letterSpacing = 0.15.sp,
)
)
}
}
}
}, onDismissRequest = {})
when (confirmAction) {
1, -1 -> EnableOverlayMode()
2, -2 -> DisableBatteryOptimisation()
3, -3 -> askCallLog()
}
}
}