fix(watch): déverrouille les demandes de permissions capteurs montre

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 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 13:17:10 +02:00
parent ab6fc81a37
commit f71a155156
2 changed files with 35 additions and 9 deletions

View File

@ -35,6 +35,6 @@ class MainActivity :
grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
WatchBridgePlugin.handlePermissionResult(requestCode, grantResults)
WatchBridgePlugin.handlePermissionResult(requestCode, permissions, grantResults)
}
}

View File

@ -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<out String>,
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)
}