diff --git a/watch_app/android/app/src/main/kotlin/com/gametime/watch/MainActivity.kt b/watch_app/android/app/src/main/kotlin/com/gametime/watch/MainActivity.kt index b96ee28..67df750 100644 --- a/watch_app/android/app/src/main/kotlin/com/gametime/watch/MainActivity.kt +++ b/watch_app/android/app/src/main/kotlin/com/gametime/watch/MainActivity.kt @@ -35,6 +35,6 @@ class MainActivity : grantResults: IntArray, ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) - WatchBridgePlugin.handlePermissionResult(requestCode, grantResults) + WatchBridgePlugin.handlePermissionResult(requestCode, permissions, grantResults) } } diff --git a/watch_app/android/app/src/main/kotlin/com/gametime/watch/bridge/WatchBridgePlugin.kt b/watch_app/android/app/src/main/kotlin/com/gametime/watch/bridge/WatchBridgePlugin.kt index 98c91ba..68f1d36 100644 --- a/watch_app/android/app/src/main/kotlin/com/gametime/watch/bridge/WatchBridgePlugin.kt +++ b/watch_app/android/app/src/main/kotlin/com/gametime/watch/bridge/WatchBridgePlugin.kt @@ -35,6 +35,7 @@ object WatchBridgePlugin { const val STATE_PATH = "/gametime/phone/projection" const val PHONE_CAPABILITY = "gametime_phone_companion" private const val SENSOR_PERMISSION_REQUEST = 4106 + private const val SENSOR_PERMISSION_RETRY_DELAY_MS = 30000L private const val READ_HEART_RATE_PERMISSION = "android.permission.health.READ_HEART_RATE" @@ -51,7 +52,8 @@ object WatchBridgePlugin { sensorSamplePath = SENSOR_SAMPLE_PATH, onLocalSample = ::emitSensorSample, ) - private var sensorPermissionRequested = false + private var sensorPermissionRequestInFlight = false + private var lastSensorPermissionRequestEpochMs = 0L private var pendingSensorPermissionRequest = false fun register(flutterEngine: FlutterEngine, context: Context) { @@ -122,10 +124,15 @@ object WatchBridgePlugin { } } - fun handlePermissionResult(requestCode: Int, grantResults: IntArray) { + fun handlePermissionResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray, + ) { if (requestCode != SENSOR_PERMISSION_REQUEST) { return } + sensorPermissionRequestInFlight = false val granted = appContext?.let(::hasRequiredSensorPermissions) == true || grantResults.all { it == PackageManager.PERMISSION_GRANTED } if (granted) { @@ -133,7 +140,10 @@ object WatchBridgePlugin { Log.d(TAG, "sensor permissions granted") appContext?.let { heartRateCollector.onBodySensorsGranted(it) } } else { - Log.w(TAG, "sensor permissions denied") + val denied = permissions.filterIndexed { index, _ -> + grantResults.getOrNull(index) != PackageManager.PERMISSION_GRANTED + } + Log.w(TAG, "sensor permissions denied=${denied.joinToString()}") } } @@ -339,10 +349,6 @@ object WatchBridgePlugin { Log.d(TAG, "sensor permission request pending: activity unavailable") return } - if (sensorPermissionRequested) { - Log.d(TAG, "sensor permission request already attempted") - return - } val permissions = requiredSensorPermissions() .filter { activity.checkSelfPermission(it) != PackageManager.PERMISSION_GRANTED } .toTypedArray() @@ -351,7 +357,27 @@ object WatchBridgePlugin { appContext?.let { heartRateCollector.onBodySensorsGranted(it) } return } - sensorPermissionRequested = true + val now = System.currentTimeMillis() + if (sensorPermissionRequestInFlight && + now - lastSensorPermissionRequestEpochMs < SENSOR_PERMISSION_RETRY_DELAY_MS + ) { + Log.d( + TAG, + "sensor permission request in flight missing=${permissions.joinToString()}", + ) + return + } + if (!sensorPermissionRequestInFlight && + now - lastSensorPermissionRequestEpochMs < SENSOR_PERMISSION_RETRY_DELAY_MS + ) { + Log.d( + TAG, + "sensor permission request throttled missing=${permissions.joinToString()}", + ) + return + } + sensorPermissionRequestInFlight = true + lastSensorPermissionRequestEpochMs = now Log.d(TAG, "request sensor permissions=${permissions.joinToString()}") activity.requestPermissions(permissions, SENSOR_PERMISSION_REQUEST) }