Implémenter des actions de navigation personnalisées

De la même manière que vous utilisez des actions de lecture personnalisées pour prendre en charge des fonctionnalités uniques dans la vue de lecture, vous pouvez utiliser des actions de navigation personnalisées pour prendre en charge des fonctionnalités uniques dans les vues de navigation. Par exemple, vous pouvez utiliser des actions de navigation personnalisées pour permettre aux utilisateurs de télécharger des playlists ou d'ajouter un élément à une file d'attente.

Lorsqu'il existe plus d'actions personnalisées que celles affichées par le fabricant d'équipement d'origine (OEM), un menu à développer est présenté à l'utilisateur. Chaque action de navigation personnalisée est définie avec :

  • ID d'action : identifiant de chaîne unique
  • Libellé d'action : texte présenté à l'utilisateur
  • URI (Uniform Resource Identifier) de l'icône d'action : drawable vectoriel pouvant être teinté

Menu à développer d'actions de navigation personnalisées

Figure 1 : Menu à développer d'actions de navigation personnalisées.

Vous définissez une liste d'actions de navigation personnalisées de manière globale dans votre BrowseRoot. Associez ensuite un sous-ensemble de ces actions à des MediaItem individuels.

Lorsqu'un utilisateur interagit avec une action de navigation personnalisée, votre application reçoit un rappel dans onCustomAction. Vous gérez ensuite l'action et mettez à jour la liste des actions pour MediaItem, si nécessaire. Cela est utile pour les actions avec état telles que "Ajouter aux favoris" et "Télécharger". Pour les actions qui n'ont pas besoin d'être mises à jour, comme "Play Radio" (Écouter la radio), vous n'avez pas besoin de mettre à jour la liste des actions.

Barre d'outils d'action de navigation personnalisée

Figure 2. Barre d'outils d'action de navigation personnalisée.

Vous pouvez également associer des actions de navigation personnalisées à la racine d'un nœud de navigation. Ces actions s'affichent dans une barre d'outils secondaire située sous la barre d'outils principale.

Pour ajouter des actions de navigation personnalisées à votre application :

  1. Remplacez deux méthodes dans votre implémentation MediaBrowserServiceCompat :

  2. Analysez les limites de l'action au moment de l'exécution :

    Dans onGetRoot, obtenez le nombre maximal d'actions autorisées pour chaque MediaItem à l'aide de la clé BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT dans le Bundle rootHints. Une limite de 0 indique que la fonctionnalité n'est pas compatible avec le système.

  3. Créez la liste globale des actions de navigation personnalisées. Pour chaque action, créez un objet Bundle avec les clés suivantes :

    • ID de l'action : EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
    • Libellé d'action EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
    • URI de l'icône d'action EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
  4. Ajoutez tous les objets Bundle d'action à une liste.

  5. Ajoutez la liste globale à votre BrowseRoot. Dans le Bundle d'extras BrowseRoot, ajoutez la liste des actions en tant qu'ArrayList Parcelable à l'aide de la clé BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST.

  6. Ajoutez des actions à vos objets MediaItem. Vous pouvez ajouter des actions à des objets MediaItem individuels en incluant la liste des ID d'action dans les extras MediaDescriptionCompat à l'aide de la clé DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST. Cette liste doit être un sous-ensemble de la liste globale des actions que vous avez définies dans le BrowseRoot.

  7. Gérez les actions et renvoyez la progression ou les résultats :

Mettre à jour l'état de l'action

Pour remplacer ces méthodes dans MediaBrowserServiceCompat :

public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)

et

public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)

Limiter les actions d'analyse

Vérifiez le nombre d'actions de navigation personnalisées acceptées :

public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) {
    rootHints.getInt(
            MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0)
}

Créer une action de navigation personnalisée

Chaque action doit être empaquetée dans un Bundle distinct.

  • ID de l'action :

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID,
                    "<ACTION_ID>")
    
  • Libellé d'action :

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL,
                    "<ACTION_LABEL>")
    
  • URI de l'icône d'action :

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
                    "<ACTION_ICON_URI>")
    

Ajouter des actions de navigation personnalisées à un ArrayList Parcelable

Ajoutez tous les objets Bundle d'action de navigation personnalisée dans une 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;
}

Ajouter une liste d'actions de navigation personnalisées à la racine de navigation

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;
}

Ajouter des actions à un MediaItem

Les ID d'action de navigation dans un MediaItem doivent être un sous-ensemble de la liste globale des actions de navigation fournies sur onGetRoot. Les actions qui ne figurent pas dans la liste globale sont ignorées.

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);

Résultat du build onCustomAction

Pour créer le résultat :

  1. Analyser mediaId à partir de Bundle 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);
                }
    
  2. Pour les résultats asynchrones, dissociez le résultat, result.detach.

  3. Compilez le bundle de résultats :

    1. Affichez un message à l'utilisateur :

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE,
                    mContext.getString(stringRes))
      
    2. Mettez à jour l'élément (permet de mettre à jour les actions d'un élément) :

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
      
    3. Ouvrez la vue de lecture :

      //Shows user the PBV without changing the playback state
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
      
    4. Mettez à jour le nœud de navigation :

      //Change current browse node to mediaId
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
      
  4. Vérifiez le résultat :

    • Erreur : appel result.sendError(resultBundle)
    • Mise à jour de l'état d'avancement : appelez result.sendProgressUpdate(resultBundle)
    • Terminer : appel result.sendResult(resultBundle)

Mettre à jour l'état de l'action

En utilisant la méthode result.sendProgressUpdate(resultBundle) avec la clé EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, vous pouvez mettre à jour le MediaItem pour refléter le nouvel état de l'action. Cela vous permet de fournir à l'utilisateur des commentaires en temps réel sur la progression et le résultat de son action.

Exemple d'action de téléchargement

Cet exemple montre comment utiliser cette fonctionnalité pour implémenter une action de téléchargement avec trois états :

  • Download (Télécharger) : il s'agit de l'état initial de l'action. Lorsque l'utilisateur sélectionne cette action, vous pouvez la remplacer par "Downloading" (Téléchargement) et appeler sendProgressUpdate pour mettre à jour l'interface utilisateur (UI).

  • L'état Téléchargement indique que le téléchargement est en cours. Vous pouvez utiliser cet état pour présenter une barre de progression ou un autre indicateur à l'utilisateur.

  • L'état Téléchargé indique que le téléchargement est terminé. Une fois le téléchargement terminé, vous pouvez remplacer "Downloading" (Téléchargement) par "Downloaded" (Téléchargé) et appeler sendResult avec la clé EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM pour indiquer que l'élément doit être actualisé. Vous pouvez également utiliser la clé EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE pour afficher un message de réussite à l'utilisateur.

Cette approche vous permet de fournir des informations claires à l'utilisateur sur le processus de téléchargement et son état actuel. Vous pouvez ajouter encore plus de détails avec des icônes qui indiquent les états de téléchargement à 25 %, 50 % et 75 %.

Exemple d'action "Ajouter aux favoris"

Un autre exemple est une action d'ajout aux favoris avec deux états :

  • L'option Ajouter aux favoris s'affiche pour les éléments qui ne figurent pas dans la liste des favoris de l'utilisateur. Lorsque l'utilisateur sélectionne cette action, remplacez-la par Favorited et appelez sendResult avec la clé EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM pour mettre à jour l'UI.

  • L'option Ajouté aux favoris s'affiche pour les éléments figurant dans la liste des favoris de l'utilisateur. Lorsque l'utilisateur sélectionne cette action, remplacez-la par Favorite (Ajouter aux favoris) et appelez sendResult avec la clé EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM pour mettre à jour l'UI.

Cette approche permet aux utilisateurs de gérer de manière claire et cohérente leurs favoris. Ces exemples montrent la flexibilité des actions de navigation personnalisées et comment les utiliser pour implémenter diverses fonctionnalités avec des commentaires en temps réel afin d'améliorer l'expérience utilisateur dans l'application multimédia de la voiture.

Vous trouverez un exemple complet d'implémentation de cette fonctionnalité dans le projet TestMediaApp.