Benutzerdefinierte Suchaktionen implementieren

Ähnlich wie bei benutzerdefinierten Wiedergabeaktionen, mit denen du spezielle Funktionen in der Wiedergabeansicht unterstützen kannst, kannst du mit benutzerdefinierten Browseraktionen spezielle Funktionen in Browseransichten unterstützen. Sie können beispielsweise benutzerdefinierte Browsing-Aktionen verwenden, damit Nutzer Playlists herunterladen oder ein Element einer Warteschlange hinzufügen können.

Wenn mehr benutzerdefinierte Aktionen vorhanden sind, als vom Original Equipment Manufacturer (OEM) angezeigt werden, wird dem Nutzer ein Überlaufmenü angezeigt. Jede benutzerdefinierte Browseraktion wird mit Folgendem definiert:

  • Aktions-ID:Eindeutige String-Kennung
  • Aktionslabel:Text, der dem Nutzer angezeigt wird
  • Einheitlicher Ressourcen-URI (Uniform Resource Identifier) für das Aktionssymbol: Vektordrawable, das eingefärbt werden kann

Dreipunkt-Menü für benutzerdefinierte Browseraktionen

Abbildung 1. Überlaufmenü für benutzerdefinierte Browseraktionen.

Sie definieren eine Liste benutzerdefinierter Browseraktionen global als Teil von BrowseRoot. Hängen Sie dann eine Teilmenge dieser Aktionen an einzelne MediaItem an.

Wenn ein Nutzer mit einer benutzerdefinierten Browsing-Aktion interagiert, erhält Ihre App einen Callback in onCustomAction. Anschließend führen Sie die Aktion aus und aktualisieren bei Bedarf die Liste der Aktionen für MediaItem. Das ist nützlich für zustandsorientierte Aktionen wie „Favorisieren“ und „Herunterladen“. Bei Aktionen, die nicht aktualisiert werden müssen, z. B. „Play Radio“ (Spiele Radio), müssen Sie die Liste der Aktionen nicht aktualisieren.

Symbolleiste für benutzerdefinierte Browseraktionen

Abbildung 2: Symbolleiste für benutzerdefinierte Browseraktionen.

Sie können einem Browse-Knoten-Stamm auch benutzerdefinierte Browse-Aktionen anhängen. Diese Aktionen werden in einer sekundären Symbolleiste unter der primären Symbolleiste angezeigt.

So fügen Sie Ihrer App benutzerdefinierte Browse-Aktionen hinzu:

  1. Überschreiben Sie zwei Methoden in Ihrer MediaBrowserServiceCompat-Implementierung:

  2. Aktionslimits zur Laufzeit parsen:

    Rufen Sie in onGetRoot die maximal zulässige Anzahl von Aktionen für jede MediaItem mit dem Schlüssel BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT im rootHints Bundle ab. Ein Limit von 0 gibt an, dass das Feature vom System nicht unterstützt wird.

  3. Globale Liste benutzerdefinierter Browseraktionen erstellen Erstellen Sie für jede Aktion ein Bundle-Objekt mit den folgenden Schlüsseln:

    • Aktions-ID EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
    • Aktionslabel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
    • Aktionssymbol-URI EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
  4. Fügen Sie alle Bundle-Aktionsobjekte einer Liste hinzu.

  5. Fügen Sie die globale Liste Ihrem BrowseRoot hinzu. Fügen Sie in den BrowseRoot-ExtrasBundle die Liste der Aktionen als Parcelable ArrayList mit dem Schlüssel BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST hinzu.

  6. Fügen Sie Ihren MediaItem-Objekten Aktionen hinzu. Sie können einzelnen MediaItem-Objekten Aktionen hinzufügen, indem Sie die Liste der Aktions-IDs in die MediaDescriptionCompat-Extras mit dem Schlüssel DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST einfügen. Diese Liste muss eine Teilmenge der globalen Liste der Aktionen sein, die Sie in BrowseRoot definiert haben.

  7. Aktionen verarbeiten und Fortschritt oder Ergebnisse zurückgeben:

    • Verarbeiten Sie die Aktion in onCustomAction anhand der Aktions-ID und aller anderen erforderlichen Daten. Sie können die ID des MediaItem, das die Aktion ausgelöst hat, aus den Extras mit dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID abrufen.

    • Sie können die Liste der Aktionen für ein MediaItem aktualisieren, indem Sie den Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM in das Fortschritts- oder Ergebnis-Bundle einfügen.

Aktionsstatus aktualisieren

So überschreiben Sie diese Methoden in MediaBrowserServiceCompat:

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

und

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

Limit für Parsing-Vorgänge

So prüfen Sie, wie viele benutzerdefinierte Browseraktionen unterstützt werden:

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

Benutzerdefinierte Browse-Aktion erstellen

Jede Aktion muss in einem separaten Bundle enthalten sein.

  • Aktions-ID:

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID,
                    "<ACTION_ID>")
    
  • Aktionslabel:

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL,
                    "<ACTION_LABEL>")
    
  • URI für Aktionssymbol:

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

Benutzerdefinierte Browse-Aktionen zur Parcelable-ArrayList hinzufügen

Fügen Sie alle benutzerdefinierten Bundle-Objekte für die Browsing-Aktion in ein ArrayList ein:

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

Benutzerdefinierte Liste mit Browsing-Aktionen zum Browsing-Stamm hinzufügen

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

MediaItem Aktionen hinzufügen

Die Browse-Aktions-IDs in einem MediaItem müssen eine Teilmenge der globalen Liste der Browse-Aktionen sein, die unter onGetRoot angegeben sind. Aktionen, die nicht in der globalen Liste enthalten sind, werden ignoriert.

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

onCustomAction-Ergebnis erstellen

So erstellen Sie das Ergebnis:

  1. mediaId aus Bundle extras parsen

    @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. Bei asynchronen Ergebnissen trennen Sie das Ergebnis ab, result.detach.

  3. Erstellen Sie das Ergebnis-Bundle:

    1. Nachricht für Nutzer anzeigen:

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE,
                    mContext.getString(stringRes))
      
    2. Element aktualisieren (wird verwendet, um Aktionen in einem Element zu aktualisieren):

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
      
    3. Öffnen Sie die Wiedergabeansicht:

      //Shows user the PBV without changing the playback state
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
      
    4. Aktualisieren Sie den Browse-Knoten:

      //Change current browse node to mediaId
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
      
  4. Prüfen Sie das Ergebnis:

    • Fehler:Anruf result.sendError(resultBundle)
    • Fortschrittsupdate:Anruf result.sendProgressUpdate(resultBundle)
    • Fertigstellen:Rufe result.sendResult(resultBundle) an.

Aktionsstatus aktualisieren

Mit der Methode result.sendProgressUpdate(resultBundle) und dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM können Sie MediaItem aktualisieren, um den neuen Status der Aktion widerzuspiegeln. So können Sie dem Nutzer in Echtzeit Feedback zum Fortschritt und Ergebnis seiner Aktion geben.

Beispiel für eine Downloadaktion

In diesem Beispiel wird beschrieben, wie Sie mit diesem Feature eine Downloadaktion mit drei Status implementieren können:

  • Herunterladen ist der Ausgangszustand der Aktion. Wenn der Nutzer diese Aktion auswählt, können Sie sie durch „Herunterladen“ ersetzen und sendProgressUpdate aufrufen, um die Benutzeroberfläche zu aktualisieren.

  • Der Status Wird heruntergeladen gibt an, dass der Download läuft. Sie können diesen Status verwenden, um dem Nutzer eine Fortschrittsanzeige oder einen anderen Indikator zu präsentieren.

  • Der Status Heruntergeladen gibt an, dass der Download abgeschlossen ist. Wenn der Download abgeschlossen ist, können Sie „Downloading“ (Wird heruntergeladen) durch „Downloaded“ (Heruntergeladen) ersetzen und sendResult mit dem EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM-Schlüssel aufrufen, um anzugeben, dass das Element aktualisiert werden soll. Außerdem können Sie mit dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE eine Erfolgsmeldung für den Nutzer anzeigen.

So können Sie dem Nutzer klares Feedback zum Downloadprozess und seinem aktuellen Status geben. Sie können mit Symbolen weitere Details hinzufügen, um den Downloadstatus von 25%, 50 % und 75% anzuzeigen.

Beispiel für eine Lieblingsaktion

Ein weiteres Beispiel ist eine Lieblingsaktion mit zwei Status:

  • Favorisieren wird für Elemente angezeigt, die nicht in der Favoritenliste des Nutzers enthalten sind. Wenn der Nutzer diese Aktion auswählt, tauschen Sie sie mit Favorisiert und rufen Sie sendResult mit dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM auf, um die Benutzeroberfläche zu aktualisieren.

  • Für Elemente in der Favoritenliste des Nutzers wird Favorisiert angezeigt. Wenn der Nutzer diese Aktion auswählt, tauschen Sie sie mit Favorisieren und rufen Sie sendResult mit dem EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM-Schlüssel auf, um die Benutzeroberfläche zu aktualisieren.

Dieser Ansatz bietet Nutzern eine klare und einheitliche Möglichkeit, ihre Lieblingsartikel zu verwalten. Diese Beispiele veranschaulichen die Flexibilität benutzerdefinierter Browsing-Vorgänge und wie Sie damit verschiedene Funktionen mit Echtzeit-Feedback für eine verbesserte Nutzerfreundlichkeit in der Media-App des Autos implementieren können.

Eine umfassende Beispielimplementierung dieser Funktion finden Sie im Projekt TestMediaApp.