From b294b287c71e4d166e0683f9b87e033ece164f8e Mon Sep 17 00:00:00 2001 From: freetlab Date: Sat, 11 Jul 2026 22:26:12 +0200 Subject: [PATCH] fix(alarm): stop a duplicate fire event from killing the active ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The live eventosAlarma stream and the one-shot obtenerEventoInicial() both read the same native fire event on cold start, so the same alarm id can reach _mostrarAlarmaSonando twice within the same tick. The second, duplicate delivery correctly detected an alarm was already active and hit the "ignored" branch — but that branch unconditionally called ocultarNotificacionAlarma, whose native handler (dismissAlarmNotification) unconditionally stops PluriWaveAlarmService for that id. Confirmed via on-device logcat: the duplicate's stop landed ~180ms after the ring-scoped media-volume override was captured and ~2.3s before the real native-to-Flutter handoff, so flutterOwnsRing was still false and the teardown backstop restored the device's original volume immediately. The Flutter/radio player kept ringing regardless (it starts independently of the native service), now anchored to whatever volume the device happened to be at — explaining both "ignores the configured ramp" and "plays at the device's own volume." The ignored branch now only hides the notification when the duplicate carries a genuinely different alarm id than the one already ringing; a duplicate of the SAME ring's own event is now a pure no-op. --- lib/app.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/app.dart b/lib/app.dart index ca77a3d..befc569 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -334,7 +334,18 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> { debugPrint( '[PluriWave][alarmas] alarma ignorada porque ya hay una activa id=${alarma.id} activa=$_alarmaSonandoId', ); - await alarmas.android.ocultarNotificacionAlarma(alarma.id); + // A duplicate delivery of the SAME ring's own fire event (the live + // eventosAlarma stream and the one-shot obtenerEventoInicial() read + // the same native event and can both reach here) must be a no-op: + // ocultarNotificacionAlarma -> dismissAlarmNotification unconditionally + // stops PluriWaveAlarmService for that id on the native side, which + // would tear down the currently-ringing service and undo the + // ring-scoped media-volume override long before the real handoff. + // Only hide the notification when a genuinely DIFFERENT alarm fired + // while this one is active (single-ring-at-a-time by design). + if (alarma.id != _alarmaSonandoId) { + await alarmas.android.ocultarNotificacionAlarma(alarma.id); + } return; }