feat(auto): browsable Android Auto media tree with play-by-id [size:exception]

Expose PluriWave to Android Auto (projected) as a media app:

- Declare car media support (automotive_app_desc.xml + manifest meta-data)
  so Android Auto discovers the existing MediaBrowserService.
- New navegacion_auto.dart: ConstructorArbolAuto builds the browse tree
  (Favoritos / Todas las emisoras / Mis emisoras, 50-item cap, stable
  emisora:<id> media ids), reproducirPorMediaId routes a car tap to the
  existing playMediaItem pipeline, FuenteEmisorasAutoLocal serves the tree
  cold-start-safe (local favorites/custom stations before Flutter UI runs).
- PluriWaveAudioHandler overrides getChildren/getMediaItem/playFromMediaId
  as thin delegations; playback pipeline untouched.
- EstadoRadio pushes live station snapshots to the browse source and
  reconciles the selected station when playback starts from the car.
- Every playable item ships title + artUri; stations without logo fall
  back to a bundled default art (android.resource://).

Tests: 52/52 green (10 new navegacion_auto, 2 new estado_radio, plus
audio safety-net suites). Handler overrides and native XML are
static-review-only (no Android build env). Size exception approved for a
single reviewable commit.
This commit is contained in:
Javier Bautista Fernández
2026-07-16 16:28:44 +02:00
parent 43781274ce
commit 35bb180612
10 changed files with 754 additions and 3 deletions
+9 -1
View File
@@ -24,16 +24,23 @@ import 'widgets/pluri_layout.dart';
import 'widgets/pluri_onboarding_dialog.dart';
import 'widgets/pluri_wave_scaffold.dart';
import 'package:pluriwave/widgets/mini_reproductor.dart';
import 'servicios/navegacion_auto.dart';
import 'servicios/servicio_alarmas_android.dart';
import 'servicios/servicio_dispositivo_audio.dart';
class PluriWaveApp extends StatelessWidget {
const PluriWaveApp({super.key, this.prefs});
const PluriWaveApp({super.key, this.prefs, this.fuenteAuto});
/// Single SharedPreferences instance resolved in main() (S3-R4) and
/// injected into every state/service.
final SharedPreferences? prefs;
/// Android Auto browse source (Design "Data Flow" — cold-bind local read
/// available before EstadoRadio builds). Optional: defaults to `null`,
/// same as every other existing caller/test that constructs
/// [PluriWaveApp] without it.
final FuenteEmisorasAuto? fuenteAuto;
@override
Widget build(BuildContext context) {
return MultiProvider(
@@ -43,6 +50,7 @@ class PluriWaveApp extends StatelessWidget {
(_) => EstadoRadio(
prefs: prefs,
dispositivoAudio: ServicioDispositivoAudioReal(),
fuenteAuto: fuenteAuto,
),
),
// Domain notifiers (S4-R1/R2/R3). Created and disposed by EstadoRadio