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 cadaMediaItem
usando a chaveBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
norootHints
Bundle
. 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
Bundle
com 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
Bundle
a uma lista.Adicione a lista global ao seu
BrowseRoot
. NosBundle
extras daBrowseRoot
, adicione a lista de ações como umParcelable
ArrayList
usando a chaveBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
.Adicione ações aos objetos
MediaItem
. Você pode adicionar ações a objetosMediaItem
individuais incluindo a lista de IDs de ação nos extrasMediaDescriptionCompat
usando 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 doMediaItem
que 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_ITEM
no 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
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 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
sendProgressUpdate
para 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
sendResult
com a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para indicar que o item precisa ser atualizado. Além disso, você pode usar a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
para 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
sendResult
com a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para 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
sendResult
com a chaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
para 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
.