feat(audio): audio session integration and runtime robustness
- Integrate audio_session (new servicio_audio_session.dart): incoming calls pause the radio and resume on end, headphone unplug pauses without auto-resume, permanent focus loss never auto-resumes, duck lowers volume - Add play-intent flag to ServicioAudio so interruption handling and future reconnect logic can distinguish user pause from system-driven stops - Eliminate read-modify-write race in ServicioAlarmas with an in-memory cache and single-writer queue across all mutations; recalcularTodas persists only when state actually changed - Convert ServicioAlarmasAndroid static StreamController/handler to injectable instance fields, restoring test isolation - Inject a single cached SharedPreferences from main.dart across services and state (removes 23 inline getInstance() calls) - Move configurarLocalizaciones out of MiniReproductor.build() (was running on every rebuild during playback) - Bound the alarm fire-dedup set (cap 200 entries, 24h pruning) - 12 new tests (89 total green), flutter analyze clean
This commit is contained in:
@@ -82,9 +82,11 @@ class ServicioGrabacionRadio {
|
||||
http.Client? cliente,
|
||||
Future<Directory> Function()? resolverDirectorioBase,
|
||||
DateTime Function()? reloj,
|
||||
SharedPreferences? prefs,
|
||||
}) : _clienteExterno = cliente,
|
||||
_resolverDirectorioBase = resolverDirectorioBase,
|
||||
_reloj = reloj ?? DateTime.now;
|
||||
_reloj = reloj ?? DateTime.now,
|
||||
_prefs = prefs;
|
||||
|
||||
static const _claveDirectorio = 'grabacion_radio_directorio';
|
||||
static const _claveMaxBytes = 'grabacion_radio_max_bytes_v1';
|
||||
@@ -93,6 +95,11 @@ class ServicioGrabacionRadio {
|
||||
final http.Client? _clienteExterno;
|
||||
final Future<Directory> Function()? _resolverDirectorioBase;
|
||||
final DateTime Function() _reloj;
|
||||
final SharedPreferences? _prefs;
|
||||
|
||||
/// Injected startup instance (S3-R4); getInstance() is only a fallback.
|
||||
Future<SharedPreferences> _resolverPrefs() async =>
|
||||
_prefs ?? SharedPreferences.getInstance();
|
||||
final _estadoController = StreamController<EstadoGrabacionRadio>.broadcast();
|
||||
AppLocalizations? _l10n;
|
||||
|
||||
@@ -123,7 +130,7 @@ class ServicioGrabacionRadio {
|
||||
|
||||
Future<void> inicializar() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final prefs = await _resolverPrefs();
|
||||
_directorioConfigurado = prefs.getString(_claveDirectorio);
|
||||
_maxBytes = prefs.getInt(_claveMaxBytes) ?? maxBytesPorDefecto;
|
||||
} catch (_) {
|
||||
@@ -151,7 +158,7 @@ class ServicioGrabacionRadio {
|
||||
}
|
||||
_directorioConfigurado = normalizado;
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final prefs = await _resolverPrefs();
|
||||
await prefs.setString(_claveDirectorio, normalizado);
|
||||
} catch (_) {}
|
||||
_emitir(_estado);
|
||||
@@ -160,7 +167,7 @@ class ServicioGrabacionRadio {
|
||||
Future<void> limpiarDirectorioConfigurado() async {
|
||||
_directorioConfigurado = null;
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final prefs = await _resolverPrefs();
|
||||
await prefs.remove(_claveDirectorio);
|
||||
} catch (_) {}
|
||||
_emitir(_estado);
|
||||
@@ -172,7 +179,7 @@ class ServicioGrabacionRadio {
|
||||
}
|
||||
_maxBytes = bytes;
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final prefs = await _resolverPrefs();
|
||||
await prefs.setInt(_claveMaxBytes, bytes);
|
||||
} catch (_) {}
|
||||
_emitir(_estado);
|
||||
|
||||
Reference in New Issue
Block a user