Esta página explica cómo implementar la radio a nivel de hardware y software.
- Los componentes del sistema ilustran y describen la pila de tecnología de radio.
- La capa de abstracción de hardware de radiodifusión (HAL) proporciona estructuras de datos e interfaces para que los OEM implementen radiodifusión como AM/FM y radio de transmisión de audio digital (DAB) a nivel de hardware.
- La implementación del control de radio se basa en
MediaSession
yMediaBrowse
, que permiten que las aplicaciones multimedia y de asistente de voz controlen la radio. Además del contenido que se proporciona a continuación, consulte Crear aplicaciones multimedia para automóviles .
Componentes del sistema
La pila de transmisión de radio incluye los siguientes componentes.
Aplicación de referencia de radio
Para obtener detalles sobre cómo implementar el control de radio, consulte Implementación de control de radio .
Una aplicación de radio Java de ejemplo ( packages/apps/Car/Radio
) sirve como implementación de referencia. Cuando se inicia el servicio de la aplicación, solicita a Radio Manager que abra un sintonizador de radio. Luego, la aplicación puede enviar solicitudes al sintonizador de radio, como sintonizar una estación de radio o frecuencia específica o buscar la siguiente estación de radio disponible. La aplicación recibe actualizaciones del Administrador de radio y del Sintonizador de radio en Radio, como información del programa actual, listas de programas de radio, configuraciones y parámetros definidos por el proveedor. La aplicación Radio de referencia solo admite radio AM y FM. Los OEM pueden modificar o reemplazar la aplicación Radio según lo deseen.
Gerente de radio
Cuando la aplicación solicita a Radio Manager que abra un sintonizador, Radio Manager ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) solicita al servicio de transmisión de radio que abra una sesión de sintonizador y luego envuelve la sesión en un Radio Tuner ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
), que se devuelve a la aplicación. El sintonizador de radio define API (como sintonizar, avanzar y cancelar) a las que se puede llamar desde aplicaciones de radio y enviar solicitudes al servicio de transmisión de radio. Los métodos de devolución de llamada ( RadioTuner.Callback
) definidos en Radio Tuner envían actualizaciones sobre la transmisión de radio HAL, como información del programa actual, listas de programas y parámetros definidos por el proveedor, desde el servicio de transmisión de radio a las aplicaciones.
Servicio de transmisión de radio
El servicio de radiodifusión ( frameworks/base/services/core/java/com/android/server/broadcastradio
) es el servicio de cliente para Broadcast Radio HAL. El Servicio de Radiodifusión coordina varios administradores de radio con HAL de Radiodifusión. El servicio de transmisión de radio admite transmisiones de radio HAL en lenguaje de definición de interfaz HAL (HIDL) y en lenguaje de definición de interfaz de Android (AIDL) . El Servicio de Radiodifusión se vincula con AIDL HAL cuando existe algún servicio AIDL HAL; de lo contrario, el servicio se vincula al HIDL HAL. El servicio de transmisión de radio crea un módulo de radio para cada instancia HAL disponible (como AM, FM y DAB).
Cada Administrador de Radio puede solicitar al Servicio de Transmisión de Radio la creación de una sesión de sintonizador en el Módulo de Radio correspondiente, según el tipo de radio. Cada sesión de sintonizador puede llamar a métodos, como sintonizar, avanzar y cancelar (definidos en las interfaces HAL) para realizar operaciones en la instancia HAL de transmisión de radio correspondiente. Cuando una sesión de sintonizador recibe una devolución de llamada de la instancia de HAL en una actualización de HAL, como información del programa actual, lista de programas, indicadores de configuración y parámetros del proveedor, se envían devoluciones de llamada sobre la actualización a todos los sintonizadores de radio vinculados al mismo módulo de radio.
Radiodifusión HAL
Para obtener más información sobre las interfaces HIDL y AIDL de la radiodifusión y las diferencias entre las dos, consulte Interfaz HAL de radiodifusión .
Capa de abstracción de hardware de radiodifusión
Las siguientes secciones describen cómo trabajar con la capa de abstracción de hardware (HAL) para implementar la transmisión de radio.
Interfaz HAL de radiodifusión
Broadcast radio HAL proporciona estructuras de datos e interfaces a nivel de hardware para implementar transmisiones de radio, como radio AM/FM y DAB.
Interfaces HIDL 2.0 y AIDL
La transmisión de radio HAL utiliza las interfaces que se describen en las siguientes secciones.
- Oyente de anuncios
- Cerrar manija
- Interfaz de devolución de llamada
- Interfaz HAL de radio de transmisión primaria
Oyente de anuncios
IAnnouncementListener
es la interfaz de devolución de llamada para el oyente de anuncios, que puede registrarse en la transmisión de radio HAL para recibir anuncios. La interfaz tiene los siguientes métodos:
AnuncioOyente | ||
---|---|---|
Descripción: Se llama cada vez que la lista de anuncios cambia. | ||
HID 2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
AIDL | oneway void onListUpdated(in Announcement[] announcements) |
Cerrar manija
ICloseHandle
es el identificador de cierre genérico para eliminar una devolución de llamada que no necesita una interfaz activa.
ICoseHandle | ||
---|---|---|
Descripción: Cierra la manija. | ||
HID 2.0 | close() | |
AIDL | void close() |
Interfaz de devolución de llamada
ITunerCallback
es la interfaz de devolución de llamada llamada por la transmisión de radio HAL para enviar actualizaciones al servicio del cliente HAL.
Devolución de llamada de ITuner | ||
---|---|---|
Descripción: lo llama HAL cuando una operación de ajuste (sintonizar, buscar (en AIDL) o escanear (en HIDL) y el paso se realiza correctamente) falla de forma asincrónica. | ||
HID 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Descripción: Se llama cuando sintoniza, busca (en AIDL) o escanea (en HIDL), o el paso tiene éxito. | ||
HID 2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
AIDL | void onTuneFailed(in Result result, in ProgramSelector selector) | |
Descripción: Se llama cuando sintoniza, busca (en AIDL) o escanea (en HIDL), o el paso tiene éxito. | ||
HID 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Descripción: Se llama cuando se actualiza la lista de programas; el tamaño de cada fragmento debe limitarse a 500 kiB. | ||
HID 2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
AIDL | oneway onProgramListUpdated(ProgramListChunk chunk) | |
Descripción: Llamado cuando la antena está conectada o desconectada. | ||
HID 2.0 | oneway onAntennaStateChange(bool connected) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Descripción: Se llama cuando los valores de los parámetros específicos del proveedor se actualizan internamente en HAL (no se debe invocar después de llamar setParameters por parte del cliente HAL). | ||
HID 2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
AIDL | void onParametersUpdated(in VendorKeyValue[] parameters) | |
Descripción: Nuevo en AIDL. Se llama cuando el indicador de configuración se actualiza internamente en HAL (no debe invocarse después de llamar setConfigFlag por parte del cliente HAL). | ||
HID 2.0 | No aplica. | |
AIDL | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
Interfaz HAL de radio de transmisión primaria
IBroadcastRadio
es la interfaz principal para la transmisión de radio HAL. En HIDL 2.0 HAL, utilice la interfaz ITunerSession
para que el sintonizador llame a operaciones. Sin embargo, como máximo hay un sintonizador activo a la vez (siempre que cada instancia HAL de radiodifusión solo tenga un chip sintonizador). ITunerSession
se eliminó de las interfaces AIDL y sus interfaces se trasladaron a IBroadcastRadio
.
IBroadcastRadio | ||
---|---|---|
Descripción: Obtenga la descripción de un módulo y sus capacidades. | ||
HID 2.0 | getProperties() generates (Properties properties) | |
AIDL | Properties getProperties() | |
Descripción: Obtiene la configuración actual o posible de la región AM/FM. | ||
HID 2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
AIDL | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
Descripción: Obtiene la configuración actual de la región DAB. | ||
HID 2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
AIDL | DabTableEntry[] getDabRegionConfig() | |
Descripción: Obtiene una imagen del caché del módulo de radio. En AIDL, el tamaño de la imagen debe ser inferior a 1 MB debido a un límite estricto en el búfer de transacciones de la carpeta. | ||
HID 2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
AIDL | byte[] getImage(in int id) | |
Descripción: Registra el oyente del anuncio. | ||
HID 2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
AIDL | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
Descripción:
| ||
HID 2.0 | openSession(ITunerCallback callback) genera (Result result, ITunerSession session) | |
AIDL | void setTunerCallback(in ITunerCallback callback) | |
Descripción:
| ||
HID 2.0 | close() | |
AIDL | unsetTunerCallback() | |
Descripción: Sintoniza un programa específico. | ||
HID 2.0 | tune(ProgramSelector program) generates (Result result) | |
AIDL | void tune(in ProgramSelector program) | |
Descripción: Busca el siguiente programa válido al aire . Para evitar confusiones en AIDL, se cambia el nombre scan a seek . | ||
HID 2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
AIDL | void seek(in boolean directionUp, in boolean skipSubChannel) | |
Descripción: Pasos al canal adyacente, que no podrá estar ocupado por ningún programa. | ||
HID 2.0 | step(bool directionUp) generates (Result result) | |
AIDL | void step(in boolean directionUp) | |
Descripción: Cancela las operaciones pendientes de sintonización, escaneo (en HIDL) o búsqueda (en AIDL) o de pasos. | ||
HID 2.0 | cancel() | |
AIDL | void cancel() | |
Descripción: Aplica un filtro a la lista de programas y comienza a enviar actualizaciones de la lista de programas a través de la devolución de llamada onProgramListUpdated . | ||
HID 2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
AIDL | void startProgramListUpdates(in ProgramFilter filter) | |
Descripción: Deja de enviar actualizaciones de la lista de programas. | ||
HID 2.0 | stopProgramListUpdates() | |
AIDL | void stopProgramListUpdates() | |
Descripción: Obtiene la configuración actual de un indicador de configuración determinado. | ||
HID 2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
AIDL | boolean isConfigFlagSet(in ConfigFlag flag) | |
Descripción: establece el indicador de configuración dado. | ||
HID 2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
AIDL | void setConfigFlag(in ConfigFlag flag, boolean value) | |
Descripción: establece valores de parámetros específicos del proveedor. | ||
HID 2.0 | setParameters(vec<VendorKeyValue> parameters) genera , (vec<VendorKeyValue> results) | |
AIDL | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
Descripción: recupera valores de parámetros específicos del proveedor. | ||
HID 2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
AIDL | VendorKeyValue[] getParameters(in String[] keys) |
Aclaraciones de interfaz
Comportamiento asincrónico
Dado que cada operación de ajuste (por ejemplo, sintonizar, escanear (en HIDL) o buscar (en AIDL) y paso) puede consumir mucho tiempo y el subproceso no debe bloquearse durante mucho tiempo, la operación debe programar operaciones que consumen mucho tiempo. que ocurra más tarde y devolver rápidamente un estado o resultado. En detalle, cada operación debería:
- Cancele todas las operaciones de ajuste pendientes.
- Compruebe si la operación se puede procesar según las entradas del método y el estado del sintonizador.
- Programe la tarea de ajuste y luego devuelva el
Result
(en HIDL) ostatus
(en AIDL) inmediatamente. Si elResult
ostatus
esOK
, se debe llamar a la devolución de llamada del sintonizadortuneFailed
ocurrentProgramInfoChanged
cuando la tarea de ajuste haya fallado (por ejemplo, debido a un tiempo de espera) o esté completa.
De manera similar, startProgramListUpdates
también programa la lenta tarea de actualizar la lista de programas para que se realice más tarde y devuelva rápidamente un estado o resultado. El método primero cancela las solicitudes de actualización pendientes y luego programa la tarea de actualización y devuelve rápidamente el resultado.
Condición de carrera
Debido al comportamiento asincrónico de las operaciones de ajuste (por ejemplo, sintonizar, escanear (en HIDL) o buscar (en AIDL) y paso), existe una condición de carrera entre la cancelación de la operación y las operaciones de ajuste. Si se llama cancel
después de que HAL complete una operación de ajuste y antes de que se complete la devolución de llamada, la cancelación se puede ignorar y la devolución de llamada debe completarse y ser recibida por el cliente HAL.
De manera similar, si se llama stopProgramListUpdates
después de que HAL complete una actualización de la lista de programas y antes de que se complete la devolución de llamada onCurrentProgramInfoChanged
, se puede ignorar stopProgramListUpdates
y la devolución de llamada debería completarse.
Límite de tamaño de datos
Dado que existe un límite estricto en el búfer de transacciones de la carpeta, el límite de datos para algunos métodos de interfaz que pasan datos de un tamaño potencialmente grande se aclara en AIDL HAL.
-
getImage
requiere que la imagen devuelta tenga menos de 1 MB. -
onProgramListUpdate
requiere que cadachunk
tenga menos de 500 kiB. La implementación de HAL debe dividir las listas de programas más grandes en varios fragmentos y enviarlas a través de múltiples devoluciones de llamada.
Cambios en las estructuras de datos AIDL HAL
Además de los cambios en las interfaces, estos cambios se han aplicado a las estructuras de datos definidas en la transmisión de radio AIDL HAL, que aprovecha el AIDL.
- La enumeración
Constant
se elimina en AIDL y se define como const int enIBroadcastRadio
. Mientras tanto,ANTENNA_DISCONNECTED_TIMEOUT_MS
pasa a llamarseANTENNA_STATE_CHANGE_TIMEOUT_MS
. Se agrega una nueva constanteTUNER_TIMEOUT_MS
. Todas las operaciones de sintonización, búsqueda y paso deben completarse dentro de este tiempo. - Enum
RDS
yDeemphasis
se eliminan en AIDL y se definen como const int enAmFmRegionConfig
. En consecuencia, tantofmDeemphasis
comofmRds
enProgramInfo
se declaran como int, un resultado del cálculo de bits de las respectivas banderas. Mientras tanto,D50
yD75
pasan a llamarseDEEMPHASIS_D50
yDEEMPHASIS_D75
, respectivamente. - Enum
ProgramInfoFlags
se eliminan en AIDL y se definen como const int enProgramInfo
con un prefijoFLAG_
agregado. En consecuencia,infoFlags
enProgramInfo
se declara como int, un resultado del cálculo de bits de las banderas.TUNED
también pasa a llamarseFLAG_TUNABLE
, para describir mejor su definición de que se puede sintonizar la estación. - En
AmFmBandRange
, se cambia el nombrescanSpacing
aseekSpacing
, ya que el nombrescan
cambia aseek
en AIDL. - Dado que el concepto de unión se introduce en AIDL,
MetadataKey
yMetadata
definidos en HIDL HAL ya no se utilizan.Metadata
de una unión AIDL se definen en AIDL HAL. Cada valor de enumeración que anteriormente estaba enMetadataKey
ahora es un campo enMetadata
con tipo de cadena o int, según sus definiciones.
Implementación de radiocontrol.
La implementación del control de radio se basa en MediaSession
y MediaBrowse
, que permiten que las aplicaciones multimedia y de asistente de voz controlen la radio. Para obtener más información, consulte Crear aplicaciones multimedia para automóviles en desarrollador.android.com.
Se proporciona una implementación del árbol de exploración de medios en la biblioteca car-broadcastradio-support en packages/apps/Car/libs
. Esta biblioteca también contiene extensiones de ProgramSelector para convertir hacia y desde URI. Se recomienda que las implementaciones de radio utilicen esta biblioteca para crear el árbol de exploración asociado.
Conmutador de fuente de medios
Para proporcionar una transición fluida entre la radio y otras aplicaciones que se muestran en los medios, la biblioteca común de medios para automóviles contiene clases que deben integrarse en la aplicación de radio. MediaAppSelectorWidget
se puede incluir en el XML de la aplicación de radio (el icono y el menú desplegable utilizados en las aplicaciones de radio y medios de referencia):
<com.android.car.media.common.MediaAppSelectorWidget android:id="@+id/app_switch_container" android:layout_width="@dimen/app_switch_widget_width" android:layout_height="wrap_content" android:background="@drawable/app_item_background" android:gravity="center" />
Este widget inicia AppSelectionFragment
, que muestra una lista de fuentes de medios a las que se puede cambiar. Si desea una interfaz de usuario distinta a la proporcionada, puede crear un widget personalizado para iniciar AppSelectionFragment
cuando se debe mostrar el conmutador.
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
Se proporciona una implementación de muestra en la implementación de la aplicación de radio de referencia, ubicada en packages/apps/Car/Radio
.
Especificaciones de control detalladas
La interfaz MediaSession
(a través de MediaSession.Callback
) proporciona mecanismos de control para el programa de radio que se reproduce actualmente:
-
onPlay
,onStop
. (Des)silenciar la reproducción de radio. -
onPause
. Pausa en diferido (si es compatible). -
onPlayFromMediaId
. Reproduzca cualquier contenido de una carpeta de nivel superior. Por ejemplo, "Reproducir FM" o "Reproducir radio". -
onPlayFromUri
. Reproduce una frecuencia específica. Por ejemplo, "Reproducir 88.5 FM". -
onSkipToNext
,onSkipToPrevious
. Sintonice una estación anterior o siguiente. -
onSetRating
. Agregar o eliminar desde o hacia Favoritos.
MediaBrowser expone un MediaItem ajustable en tres tipos de directorios de nivel superior:
- ( Opcional ) Programas (estaciones). Este modo lo utilizan normalmente las radios con sintonizador dual para indicar todas las estaciones de radio sintonizables disponibles en la ubicación del usuario.
- Favoritos. Programas de radio agregados a la lista de Favoritos, algunos pueden no estar disponibles (fuera del alcance de recepción).
- Canales de banda. Todos los canales físicamente posibles en la región actual (87.9, 88.1, 88.3, 88.5, 88.7, 88.9, 89.1, etc.). Cada banda tiene un directorio de nivel superior independiente.
Cada elemento en cada una de estas carpetas (AM/FM/Programas) es un MediaItem con un URI que se puede usar con MediaSession para sintonizar. Cada carpeta de nivel superior (AM/FM/Programas) es un MediaItem con un mediaId que se puede usar con MediaSession para activar la reproducción y queda a discreción del OEM. Por ejemplo, "Reproducir FM", "Reproducir AM" y "Reproducir radio" son consultas de radio no específicas que utilizan un mediaId para enviar a la aplicación de radio OEM. Depende de la aplicación de radio determinar qué reproducir a partir de la solicitud genérica y el mediaId.
Sesión de medios
Dado que no existe el concepto de pausar una transmisión, las acciones Reproducir, Pausar y Detener no siempre se aplican a la radio. Con la radio, la acción Detener está asociada con silenciar la transmisión, mientras que Reproducir está asociada con eliminar el silencio.
Algunos sintonizadores de radio (o aplicaciones) brindan la capacidad de simular una pausa en la transmisión almacenando en caché el contenido y luego reproduciéndolo más tarde. En tales casos, utilice onPause
.
La reproducción desde acciones mediaId y URI tiene como objetivo sintonizar una estación obtenida de la interfaz MediaBrowser. El mediaId es una cadena arbitraria proporcionada por la aplicación de radio para imponer un valor único (por lo que una ID determinada apunta a un solo elemento) y estable (por lo que un elemento determinado tiene la misma ID durante toda la sesión) con el que identificar una estación determinada. . El URI tendrá un esquema bien definido. En resumen, una forma de ProgramSelector con URI. Si bien esto preserva el atributo de unicidad, no es necesario que sea estable, aunque puede cambiar cuando la estación pasa a una frecuencia diferente.
Por diseño, no se utiliza onPlayFromSearch
. Es responsabilidad del cliente (aplicación complementaria) seleccionar un resultado de búsqueda del árbol de MediaBrowser. Trasladar esa responsabilidad a la aplicación de radio aumentaría la complejidad, requeriría contratos formales sobre cómo deberían aparecer las consultas de cadena y daría como resultado una experiencia de usuario desigual en diferentes plataformas de hardware.
Nota: La aplicación de radio no contiene información adicional que sería útil para buscar el nombre de una estación que no esté expuesta al cliente a través de la interfaz MediaBrowser.
Saltar a la estación anterior o siguiente depende del contexto actual:
- Cuando una aplicación está sintonizada en una estación de la lista de Favoritos, la aplicación puede pasar a la siguiente estación de la lista de Favoritos.
- Escuchar una emisora de la lista de programas puede provocar que se sintonice la siguiente emisora disponible, ordenada según el número de canal.
- Escuchar un canal arbitrario puede resultar en la sintonización del siguiente canal físico, incluso cuando no hay señal de transmisión.
La aplicación de radio se encarga de estas acciones.
Manejo de errores
Las acciones TransportControls
(Reproducir, Detener y Siguiente) no proporcionan información sobre si la acción se realizó correctamente o no. La única forma de indicar un error es establecer el estado de MediaSession en STATE_ERROR
con un mensaje de error.
La aplicación de radio debe manejar esas acciones y ejecutarlas o establecer un estado de error. Si la ejecución del comando Reproducir no es inmediata, el estado de reproducción debe cambiarse a STATE_CONNECTING
(en caso de sintonización directa) o STATE_SKIPPING_TO_PREVIOUS
o NEXT
mientras se ejecuta el comando.
El cliente debe observar PlaybackState
y verificar que la sesión cambió el programa actual a lo que se solicitó o entró en el estado de error. STATE_CONNECTING
no debe exceder los 30 segundos. Sin embargo, una sintonización directa a una frecuencia AM/FM determinada debería funcionar mucho más rápido.
Agregar y eliminar favoritos
MediaSession tiene soporte de clasificación, que se puede utilizar para controlar Favoritos. onSetRating
llamado con una calificación de tipo RATING_HEART
agrega o elimina la estación sintonizada actualmente en o desde la lista de Favoritos.
A diferencia de los ajustes preestablecidos heredados, este modelo supone una lista de Favoritos desordenada e ilimitada, cuando cada favorito guardado se asignaba a una ranura numérica (normalmente, del 1 al 6). Como resultado, los sistemas basados en ajustes preestablecidos serían incompatibles con la operación onSetRating
.
La limitación de la API MediaSession es que solo se puede agregar o eliminar la estación actualmente sintonizada. Por ejemplo, los elementos deben seleccionarse primero antes de poder eliminarse. Esto es sólo una limitación del cliente MediaBrowser, como una aplicación complementaria. La aplicación de radio no tiene restricciones similares. Esta parte es opcional cuando una aplicación no admite Favoritos.
Navegador de medios
Para expresar qué frecuencias o nombres de canales físicos (cuando sintonizar un canal arbitrario es adecuado para una tecnología de radio determinada) son válidos para una región determinada, se enumeran todos los canales (frecuencias) válidos para cada banda. En la región de EE. UU., esto equivale a 101 canales de FM en el rango de 87,8 a 108,0 MHz (usando un espaciado de 0,2 MHz) y 117 canales de AM en el rango de 530 a 1700 kHz (usando un espaciado de 10 kHz). Dado que la radio HD utiliza el mismo espacio de canales, no se presenta por separado.
La lista de programas de radio disponibles actualmente es plana porque no permite esquemas de visualización como la agrupación por conjunto de transmisión directa de audio (DAB).
Es posible que las entradas de la lista de favoritos no se puedan ajustar. Por ejemplo, si un programa determinado está fuera de rango. La aplicación de radio puede detectar o no si la entrada se puede sintonizar de antemano. Si es así, es posible que no marque la entrada como reproducible.
Para identificar las carpetas de nivel superior se aplica el mismo mecanismo que utiliza Bluetooth. Es decir, un paquete Extras del objeto MediaDescription
contiene un campo específico del sintonizador tal como lo hace Bluetooth con EXTRA_BT_FOLDER_TYPE
. En el caso de la radiodifusión, esto lleva a definir los siguientes nuevos campos en la API pública:
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
. Uno de los siguientes valores:-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
. Programas disponibles actualmente. -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
. Favoritos. -
BCRADIO_FOLDER_TYPE_BAND = 3
. Todos los canales físicos para una banda determinada.
No es necesario definir ningún campo de metadatos personalizados específicos de la radio, ya que todos los datos relevantes encajan en el esquema
MediaBrowser.MediaItem
existente:- Nombre del programa (RDS PS, nombre del servicio DAB).
MediaDescription.getTitle
. - Frecuencia FM. URI (consulte ProgramSelector ) o
MediaDescription.getTitle
(si una entrada está en la carpetaBROADCASTRADIO_FOLDER_TYPE_BAND
). - Identificadores específicos de radio (RDS PI, DAB SId).
MediaDescription.getMediaUri
analizado en ProgramSelector.
Normalmente, no es necesario buscar la frecuencia FM para una entrada en el programa actual o en la lista de Favoritos (ya que el cliente debe operar con ID de medios). Sin embargo, si surgiera tal necesidad (por ejemplo, para fines de visualización), está presente en el URI y se puede analizar en
ProgramSelector
. Dicho esto, no se recomienda utilizar el URI para seleccionar elementos dentro de la sesión actual. Para obtener más información, consulteProgramSelector
.Para evitar problemas de rendimiento o relacionados con la carpeta, el servicio MediaBrowser debe admitir la paginación:
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- Parámetros adicionales para
subscribe()
Nota: De forma predeterminada, la paginación se implementa de forma predeterminada en la variante
onLoadChildren()
sin manejo de opciones.Las entradas relacionadas de todo tipo de listas (canales sin procesar, programas encontrados y favoritos) pueden tener diferentes mediaIds (depende de la aplicación de radio; la biblioteca de soporte los tendrá diferentes). Los URI (en formato ProgramSelector) difieren entre los canales sin formato y los programas encontrados en la mayoría de los casos (excepto FM sin RDS), pero son prácticamente los mismos entre los programas encontrados y los favoritos (excepto, por ejemplo, cuando se actualizó AF).
Tener diferentes mediaIds para entradas de diferentes tipos de listas permite realizar diferentes acciones sobre ellas. Puede recorrer la lista de Favoritos o la lista de Todos los programas en
onSkipToNext
, dependiendo de la carpeta delMediaItem
seleccionado recientemente (consulte MediaSession ).Acciones de melodía especiales
La lista de programas permite a los usuarios sintonizar una estación específica, pero no les permite realizar solicitudes generales como "Sintonizar FM", lo que podría resultar en sintonizar una estación escuchada recientemente en la banda FM.
Para admitir tales acciones, algunos directorios de nivel superior tienen configurado el indicador
FLAG_PLAYABLE
(junto conFLAG_BROWSABLE
para carpetas).Acción Sintoniza como emitir Reproducir radio cualquier canal de radio startService(ACTION_PLAY_BROADCASTRADIO)
o
playFromMediaId(MediaBrowser. getRoot() )
Reproducir FM Cualquier canal FM Reproduce desde el mediaId
de la banda FM.La determinación de qué programa sintonizar depende de la aplicación. Este suele ser el canal sintonizado más recientemente de la lista proporcionada. Para obtener detalles sobre
ACTION_PLAY_BROADCASTRADIO
, consulte Intenciones de juego generales .Conexión de descubrimiento y servicio.
PackageManager
puede encontrar directamente el árbol de transmisión de radio que sirve MediaBrowserService. Para hacerlo, llame aresolveService
con la intenciónACTION_PLAY_BROADCASTRADIO
(consulte Intenciones de reproducción generales ) y el indicadorMATCH_SYSTEM_ONLY
. Para buscar todos los servicios que ofrecen radio (puede haber más de uno; por ejemplo, AM/FM y satélite separados), utilicequeryIntentServices
.El servicio resuelto también maneja la intención de enlace
android.media.browse.MediaBrowserService
. Esto se verifica con GTS.Para conectarse al MediaBrowserService seleccionado, cree una instancia
MediaBrowser
para un componente de servicio determinado yconnect
. Después de establecer la conexión, se puede obtener un identificador de MediaSession a través degetSessionToken
.La aplicación Radio puede restringir los paquetes de clientes a los que se les permite conectarse en una implementación
onGetRoot
de su servicio. La aplicación debería permitir que las aplicaciones del sistema se conecten sin incluirse en la lista blanca. Para obtener detalles sobre la inclusión en la lista blanca, consulte Aceptar el paquete y la firma de la aplicación Asistente .Si la aplicación de fuente específica (por ejemplo, una aplicación de radio) está instalada en un dispositivo sin dicho soporte de fuente, aún se anunciará como manejando la intención
ACTION_PLAY_BROADCASTRADIO
, pero su árbol MediaBrowser no contendrá etiquetas específicas de radio. Por lo tanto, un cliente que desee comprobar si una fuente determinada está disponible en un dispositivo debe:- Descubra el servicio de radio (llame a
resolveService
paraACTION_PLAY_BROADCASTRADIO
). - Cree
MediaBrowser
y luego conéctese a él. - Determine la presencia de
MediaItem
conEXTRA_BCRADIO_FOLDER_TYPE
extra.
Nota: En la mayoría de los casos, el cliente debe escanear todos los árboles de MediaBrowser disponibles para detectar todas las fuentes disponibles para un dispositivo determinado.
Nombres de bandas
La lista de bandas está representada por un conjunto de directorios de nivel superior con una etiqueta de tipo de carpeta establecida en
BCRADIO_FOLDER_TYPE_BAND
. Los títulos de susMediaItem
son cadenas localizadas que representan nombres de bandas. En la mayoría de los casos será lo mismo que la traducción al inglés, pero el cliente no puede depender de esa suposición.Para proporcionar un mecanismo estable para buscar ciertas bandas, se agrega una etiqueta adicional para las carpetas de bandas,
EXTRA_BCRADIO_BAND_NAME_EN
. Este es un nombre no localizado de la banda y solo puede tomar uno de estos valores predefinidos:-
AM
-
FM
-
DAB
Si la banda no está en esta lista, no se debe configurar la etiqueta con el nombre de la banda. Sin embargo, si la banda está en la lista, debe tener una etiqueta establecida. La radio HD no enumera bandas separadas ya que utiliza el mismo medio subyacente que AM/FM.
Intenciones generales de juego
Cada aplicación dedicada a reproducir una fuente determinada (como radio o CD) debe manejar una intención de reproducción general para comenzar a reproducir algún contenido posiblemente desde un estado inactivo (por ejemplo, después del arranque). Depende de la aplicación cómo seleccionar el contenido para reproducir, pero generalmente es el programa de radio o la pista de CD reproducidos recientemente. Hay una intención separada definida para cada fuente de audio:
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA o CD-Texto -
android.car.intent.action.PLAY_DATADISC
: disco de datos óptico como CD/DVD, pero no CD-DA (puede ser un CD de modo mixto) -
android.car.intent.action.PLAY_AUX
: Sin especificar qué puerto AUX -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: Sin especificar qué dispositivo USB -
android.car.intent.action.PLAY_LOCAL
: almacenamiento de medios local (flash incorporado)
Se eligieron intenciones para usarlas en el comando de reproducción general porque resuelven dos problemas a la vez: el comando de reproducción general en sí y el descubrimiento de servicios. El beneficio adicional de tener tal intención sería la posibilidad de ejecutar una acción tan simple sin abrir la sesión de MediaBrowser.
El descubrimiento de servicios es en realidad el problema más importante que se resuelve con estos intentos. El procedimiento para el descubrimiento de servicios es fácil e inequívoco de esta manera (consulte Descubrimiento y conexión de servicios ).
Para facilitar algunas implementaciones de clientes, existe una forma alternativa de emitir dicho comando Play (que también debe implementarse mediante la aplicación de radio): emitir
playFromMediaId
con el rootId del nodo raíz (usado como mediaId). Si bien el nodo raíz no está destinado a ser reproducible, su rootId es una cadena arbitraria que se puede utilizar como mediaId. Sin embargo, los clientes no están obligados a comprender este matiz.Selector de programa
Si bien
mediaId
es suficiente para seleccionar un canal deMediaBrowserService
, queda vinculado a una sesión y no es coherente entre los proveedores. En algunos casos, el cliente puede necesitar un puntero absoluto (como una frecuencia absoluta) para mantenerlo entre sesiones y dispositivos.En la era de las transmisiones de radio digitales, una simple frecuencia no es suficiente para sintonizar una estación específica. Por lo tanto, utilice
ProgramSelector
para sintonizar un canal analógico o digital.ProgramSelector
consta de dos partes:- Identificador primario. Un identificador único y estable para una estación de radio determinada que no cambia pero que puede no ser suficiente para sintonizar esa estación. Por ejemplo, el código RDS PI, que puede traducirse al distintivo de llamada en EE. UU.
- Identificadores secundarios. Identificadores adicionales útiles para sintonizar esa estación (por ejemplo, frecuencia), que posiblemente incluyan identificadores de otras tecnologías de radio. Por ejemplo, una estación DAB puede tener un respaldo de transmisión analógica.
Para permitir que
ProgramSelector
se ajuste a la solución basadaMediaBrowser
oMediaSession
, defina un esquema de URI para serializarlo. El esquema se define de la siguiente manera:broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
En este ejemplo, la parte de Identificadores secundarios (después del signo de interrogación (
?
)) es opcional y se puede eliminar para proporcionar un identificador estable para usar comomediaId
. Por ejemplo:-
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=88500&AMFM_FREQUENCY=103300
-
broadcastradio://program/AMFM_FREQUENCY/102100
-
broadcastradio://program/DAB_SID_EXT/14895264?RDS_PI=1234
La parte de autoridad (también conocida como anfitrión) del
program
ofrece cierto margen para ampliar el plan en el futuro. Las cadenas de tipo de identificador se especifican con precisión como sus nombres en la definición HAL 2.x deIdentifierType
y el formato del valor es un número decimal o hexadecimal (con prefijo0x
).Todos los identificadores específicos del proveedor están representados por el prefijo
VENDOR_
. Por ejemplo,VENDOR_0
paraVENDOR_START
yVENDOR_1
paraVENDOR_START
más 1. Dichos URI son específicos del hardware de radio en el que se generaron y no se pueden transferir entre dispositivos fabricados por diferentes OEM.Estos URI deben asignarse a cada MediaItem en las carpetas de radio de nivel superior. Además, MediaSession debe admitir tanto
playFromMediaId
comoplayFromUri
. Sin embargo, el URI está destinado principalmente a la extracción de metadatos de radio (como la frecuencia de FM) y al almacenamiento persistente. No hay garantía de que el URI esté disponible para todos los elementos multimedia (por ejemplo, cuando el marco aún no admite el tipo de ID principal). Por otro lado, Media ID siempre funciona. No se recomienda que los clientes utilicen URI para seleccionar elementos de la sesión actual de MediaBrowser. En su lugar, utiliceplayFromMediaId
. Dicho esto, no es opcional para la aplicación de servicio y los URI faltantes se reservan para casos bien justificados.El diseño inicial utilizó dos puntos en lugar de la secuencia
://
después de la parte del esquema. Sin embargo, el primero no es compatible conandroid.net.Uri
para referencias de URI jerárquicas absolutas.Otros tipos de fuentes
Otras fuentes de audio se pueden manejar de manera similar. Por ejemplo, la entrada auxiliar y el reproductor de CD de audio.
Una sola aplicación puede servir a varios tipos de fuentes. En tales casos, se recomienda crear un MediaBrowserService independiente para cada tipo de fuente. Incluso en una configuración con múltiples fuentes/MediaBrowserServices servidos, se recomienda encarecidamente tener una única MediaSession dentro de una sola aplicación.
CD de audio
Similar al CD de audio en el sentido de que la aplicación que sirve dichos discos expondría MediaBrowser con una única entrada explorable (o más, si el sistema tiene un cambiador de CD), que a su vez contendría todas las pistas de un CD determinado. Si el sistema no tiene conocimiento sobre las pistas de cada CD (por ejemplo, cuando todos los discos se insertan en un cartucho a la vez y no los lee todos), entonces MediaItem para todo el disco sería simplemente
PLAYABLE
, noBROWSABLE
yPLAYABLE
. Si no hay ningún disco en una ranura determinada, el elemento no seráPLAYABLE
niBROWSABLE
(pero cada ranura siempre debe estar presente en el árbol).Estas entradas se marcarían de forma similar a como lo están las carpetas de radiodifusión; contendrían campos adicionales adicionales definidos en la API MediaDescription:
-
EXTRA_CD_TRACK
: para cadaMediaItem
en un CD de audio, número de pista basado en 1. -
EXTRA_CD_DISK
: número de disco basado en 1.
Para sistemas habilitados para CD-Text y discos compatibles, el MediaItem de nivel superior tendría un título del disco. De manera similar, los MediaItems para pistas tendrían un título de la pista.
Entrada auxiliar
La aplicación que proporciona entrada auxiliar expone un árbol de MediaBrowser con una sola entrada (o más, cuando existen varios puertos) que representa el puerto de entrada AUX. La MediaSession respectiva toma su mediaId y cambia a esa fuente después de recibir la solicitud
playFromMediaId
.Cada entrada AUX MediaItem tendría un campo adicional
EXTRA_AUX_PORT_NAME
configurado para el nombre no localizado del puerto sin la frase "AUX". Por ejemplo, "AUX 1" se habría configurado en "1", "AUX front" en "front" y "AUX" en una cadena vacía. En configuraciones regionales distintas al inglés, la etiqueta de nombre seguirá siendo la misma cadena en inglés. Es poco probable que, en cuanto aEXTRA_BCRADIO_BAND_NAME_EN
, los valores estén definidos por el OEM y no estén restringidos a una lista predefinida.Si el hardware puede detectar dispositivos conectados al puerto AUX, el hardware debe marcar el MediaItem como
PLAYABLE
, solo si la entrada está conectada. El hardware aún debe enumerarse (pero noPLAYABLE
) si nada se conectó a este puerto. Si el hardware no tiene tal capacidad, el MediaItem siempre debe estar configurado paraPLAYABLE
.Campos adicionales
Defina los siguientes campos:
-
EXTRA_CD_TRACK = "android.media.extra.CD_TRACK"
-
EXTRA_CD_DISK = "android.media.extra.CD_DISK"
-
EXTRA_AUX_PORT_NAME = "android.media.extra.AUX_PORT_NAME"
El cliente necesita revisar los mediacciones de nivel superior para elementos que tienen el conjunto de campo adicional
EXTRA_CD_DISK
oEXTRA_AUX_PORT_NAME
adicional.Ejemplos detallados
Los siguientes ejemplos abordan la estructura del árbol MediaBrowser para los tipos de origen que forman parte de este diseño.
Broadcast Radio MediaBrowserService (maneja
ACTION_PLAY_BROADCASTRADIO
):- Estaciones (Browsable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (Playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (Playable) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (Playable) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (Playable) URI:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90.5 FM (Playable) - FM sin RDSURI:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC One (Playable) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (Playable) URI:
- Favoritos (Browsable, Playable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (Playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC Two (no jugable) URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (Playable) URI:
- AM (Browsable, Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (Playable) URI:
- FM (Browsable, Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87.7 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87.9 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87.7 FM (Playable) URI:
- DAB (Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
Audio CD MediaBrowserService (maneja
ACTION_PLAY_AUDIOCD
):- Disco 1 (Playable)
EXTRA_CD_DISK=1
- Disco 2 (navegable, jugable)
EXTRA_CD_DISK=2
- Track 1 (Playable)
EXTRA_CD_TRACK=1
- Track 2 (Playable)
EXTRA_CD_TRACK=2
- Track 1 (Playable)
- Mi CD de música (navegable, reproducible)
EXTRA_CD_DISK=3
- Todo solo (jugable)
EXTRA_CD_TRACK=1
- Reise, Reise (Playable)
EXTRA_CD_TRACK=2
- Todo solo (jugable)
- Slot vacío 4 (no jugable)
EXTRA_CD_DISK=4
Aux MediaBrowserService (maneja
ACTION_PLAY_AUX
):- Aux front (playable)
EXTRA_AUX_PORT_NAME="front"
- Aux tras (playable)
EXTRA_AUX_PORT_NAME="rear"
-