diff --git a/gearslip/src/main/AndroidManifest.xml b/gearslip/src/main/AndroidManifest.xml
index c683230..b54c265 100644
--- a/gearslip/src/main/AndroidManifest.xml
+++ b/gearslip/src/main/AndroidManifest.xml
@@ -162,6 +162,12 @@
activity so Settings can switch off just this (AppSettings.setGearslipEnabled) and leave
the head unit to Android Auto, without disabling the screen the switch is on.
-->
+
+
, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ GearslipLog.i("permissions: ${permissions.zip(grantResults.toList()).joinToString { (p, r) -> "${p.substringAfterLast('.')}=${r == 0}" }}")
+ finish()
+ }
+
+ companion object {
+ private const val EXTRA_PERMISSIONS = "permissions"
+ private const val REQUEST = 1
+
+ /** Shows the permission dialog on the phone, whichever screen [context] belongs to. */
+ fun ask(context: Context, permissions: Array) {
+ val intent = Intent(context, PermissionActivity::class.java)
+ .putExtra(EXTRA_PERMISSIONS, permissions)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ val options = ActivityOptions.makeBasic().setLaunchDisplayId(Display.DEFAULT_DISPLAY)
+ runCatching { context.startActivity(intent, options.toBundle()) }
+ .onFailure { GearslipLog.w("permissions: could not ask on the phone: ${it.message}") }
+ }
+ }
+}
diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/PhoneDialerScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/PhoneDialerScreen.kt
index ad215fe..e691c23 100644
--- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/PhoneDialerScreen.kt
+++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/PhoneDialerScreen.kt
@@ -133,7 +133,7 @@ private const val TAB_KEYPAD = 1
@Composable
fun PhoneDialerScreen() {
val context = LocalContext.current
- val hasPermissions = hasCallPermissions(context)
+ var hasPermissions by remember { mutableStateOf(hasCallPermissions(context)) }
var tab by remember { mutableStateOf(TAB_CONTACTS) }
Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
@@ -148,7 +148,7 @@ fun PhoneDialerScreen() {
}
if (!hasPermissions) {
- MissingPermission(context)
+ MissingPermission(context) { hasPermissions = true }
return@Column
}
@@ -159,19 +159,23 @@ fun PhoneDialerScreen() {
}
@Composable
-private fun MissingPermission(context: Context) {
+private fun MissingPermission(context: Context, onGranted: () -> Unit) {
+ // Android's dialog can't show on the car screen, so it opens on the phone; checking again
+ // every second picks the answer up without the driver having to come back in.
+ androidx.compose.runtime.LaunchedEffect(Unit) {
+ while (!hasCallPermissions(context)) kotlinx.coroutines.delay(1_000)
+ onGranted()
+ }
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Text(
- "Gearslip needs the Phone and Contacts permissions to dial from here. Grant them " +
- "from the app's settings.",
+ "Gearslip needs the Phone and Contacts permissions to dial from here. Allow them on " +
+ "the phone when you're parked.",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
GsButton(tone = GsTone.Tonal, onClick = {
- context.startActivity(
- Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", context.packageName, null)),
- )
- }) { Text("Open app settings") }
+ app.seb3thehacker.gearslip.PermissionActivity.ask(context, CALL_PERMISSIONS)
+ }) { Text("Ask on the phone") }
}
}
diff --git a/gearslip/src/main/res/values/themes.xml b/gearslip/src/main/res/values/themes.xml
index fa51d18..5a71aa0 100644
--- a/gearslip/src/main/res/values/themes.xml
+++ b/gearslip/src/main/res/values/themes.xml
@@ -9,4 +9,12 @@
- true
- false
+
+
+