8fc3d99fbdfe3b68b7a5711fc3f2a4c9109e348f
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8fc3d99fbd |
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. |
||
|
|
241f81e535 |
fix: cumplir las guias de calidad de Android Auto y localizar el arbol del coche
Google Play devolvio "Approved with Issues" en el codigo 157: "clicking on stop button makes the entire app useless", citado contra las Android for Cars App Quality Guidelines. La causa no era el boton de parar. Maquina de estados del transporte _cambiarFuente publicaba mediaItem y loading ANTES de su primer await y solo comprobaba su revision despues de que _recrearPlayer retornase. Los cambios de fuente se encolan incrementando la revision al encolar, no al ejecutar, asi que tocar una emisora, tocar otra antes de que cargue y pulsar Stop dejaba que las entradas obsoletas reescribieran loading sobre el idle que stop() acababa de publicar. Estado final: loading para siempre sobre una sesion que audio_service ya habia desactivado. Ahora la guarda de revision es la primera sentencia del metodo. pause() no invalidaba una carga en vuelo, asi que la emisora arrancaba igual despues de pulsar pausa; se revalida la intencion antes de llamar a play(). Se anade un suelo de estado que cierra cualquier loading o buffering sin carga viva, exento cuando el reproductor ya entrego audio y solo esta rebufferando, para no convertir un tunel en un error. El presupuesto hasta el primer mensaje baja a menos de diez segundos y los reintentos ya no borran el mensaje visible. Tier gratuito en el coche El arbol devolvia una unica fila no reproducible para cualquier carpeta cuando no habia premium, y un revisor con instalacion limpia siempre es tier gratuito. Ademas skipToNext, skipToPrevious, playFromSearch y playFromMediaId retornaban en silencio. La raiz gratuita pasa a ofrecer una sola carpeta con emisoras reales y reproducibles, compiladas en el binario para que existan en frio, y la puerta de entitlement acota contenido en vez de bloquear acciones. Se elimina la fila "Funcion Premium". Una consulta de voz vacia arranca la ultima emisora, que fallaba tambien a los clientes de pago. Localizacion El locale del handler solo lo fijaba un widget que el motor headless nunca construye, asi que todo error del coche salia en castellano. Se resuelve desde el locale de plataforma. Se traducen las once etiquetas del arbol que estaban a fuego y se retira la convencion que lo justificaba. Un test nuevo falla si vuelve a aparecer texto visible fuera del sistema de traduccion. Suite completa: 1455 pasan, 2 omitidos. Los mecanismos se verificaron por mutacion: borrar cada uno pone la suite en rojo. flutter analyze mantiene los 5 avisos preexistentes. |