Author SHA1 Message Date
MrBlakeandClaude Opus 5.5 a332ca9c23 fix(telefon): ask for the phone role on first start and before calling without it; 0.1.1
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 16:41:47 +02:00
3 changed files with 28 additions and 3 deletions
+2 -2
View File
@@ -16,8 +16,8 @@ android {
applicationId = "app.telefon" applicationId = "app.telefon"
minSdk = 29 minSdk = 29
targetSdk = 36 targetSdk = 36
versionCode = 1 versionCode = 2
versionName = "0.1.0" versionName = "0.1.1"
} }
// Release key lives outside the repo; without it, release builds fall back to the debug key (local only). // Release key lives outside the repo; without it, release builds fall back to the debug key (local only).
@@ -102,14 +102,36 @@ private fun PhoneApp(dialRequest: String?, onDialHandled: () -> Unit) {
val roleLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { val roleLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
isDefault = role.isRoleHeld(RoleManager.ROLE_DIALER); granted = hasCore(ctx) isDefault = role.isRoleHeld(RoleManager.ROLE_DIALER); granted = hasCore(ctx)
} }
var askedRole by rememberSaveable { mutableStateOf(false) }
// first start: ask for the role right away; the dialog grants the phone permissions too
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
if (!isDefault && !askedRole && role.isRoleAvailable(RoleManager.ROLE_DIALER)) {
askedRole = true
roleLauncher.launch(role.createRequestRoleIntent(RoleManager.ROLE_DIALER))
return@LaunchedEffect
}
if (!granted) perms.launch(arrayOf(Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE, if (!granted) perms.launch(arrayOf(Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE,
Manifest.permission.READ_PHONE_STATE, Manifest.permission.POST_NOTIFICATIONS)) Manifest.permission.READ_PHONE_STATE, Manifest.permission.POST_NOTIFICATIONS))
} }
val log by remember(granted) { Contacts.callLog(ctx) }.collectAsState(initial = emptyList()) val log by remember(granted) { Contacts.callLog(ctx) }.collectAsState(initial = emptyList())
val people by remember(granted) { Contacts.people(ctx) }.collectAsState(initial = emptyList()) val people by remember(granted) { Contacts.people(ctx) }.collectAsState(initial = emptyList())
val call: (String) -> Unit = { n -> placeCall(ctx, n) } var pendingNumber by remember { mutableStateOf<String?>(null) }
// without the role Android shows the call in the system phone app: say so instead of jumping away
val call: (String) -> Unit = { n -> if (isDefault) placeCall(ctx, n) else pendingNumber = n }
pendingNumber?.let { n ->
androidx.compose.material3.AlertDialog(
onDismissRequest = { pendingNumber = null },
title = { Text(stringResource(R.string.default_title)) },
text = { Text(stringResource(R.string.not_default_call)) },
confirmButton = {
androidx.compose.material3.TextButton(onClick = { pendingNumber = null; roleLauncher.launch(role.createRequestRoleIntent(RoleManager.ROLE_DIALER)) }) {
Text(stringResource(R.string.make_default))
}
},
dismissButton = { androidx.compose.material3.TextButton(onClick = { pendingNumber = null; placeCall(ctx, n) }) { Text(stringResource(R.string.call_anyway)) } },
)
}
screen?.let { s -> screen?.let { s ->
BackHandler { screen = null } BackHandler { screen = null }
@@ -36,6 +36,9 @@
<string name="default_title">Als Standard-Telefon-App festlegen</string> <string name="default_title">Als Standard-Telefon-App festlegen</string>
<string name="default_text">Nur dann kann diese App Anrufe annehmen und anzeigen. Du kannst das jederzeit in den Android-Einstellungen ändern.</string> <string name="default_text">Nur dann kann diese App Anrufe annehmen und anzeigen. Du kannst das jederzeit in den Android-Einstellungen ändern.</string>
<string name="not_default_call">Diese App ist noch nicht deine Standard-Telefon-App. Android zeigt den Anruf deshalb in der System-Telefon-App an.</string>
<string name="make_default">Als Standard festlegen</string>
<string name="call_anyway">Trotzdem anrufen</string>
<string name="incoming_call">Eingehender Anruf</string> <string name="incoming_call">Eingehender Anruf</string>
<string name="calling">Wird angerufen …</string> <string name="calling">Wird angerufen …</string>
<string name="on_hold">Gehalten</string> <string name="on_hold">Gehalten</string>