實作自訂瀏覽動作

與使用自訂播放動作支援播放檢視畫面中的獨特功能類似,您可以使用自訂瀏覽動作支援瀏覽檢視畫面中的獨特功能。舉例來說,您可以使用自訂瀏覽動作,讓使用者下載播放清單或將項目加入佇列。

如果自訂動作數量超過原始設備製造商 (OEM) 顯示的數量,系統會向使用者顯示溢位選單。每個自訂瀏覽動作都是以下列項目定義:

  • 動作 ID:專屬字串 ID
  • 動作標籤:向使用者顯示的文字
  • 動作圖示統一資源識別碼 (URI):可著色的向量可繪項目

自訂瀏覽動作溢位

圖 1. 自訂瀏覽動作溢位。

您可以在 BrowseRoot 中定義全域自訂瀏覽動作清單。然後將這些動作的子集附加至個別 MediaItem

使用者與自訂瀏覽動作互動時,應用程式會在 onCustomAction 中收到回呼。接著處理動作,並視需要更新 MediaItem 的動作清單。這項功能適用於需要記錄狀態的動作,例如「加入我的最愛」和「下載」。如果動作不需要更新 (例如 Play Radio),則不必更新動作清單。

自訂瀏覽動作工具列

圖 2. 自訂瀏覽動作工具列。

你也可以將自訂瀏覽動作附加至瀏覽節點根目錄。這些動作會顯示在主要工具列下方的次要工具列中。

如要在應用程式中新增自訂瀏覽動作,請按照下列步驟操作:

  1. MediaBrowserServiceCompat 實作中覆寫兩個方法:

  2. 在執行階段剖析動作限制:

    onGetRoot 中,使用 rootHints Bundle 中的金鑰 BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT,取得每個 MediaItem 允許的動作數量上限。如果限制為 0,表示系統不支援這項功能。

  3. 建立自訂瀏覽動作的全域清單。針對每個動作,建立具有下列鍵的 Bundle 物件:

    • 動作 ID EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
    • 動作標籤 EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
    • 動作圖示 URI EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
  4. 將所有動作 Bundle 物件新增至清單。

  5. 將全域清單加入 BrowseRoot。在 BrowseRoot 額外資訊 Bundle 中,使用鍵 BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST 將動作清單新增為 Parcelable ArrayList

  6. MediaItem 物件中新增動作。如要將動作新增至個別 MediaItem 物件,請在 MediaDescriptionCompat 額外資訊中加入動作 ID 清單,並使用 DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST 鍵。這份清單必須是您在 BrowseRoot 中定義的動作全域清單子集。

  7. 處理動作並傳回進度或結果:

更新動作狀態

如要在 MediaBrowserServiceCompat 中覆寫這些方法,請按照下列步驟操作:

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

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

剖析動作限制

查看系統支援多少自訂瀏覽動作:

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

建立自訂瀏覽動作

每個動作都必須封裝到個別的 Bundle 中。

  • 動作 ID:

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID,
                    "<ACTION_ID>")
    
  • 動作標籤:

    bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL,
                    "<ACTION_LABEL>")
    
  • 動作圖示 URI:

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

將自訂瀏覽動作新增至 Parcelable ArrayList

將所有自訂瀏覽動作 Bundle 物件新增至 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;
}

在瀏覽根目錄中新增自訂瀏覽動作清單

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 中新增動作

MediaItem 中的瀏覽動作 ID 必須是 onGetRoot 中所列全域瀏覽動作的子集。系統會忽略不在全域清單中的動作。

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 結果

如要建構結果,請按照下列步驟操作:

  1. Bundle extras 剖析 mediaId

    @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. 如要取得非同步結果,請分離結果 result.detach

  3. 建構結果套裝組合:

    1. 向使用者顯示訊息:

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE,
                    mContext.getString(stringRes))
      
    2. 更新項目 (用於更新項目中的動作):

      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
      
    3. 開啟播放畫面:

      //Shows user the PBV without changing the playback state
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
      
    4. 更新瀏覽節點:

      //Change current browse node to mediaId
      mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
      
  4. 查看結果:

    • 錯誤:通話 result.sendError(resultBundle)
    • 進度更新:通話 result.sendProgressUpdate(resultBundle)
    • 完成:撥打電話 result.sendResult(resultBundle)

更新動作狀態

使用 result.sendProgressUpdate(resultBundle) 方法和 EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM 鍵,即可更新 MediaItem 以反映動作的新狀態。您可以藉此向使用者即時回報動作的進度和結果。

下載動作範例

這個範例說明如何使用這項功能,實作具有三種狀態的下載動作:

  • 「下載」是動作的初始狀態。使用者選取這項動作時,您可以將其換成「正在下載」,並呼叫 sendProgressUpdate 更新使用者介面 (UI)。

  • 「下載中」狀態表示下載作業正在進行。您可以使用這個狀態向使用者顯示進度列或其他指標。

  • 「已下載」狀態表示下載完成。下載完成後,您可以將「Downloading」換成「Downloaded」,並使用 EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM 鍵呼叫 sendResult,表示應重新整理項目。此外,您可以使用 EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE 鍵向使用者顯示成功訊息。

這種做法可讓您向使用者清楚說明下載程序和目前狀態。你可以使用圖示新增更多詳細資料,顯示 25%、50% 和 75% 的下載狀態。

喜愛動作範例

另一個例子是具有兩種狀態的「我的最愛」動作:

這種做法可讓使用者以清楚一致的方式管理喜愛的項目。這些範例展示了自訂瀏覽動作的彈性,以及如何使用這些動作實作各種功能,並提供即時意見回饋,進一步提升車輛媒體應用程式的使用者體驗。

如要查看這項功能的完整實作範例,請參閱 TestMediaApp 專案。