4042cf5ffdb4f0daad2e01dac4650fc4e0567818
Regression from the previous commit. Ranking every AudioDeviceInfo type this
build does not name individually ABOVE the built-in speaker was meant to let
a car stereo on LE Audio or an automotive bus win. It also promoted the
internal sinks a phone exposes permanently: on the Xiaomi test device
AudioManager reports TYPE_FM (14) as an output, so getActiveAudioDevice
picked it over the real speaker with nothing connected at all. Confirmed on
device:
audio_devices.onListen -> {id=other:14:4, type=14, name=2412DPC0AG}
It then reached Dart under an `other:14:4` id whose type is neither the base
speaker nor a known one, slipped past the collision guard and had a preset
row persisted for it -- reinstating the exact symptom this series set out to
kill: a permanent green active-output dot on a device that was not connected.
Replace the deny-by-omission ranking with an explicit allow list of outputs a
user actually connects. The built-in speaker sits below all of them and above
everything else, so any sink that physically exists but is never where media
plays (TYPE_FM, TYPE_BUILTIN_SPEAKER_SAFE, telephony, remote submix) can no
longer be selected. A one-time purge clears the `other:` rows the bad build
persisted; genuine ones re-register on their next connection.
Fix the USB type constant while here: TYPE_USB_HEADSET is 22, not 14, and 14
is TYPE_FM. The Kotlin USB branch hardcoded 14 and the Dart type table
mirrored the same mistake, so the two cancelled out for real USB headsets
while making a phone's own FM sink decode as USB audio. Both now use 22.
Verified with javap against android.jar (android-36) rather than trusting the
comment that introduced the error.
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%