FreeTLab 86dd20b184 fix: el coche recuerda la ultima emisora y deja de publicar una sesion fantasma
Tres defectos preexistentes alrededor de la reanudacion en Android Auto. Ninguno
es una regresion: el consumidor (la raiz `recent`) se añadio en septiembre y es
lo que dejo el hueco a la vista.

La ultima emisora solo la escribia el telefono

La clave `ultima_emisora_v1` tenia como unico escritor a
`EstadoRadio._persistirUltimaEmisora`, y `EstadoRadio` solo existe si hay arbol
de widgets. El motor que arranca Android Auto es headless de verdad, asi que una
sesion que ocurriera solo en el coche jamas actualizaba la clave y al reconectar
se ofrecia la emisora de la ultima vez que se uso el movil.

El handler recibe ahora sus puertos de lectura y escritura, con la misma forma
que los del ecualizador y el contexto de salto, y escribe desde `_cambiarFuente`:
el cuello de botella por el que pasan todas las rutas -- telefono, toque en el
coche, voz, saltos, avance de cola y la propia reanudacion.

Se ELIMINA el escritor del telefono en vez de sumar un segundo. Dos escritores
independientes de la misma clave acaban divergiendo siempre; es exactamente lo
que ya costo varias rondas con el flag del ecualizador.

Las pistas locales quedan excluidas: un `content://` guardado como ultima
emisora seria una fila de reanudacion que no resuelve a nada.

play() sin fuente levantaba un servicio en primer plano vacio

just_audio publica `playing:true` antes de comprobar si hay fuente, asi que un
`play()` en frio no tocaba la plataforma pero si emitia ese estado sobre
`processingState: idle`. audio_service entraba en estado de reproduccion
mientras el estado nativo seguia en NONE: notificacion con boton de pausa, cero
audio, sin titulo ni caratula, y un Future que no se completaba nunca. El coche
enruta su tecla de play directamente ahi.

Ahora `play()` sin fuente abierta restaura la ultima emisora por la ruta normal,
y si no hay nada que restaurar no toca el reproductor ni publica nada.

En frio no habia metadatos que enseñar

El unico `mediaItem.add` util vivia dentro de `_cambiarFuente`, asi que en un
motor recien arrancado el lado nativo nunca recibia metadatos. Se siembra el
`mediaItem` de la emisora persistida sin cargar ni reproducir nada, con guarda
antes y despues de la lectura de disco para no pisar una emisora ya sonando.

`getMediaItem` resolvia solo contra el universo completo -- vacio en el motor del
coche -- mientras `porUuid` si caia en las destacadas. El coche podia navegar una
emisora destacada y luego no resolver su ficha. Ambos usan ahora la misma ruta.

Suite completa: 1529 pasan, 2 omitidos. flutter analyze mantiene los 5 avisos
preexistentes.
2026-09-06 00:10:58 +02:00

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 getflutter testbuild apk --releasebuild 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

S
Description
PluriWave — Radio mundial con ecualizador, reconocimiento de canciones y UI premium
Readme
49 MiB
Languages
Dart 86%
HTML 7.1%
Kotlin 5.1%
JavaScript 1.6%
Swift 0.1%