Benutzerdefinierte Suchaktionen implementieren

Ähnlich wie bei benutzerdefinierten Wiedergabeaktionen, mit denen Sie spezielle Funktionen in der Wiedergabeansicht unterstützen, können Sie mit benutzerdefinierten Browseraktionen spezielle Funktionen in Browseransichten unterstützen. So können Nutzer beispielsweise mit benutzerdefinierten Browseraktionen Playlists herunterladen oder ein Element einer Warteschlange hinzufügen.

Wenn mehr benutzerdefinierte Aktionen vorhanden sind, als vom Originalgerätehersteller (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
  • URI des Aktionssymbols: Vektordrawable, das eingefärbt werden kann

Dreipunkt-Menü für benutzerdefinierte Suchaktionen

Abbildung 1: Überlauf für benutzerdefinierte Browseraktionen.

Sie definieren eine Liste benutzerdefinierter Browsing-Aktionen 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. Sie führen dann 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“, 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-Root 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 Suchaktionen 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 Suchaktionen 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-Objekte der Aktion in eine Liste ein.

  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 mit dem Schlüssel DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST in die MediaDescriptionCompat-Extras einfügen. Diese Liste muss eine Teilmenge der globalen Liste der Aktionen sein, die Sie in der BrowseRoot definiert haben.

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

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 verpackt werden.

  • 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 Suchaktionen 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 Browseraktionen zum Browser-Root 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);

Ergebnis von „onCustomAction“ 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 Browsing-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:Rufen Sie 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“ durch „Downloaded“ ersetzen und sendResult mit dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM 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 Favoritenaktion

Ein weiteres Beispiel ist eine Lieblingsaktion mit zwei Status:

  • Bei Elementen, die nicht in der Favoritenliste des Nutzers enthalten sind, wird Favorit angezeigt. 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.

  • Bei Elementen 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 Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM auf, um die Benutzeroberfläche zu aktualisieren.

Dieser Ansatz bietet Nutzern eine klare und konsistente Möglichkeit, ihre Lieblingsartikel zu verwalten. Diese Beispiele veranschaulichen die Flexibilität benutzerdefinierter Browse-Aktionen 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.