7054a4c871086cfbdc107e3c213cf46bebcf5fc3
Three reported issues, two fixed and one instrumented. 1. Posponer left the alarm snoozed ~1444 minutes (24h04m). Traced end to end in Kotlin. onAlarmFired runs from the receiver BEFORE the ringing notification exists, and persists snoozeOriginMillis = null plus a triggerAtMillis already advanced to TOMORROW by computeNextTriggerMillis. snooze() then anchored on `spec.snoozeOriginMillis ?: spec.triggerAtMillis` and picked up tomorrow. The existing clamp could not catch it: it only rescues anchors in the PAST, so an anchor +24h out sails through. The countdown text is honest -- ceilMinutes(snoozeUntil - now) over Dart's own template -- the corrupt value is snoozeUntil. With N=5 and a tap at T+1min the arithmetic lands on 1444 exactly. This is the defecta9da855fixed on the Dart side with EstadoAlarmas._ocurrenciaSonando, after9c7cf4ehad fixed only one of two adjacent callers. The native lane never got that guard. Now it has anchorOccurrenceMillis, with a per-surface forward allowance: none for snooze() (the ringing notification closes an occurrence that has arrived) and a full PRE_NOTICE_MILLIS for postponeNext() (the pre-notice notification's occurrence legitimately has not). No Kotlin test source set exists in this project, so CI cannot verify this and no Dart test sees it (all use FakePuertoAlarmasAndroid). Verified by reading; needs an on-device pass. 2. The equalizer toggle stayed invisible on the Android Auto playback screen even on v1.2.14+136, which does contain it. On Android 13+ createCustomAction (AudioService.java:466-469) turns MediaControl.stop into a custom action too, so the car receives TWO in list order and stop was first -- a head unit exposing one custom-action slot shows that and buries the rest in an overflow menu. The equalizer now precedes stop and wins the slot; it is the better occupant, since the car has its own path to stop playback while the equalizer is reachable no other way from that screen. No platform detection needed, and the phone notification is untouched on every API level: nativeActions comes out [prev?, play/pause, stop, next?] below 13 and [prev?, play/pause, next?] on 13+, exactly as before. Both are now asserted. The list also moves to a public construirControlesTransporte. The guard test used to re-declare its own copy of the shape, so it stayed green while asserting a list lib/ no longer produced. It calls the real builder now. 3. Android Auto shows PLAY while a station is audibly playing: NOT fixed, deliberately. The car takes that icon from PlaybackStateCompat.getState() (AudioService.java:601-611), not from controls -- so none of the recent controls work can be the cause. All eight playbackState.add sites were audited and none publishes playing:false while audio runs, which leaves no traced input to fix. A proposed resync off bufferedPositionStream was rejected: it can publish a spurious idle, which AudioService.java:565-567 turns into stop() and tears down the foreground service -- the exact regressionabc6b47fixed, on the highest-frequency listener in the handler. Added instead a change-gated trace of the state actually published, with eqDisponible alongside it (that flag gates the equalizer action and is otherwise unobservable). One car session with `adb logcat -s ServicioAudio` settles both this and issue 2. Tests: 1124 -> 1127.
PluriWave
Radio mundial con ecualizador personalizable, reconocimiento de canciones y UI premium.
Features
- +53.000 emisoras de 238 países (Radio Browser API)
- Ecualizador por emisora — guarda tu preset favorito para cada radio
- Reconocimiento de canciones — "¿Qué suena?" sin salir de la app
- Timer de auto-apagado — perfecto para dormir
- Reproducción en segundo plano — sigue sonando con la pantalla apagada
- Favoritos — acceso rápido a emisoras preferidas
- Compartir — envía emisoras a tus amigos
- UI premium — Material You, visualizador de audio, animaciones fluidas
Monetización
- 14 días PRO gratis al instalar
- Free: radio + favoritos + timer + background (con ads)
- PRO €2.99/año: sin ads + ecualizador + reconocimiento ilimitado
Stack
- Frontend: Flutter (Android + iOS)
- Radio API: Radio Browser (gratis, +53K emisoras)
- Audio: just_audio + audio_service
- Ecualizador: just_audio equalizer (Android nativo)
- Reconocimiento: AudD API (1000 req/mes free)
- Ads: Google AdMob
- Compras: in_app_purchase
CI/CD
Workflow Gitea Actions en .gitea/workflows/ci.yml, runner macmini-flutter.
Jobs: flutter pub get → flutter test → build apk --release → build appbundle --release
Artifacts: APK y AAB guardados en Gitea con nombre pluriwave-apk-<sha> / pluriwave-aab-<sha>.
Notificaciones: Telegram al completar (éxito ✅ / fallo ❌).
Secrets necesarios en el repo:
| Secret | Uso |
|---|---|
TELEGRAM_BOT_TOKEN |
Notificaciones CI |
TELEGRAM_CHAT_ID |
Canal de destino |
Signing: build de release usa clave debug (válido para CI interno). Para Play Store se requiere keystore como secret adicional.
Desarrollador
FreeTimeLab — freetimelab.es
Licencia
MIT
Description
PluriWave — Radio mundial con ecualizador, reconocimiento de canciones y UI premium
49 MiB
Languages
Dart
86%
HTML
7.1%
Kotlin
5.1%
JavaScript
1.6%
Swift
0.1%