feat(eq): android auto custom equalizer and robust device detection
Build & Deploy PluriWave / Análisis de código (push) Successful in 26s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m16s

- MainActivity: onListen re-emits the current active device and registers
  the audio device callback idempotently, so recreated activities resync
  instead of freezing the active-device id on a disconnected device.
- servicio_dispositivo_audio: resubscribir() re-opens the event channel;
  estado_ecualizador exposes refrescarDispositivoActual() with an
  in-flight guard, invoked on app resume and when opening advanced EQ
  options, clearing stale green-dot device selections.
- navegacion_auto/servicio_audio: new 'Personalizado' browse tree in
  Android Auto (5 band folders, 13 gain steps each) applied live via
  setBanda; preset and gain taps persist at device level when
  multi-device EQ is active and respect station/matrix overrides,
  with apply-before-persist ordering and children-changed notifications.
- l10n: regenerate stale generated localizations; add rxdart as direct
  dependency for the subscribeToChildren override.
This commit is contained in:
Javier Bautista Fernández
2026-07-22 10:26:02 +02:00
parent 3473034b58
commit 163ff69f7a
29 changed files with 1883 additions and 42 deletions
+25
View File
@@ -433,11 +433,20 @@ class FakeServicioDispositivoAudioThrows extends ServicioDispositivoAudio {
@override
Stream<DispositivoAudio> get onDispositivoCambiado => _controller.stream;
/// Number of times [resubscribir] was called.
int resubscribirLlamadas = 0;
@override
Future<DispositivoAudio> obtenerDispositivoActual() async {
throw Exception('Platform channel error: device unavailable');
}
@override
Future<void> resubscribir() async {
resubscribirLlamadas++;
throw Exception('Platform channel error: resubscribe unavailable');
}
@override
Future<bool> solicitarPermisoBluetooth() async => true;
@@ -462,6 +471,9 @@ class FakeServicioDispositivoAudio extends ServicioDispositivoAudio {
/// Number of times [solicitarPermisoBluetooth] was called.
int solicitarPermisoBluetoothCalls = 0;
/// Number of times [resubscribir] was called.
int resubscribirLlamadas = 0;
final _controller = StreamController<DispositivoAudio>.broadcast();
DispositivoAudio? _dispositivoActual;
@@ -481,6 +493,11 @@ class FakeServicioDispositivoAudio extends ServicioDispositivoAudio {
);
}
@override
Future<void> resubscribir() async {
resubscribirLlamadas++;
}
@override
Future<bool> solicitarPermisoBluetooth() async {
solicitarPermisoBluetoothCalls++;
@@ -493,6 +510,14 @@ class FakeServicioDispositivoAudio extends ServicioDispositivoAudio {
_controller.add(dispositivo);
}
/// Helper for tests: change the cached device WITHOUT emitting a stream
/// event — simulates the stale-subscription bug (activity recreation),
/// where the native device changed but the event never reached Dart and
/// only a fresh query ([obtenerDispositivoActual]) sees the new value.
void establecerDispositivoSinEvento(DispositivoAudio dispositivo) {
_dispositivoActual = dispositivo;
}
@override
Future<void> dispose() async {
await _controller.close();