From f71a15515623c2589a50c8f6333439b37230afe2 Mon Sep 17 00:00:00 2001 From: Blomios Date: Tue, 28 Jul 2026 13:17:10 +0200 Subject: [PATCH] =?UTF-8?q?fix(watch):=20d=C3=A9verrouille=20les=20demande?= =?UTF-8?q?s=20de=20permissions=20capteurs=20montre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit READ_HEART_RATE et ACTIVITY_RECOGNITION restaient bloquées à granted=false à cause d'un verrou permanent après une première tentative de demande ("sensor permission request already attempted" en boucle dans les logs). Remplace le verrou par sensorPermissionRequestInFlight avec throttling et reprise au callback de permission, pour permettre de redemander sans relancer l'app. QA verte sur ce périmètre ciblé. Co-Authored-By: Claude Opus 4.8 --- .../kotlin/com/gametime/watch/MainActivity.kt | 2 +- .../watch/bridge/WatchBridgePlugin.kt | 42 +++++++++++++++---- 2 files changed, 35 insertions(+), 9 deletions(-) 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) }