De manera similar a cómo usas las acciones de reproducción personalizadas para admitir capacidades únicas en la vista de reproducción, puedes usar acciones de exploración personalizadas para admitir capacidades únicas en las vistas de exploración. Por ejemplo, puedes usar acciones de exploración personalizadas para que los usuarios puedan descargar playlists o agregar un elemento a una fila.
Cuando hay más acciones personalizadas de las que muestra el fabricante de equipo original (OEM), se le muestra un menú ampliado al usuario. Cada acción de exploración personalizada se define con lo siguiente:
- ID de acción: Identificador de cadena único
- Etiqueta de acción: Texto que se muestra al usuario
- Identificador de recursos uniforme (URI) del ícono de acción: Elemento de diseño vectorial que puede ajustarse
Figura 1: Menú ampliado de acciones de exploración personalizadas.
Define una lista de acciones de exploración personalizadas a nivel global como parte de tu BrowseRoot
. Luego, adjunta un subconjunto de estas acciones a los elementos MediaItem
individuales.
Cuando un usuario interactúa con una acción de exploración personalizada, tu app recibe una devolución de llamada en onCustomAction
. Luego, puedes controlar la acción y actualizar la lista de acciones para el elemento MediaItem
si es necesario. Esto es útil para acciones con estado, como Favoritos y Descargar. En el caso de las acciones que no necesitan actualización, como Play Radio, no es necesario que actualices la lista de acciones.
Figura 2: Es la barra de herramientas de las acciones de exploración personalizadas.
También puedes adjuntar acciones de exploración personalizadas a la raíz de un nodo de exploración. Estas acciones se muestran en una barra de herramientas secundaria, debajo de la barra de herramientas principal.
Sigue estos pasos para agregar acciones de exploración personalizadas a tu app:
Anula dos métodos en tu implementación de
MediaBrowserServiceCompat
:Analiza los límites de acciones en el tiempo de ejecución:
En
onGetRoot
, obtén la cantidad máxima de acciones permitidas para cada elementoMediaItem
usando la claveBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
en el objetoBundle
derootHints
. Un límite de 0 indica que el sistema no admite la función.Crea la lista global de acciones de exploración personalizadas. Para cada acción, crea un objeto
Bundle
con estas claves:- ID de acción
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
- Etiqueta de acción
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
- URI del ícono de acción
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
- ID de acción
Agrega todos los objetos
Bundle
de acción a una lista.Agrega la lista global a tu
BrowseRoot
. En el objetoBundle
adicional deBrowseRoot
, agrega la lista de acciones como un objetoArrayList
deParcelable
con la claveBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
.Agrega acciones a tus objetos
MediaItem
. Puedes agregar acciones a objetosMediaItem
individuales si incluyes la lista de IDs de acción en los elementosMediaDescriptionCompat
adicionales con la claveDESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
. Esta lista debe ser un subconjunto de la lista global de acciones que definiste en el objetoBrowseRoot
.Controla las acciones y devuelve el progreso o los resultados:
En
onCustomAction
, controla la acción según el ID de acción y cualquier otro dato que necesites. Puedes usar la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
para obtener el ID del objetoMediaItem
que activó la acción desde el elemento adicional.Puedes actualizar la lista de acciones de un objeto
MediaItem
si incluyes la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
en el paquete de progreso o de resultados.
Actualiza el estado de la acción
Para anular estos métodos en MediaBrowserServiceCompat
, haz lo siguiente:
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
y
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
Analiza el límite de acciones
Comprueba cuántas acciones de exploración personalizadas se admiten:
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) {
rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0)
}
Compila una acción de exploración personalizada
Cada acción debe empaquetarse en un objeto Bundle
separado.
ID de acción:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")
Etiqueta de acción:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")
URI del ícono de acción:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
Agrega acciones de exploración personalizadas a ArrayList de Parcelable
Agrega todos los objetos Bundle
de acciones de exploración personalizadas a un elemento ArrayList
:
private ArrayList<Bundle> createCustomActionsList(
CustomBrowseAction browseActions) {
ArrayList<Bundle> browseActionsBundle = new ArrayList<>();
for (CustomBrowseAction browseAction : browseActions) {
Bundle action = new Bundle();
action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID,
browseAction.mId);
action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL,
getString(browseAction.mLabelResId));
action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
browseAction.mIcon);
browseActionsBundle.add(action);
}
return browseActionsBundle;
}
Agrega una lista de acciones de exploración personalizadas a la raíz de la exploración
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid,
Bundle rootHints) {
Bundle browserRootExtras = new Bundle();
browserRootExtras.putParcelableArrayList(
BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST,
createCustomActionsList()));
mRoot = new BrowserRoot(ROOT_ID, browserRootExtras);
return mRoot;
}
Agrega acciones a un objeto MediaItem
Los IDs de acciones de exploración de un objeto MediaItem
deben ser un subconjunto de la lista global de acciones de exploración que se proporciona en onGetRoot
. Se ignoran las acciones que no estén en la lista global.
MediaDescriptionCompat buildDescription (long id, String title, String subtitle,
String description, Uri iconUri, Uri mediaUri,
ArrayList<String> browseActionIds) {
MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder();
bob.setMediaId(id);
bob.setTitle(title);
bob.setSubtitle(subtitle);
bob.setDescription(description);
bob.setIconUri(iconUri);
bob.setMediaUri(mediaUri);
Bundle extras = new Bundle();
extras.putStringArrayList(
DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST,
browseActionIds);
bob.setExtras(extras);
return bob.build();
}
MediaItem mediaItem = new MediaItem(buildDescription(...), flags);
Compila el resultado de onCustomAction
Para compilar el resultado, haz lo siguiente:
Analiza
mediaId
deBundle extras
@Override public void onCustomAction( @NonNull String action, Bundle extras, @NonNull Result<Bundle> result){ String mediaId = extras.getString(MediaConstans.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID); }
Para los resultados asíncronos, desconecta el resultado,
result.detach
.Compila el paquete de resultados:
Muestra un mensaje al usuario:
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
Actualiza el elemento (usar para actualizar acciones en un elemento):
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
Abre la vista de reproducción:
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
Actualiza el nodo de exploración:
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
Verifica el resultado:
- Error: Call
result.sendError(resultBundle)
- Actualización del progreso: Llama a
result.sendProgressUpdate(resultBundle)
- Finalizar: Llamar a
result.sendResult(resultBundle)
- Error: Call
Actualiza el estado de la acción
Si usas el método result.sendProgressUpdate(resultBundle)
con la clave EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
, puedes actualizar el objeto MediaItem
para que refleje el nuevo estado de la acción. De esta manera, puedes proporcionarle comentarios en tiempo real al usuario sobre el progreso y el resultado de su acción.
Ejemplo de acción de descarga
En este ejemplo, se describe cómo puedes usar esta función para implementar una acción de descarga con tres estados:
Descargar es el estado inicial de la acción. Cuando el usuario selecciona esta acción, puedes cambiarla por Descargando y llamar a
sendProgressUpdate
para actualizar la interfaz de usuario (IU).El estado Descargando indica que la descarga está en curso. Puedes usar este estado para mostrarle al usuario una barra de progreso o algún otro indicador.
El estado Descargado indica que se completó la descarga. Cuando finaliza la descarga, puedes cambiar Descargando por Instalado y llamar a
sendResult
con la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para indicar que el elemento debe actualizarse. Además, puedes usar la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
para mostrarle un mensaje de confirmación al usuario.
Este enfoque te permite proporcionarle comentarios claros al usuario sobre el proceso de descarga y su estado actual. Puedes agregar aún más detalles con íconos que muestren los estados de descarga del 25%, 50% y 75%.
Ejemplo de acción de favoritos
En este otro ejemplo, se muestra una acción de favoritos con dos estados:
Se muestra Favoritos para los elementos que no están en la lista de favoritos del usuario. Cuando el usuario selecciona esta acción, cámbiala por Se agregó a Favoritos y llama a
sendResult
con la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para actualizar la IU.Se muestra Se agregó a Favoritos para los elementos de la lista de favoritos del usuario. Cuando el usuario selecciona esta acción, cámbiala por Favoritos y llama a
sendResult
con la claveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para actualizar la IU.
Este enfoque proporciona una forma clara y coherente para que los usuarios administren sus elementos favoritos. Estos ejemplos muestran la flexibilidad de las acciones de exploración personalizadas y la manera en que puedes usarlas para implementar una variedad de funcionalidades con comentarios en tiempo real para mejorar la experiencia del usuario en la app de música del automóvil.
Puedes ver una implementación de ejemplo completa de esta función en el proyecto TestMediaApp
.