Assim como você usa ações de reprodução personalizadas para oferecer suporte a recursos exclusivos na visualização de reprodução, é possível usar ações de navegação personalizadas para oferecer suporte a recursos exclusivos nas visualizações de navegação. Por exemplo, você pode usar ações de navegação personalizadas para que os usuários possam baixar playlists ou adicionar um item a uma fila.
Quando há mais ações personalizadas do que as exibidas pelo fabricante de equipamento original (OEM), um menu flutuante é mostrado ao usuário. Cada ação de navegação personalizada é definida com um:
- ID da ação:identificador de string exclusivo
- Rótulo da ação:texto exibido para o usuário
- Identificador uniforme de recurso (URI) do ícone de ação: drawable vetorial que pode ser colorido.

Figura 1. Menu flutuante de ações de navegação personalizadas.
Você define uma lista de ações de navegação personalizadas globalmente como parte da sua
BrowseRoot. Em seguida, anexe um subconjunto dessas ações a cada
MediaItem.
Quando um usuário interage com uma ação de navegação personalizada, seu app recebe um callback
em onCustomAction. Em seguida, você processa a ação e atualiza a lista de
ações para o MediaItem, se necessário. Isso é útil para ações com estado,
como "Adicionar aos favoritos" e "Fazer o download". No caso de ações que não precisam ser atualizadas, como
Tocar rádio, não é necessário atualizar a lista.

Figura 2. Barra de ferramentas de ações de navegação personalizadas.
Você também pode anexar ações de navegação personalizadas a uma raiz de nó de navegação. Essas ações são mostradas em uma barra de ferramentas secundária abaixo da barra de ferramentas principal.
Para adicionar ações de navegação personalizadas ao seu app:
Substitua dois métodos na implementação de
MediaBrowserServiceCompat:Analise os limites de ação durante a execução:
Em
onGetRoot, confira o número máximo de ações permitidas para cadaMediaItemusando a chaveBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMITnorootHintsBundle. Um limite de 0 indica que o sistema não oferece suporte ao recurso.Crie a lista global de ações de navegação personalizadas. Para cada ação, crie um objeto
Bundlecom estas chaves:- ID da ação
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID - Rótulo da ação
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL - URI do ícone de ação
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
- ID da ação
Adicione todos os objetos de ação
Bundlea uma lista.Adicione a lista global ao seu
BrowseRoot. NosBundleextras daBrowseRoot, adicione a lista de ações como umParcelableArrayListusando a chaveBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST.Adicione ações aos objetos
MediaItem. Você pode adicionar ações a objetosMediaItemindividuais incluindo a lista de IDs de ação nos extrasMediaDescriptionCompatusando a chaveDESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST. Essa lista precisa ser um subconjunto da lista global de ações definida naBrowseRoot.Processe as ações e retorne o progresso ou os resultados:
Em
onCustomAction, processe a ação com base no ID dela e em outros dados necessários. Você pode conferir o ID doMediaItemque acionou a ação nos extras usando a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID.Para atualizar a lista de ações para um
MediaItem, inclua a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMno pacote de progresso ou de resultados.
Atualizar o estado da ação
Para substituir esses métodos em MediaBrowserServiceCompat:
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
e
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
Analisar limite de ações
Confira quantas ações de navegação personalizadas têm suporte:
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) {
rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0)
}
Criar uma ação de navegação personalizada
Cada ação precisa ser empacotada em um Bundle separado.
ID da ação:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")Rótulo da ação:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")URI do ícone de ação:
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
Adicionar ações de navegação personalizadas a Parcelable ArrayList
Adicione todos os objetos Bundle de ação de navegação personalizada a uma 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;
}
Adicionar a lista de ações de navegação personalizadas à raiz de navegação
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;
}
Adicionar ações a um MediaItem
Os IDs das ações de navegação em um MediaItem precisam ser um subconjunto da lista global de
ações de navegação fornecida em onGetRoot. As ações que não estiverem na lista global serão ignoradas.
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);
Resultado do build onCustomAction
Para criar o resultado:
Analisar
mediaIddeBundle 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 resultados assíncronos, remova o resultado,
result.detach.Crie o pacote de resultados:
Exiba uma mensagem para o usuário:
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))Atualize o item (use para atualizar as ações em um item):
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);Abra a visualização de reprodução:
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);Atualize o nó de navegação:
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
Confira o resultado:
- Erro:chamada
result.sendError(resultBundle) - Atualização de progresso:ligue para
result.sendProgressUpdate(resultBundle) - Concluir:ligue para
result.sendResult(resultBundle)
- Erro:chamada
Atualizar o estado da ação
Ao usar o método result.sendProgressUpdate(resultBundle) com a chave
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, você pode atualizar o MediaItem para refletir o novo estado da ação. Isso permite fornecer
feedback em tempo real ao usuário sobre o progresso e o resultado da ação.
Exemplo de ação de download
Este exemplo descreve como usar esse recurso para implementar uma ação de download com três estados:
Fazer o download é o estado inicial da ação. Quando o usuário selecionar essa ação, troque por "Fazendo o download" e chame
sendProgressUpdatepara atualizar a interface do usuário (UI).O estado Fazendo o download indica que o download está em andamento. É possível usar esse estado para mostrar uma barra de progresso ou outro indicador ao usuário.
O estado Salvo indica que o download foi concluído. Quando o download for concluído, troque "Fazendo o download" por "Salvo" e chame
sendResultcom a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMpara indicar que o item precisa ser atualizado. Além disso, você pode usar a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGEpara mostrar uma mensagem de êxito para o usuário.
Essa abordagem permite fornecer um feedback claro ao usuário sobre o processo de download e o estado atual dele. Você pode adicionar ainda mais detalhes com ícones para mostrar os estados de download de 25%, 50% e 75%.
Exemplo de ação de adicionar aos favoritos
Outro exemplo é uma ação de adicionar aos favoritos com dois estados:
Adicionar aos favoritos é exibido para itens que não estão na lista de favoritos do usuário. Quando o usuário selecionar essa ação, troque por Adicionado aos favoritos e chame
sendResultcom a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMpara atualizar a interface.Adicionado aos favoritos é exibido para itens na lista de favoritos do usuário. Quando o usuário selecionar essa ação, troque por Adicionar aos favoritos e chame
sendResultcom a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMpara atualizar a interface.
Essa abordagem oferece uma maneira clara e consistente para os usuários gerenciarem os itens favoritos. Esses exemplos mostram a flexibilidade das ações de navegação personalizadas e como você pode usá-las para implementar uma variedade de funcionalidades com feedback em tempo real para melhorar a experiência do usuário no app de mídia do carro.
Confira um exemplo completo de implementação desse recurso no projeto
TestMediaApp.