与使用自定义播放操作在播放视图中支持独特功能类似,您可以使用自定义浏览操作在浏览视图中支持独特功能。例如,您可以使用自定义浏览操作,以便用户可以下载播放列表或将项目添加到队列中。
如果自定义操作的数量多于原始设备制造商 (OEM) 显示的数量,系统会向用户显示溢出菜单。每项自定义浏览操作都通过以下方式定义:
- 操作 ID:唯一字符串标识符
- 操作标签:向用户显示的文字
- 操作图标统一资源标识符 (URI):可着色的矢量可绘制对象
图 1. 自定义浏览操作溢出。
您可以在 BrowseRoot
中全局定义自定义浏览操作列表。然后,将这些操作的子集附加到各个 MediaItem
。
当用户与自定义浏览操作互动时,您的应用会在 onCustomAction
中收到回调。然后,您处理该操作,并根据需要更新 MediaItem
的操作列表。这对于有状态操作(例如“收藏”和“下载”)非常有用。对于不需要更新的操作(例如 Play Radio),您无需更新操作列表。
图 2. 自定义浏览操作工具栏。
您还可以将自定义浏览操作附加到浏览节点根。这些操作显示在主工具栏下方的辅助工具栏中。
如需向应用添加自定义浏览操作,请执行以下操作:
在
MediaBrowserServiceCompat
实现中替换两种方法:在运行时解析操作限制:
在
onGetRoot
中,使用rootHints
Bundle
中的键BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
获取每个MediaItem
允许的最大操作数。限制为 0 表示系统不支持相应功能。构建自定义浏览操作的全局列表。针对每项操作,创建一个包含以下键的
Bundle
对象:- 操作 ID
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
- 操作标签
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
- 操作图标 URI
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
- 操作 ID
将所有操作
Bundle
对象添加到一个列表中。将全局列表添加到
BrowseRoot
。在BrowseRoot
extrasBundle
中,使用键BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
将操作列表添加为Parcelable
ArrayList
。向
MediaItem
对象添加操作。您可以使用键DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
将操作 ID 列表包含在MediaDescriptionCompat
extra 中,从而向各个MediaItem
对象添加操作。此列表必须是您在BrowseRoot
中定义的全局操作列表的子集。处理操作并返回进度或结果:
在
onCustomAction
中,根据操作 ID 和您需要的任何其他数据来处理操作。您可以使用键EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
从 extra 中获取触发操作的MediaItem
的 ID。您可以在进度或结果 bundle 中添加键
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
,以更新MediaItem
的操作列表。
更新操作状态
如需在 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 结果
如需构建结果,请执行以下操作:
从
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); }
对于异步结果,请分离结果,
result.detach
。构建结果 bundle:
向用户显示消息:
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
更新商品(用于更新商品中的操作):
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
打开播放视图:
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
更新浏览节点:
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
查看结果:
- 错误:调用
result.sendError(resultBundle)
- 进度更新:通话
result.sendProgressUpdate(resultBundle)
- 完成:调用
result.sendResult(resultBundle)
- 错误:调用
更新操作状态
通过将 result.sendProgressUpdate(resultBundle)
方法与 EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
键搭配使用,您可以更新 MediaItem
以反映操作的新状态。这样,您就可以向用户实时反馈其操作的进度和结果。
下载操作示例
此示例介绍了如何使用此功能来实现具有三种状态的下载操作:
下载是操作的初始状态。当用户选择此操作时,您可以将其与“正在下载”操作交换,并调用
sendProgressUpdate
来更新界面 (UI)。正在下载状态表示下载正在进行中。您可以使用此状态向用户显示进度条或其他指示器。
已下载状态表示下载已完成。下载完成后,您可以将“正在下载”替换为“已下载”,并使用
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
键调用sendResult
,以指示应刷新相应项。此外,您还可以使用EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
键向用户显示成功消息。
这种方法可让您向用户清晰反馈下载过程及其当前状态。您可以使用图标添加更多详细信息,以显示 25%、50% 和 75% 的下载状态。
收藏操作示例
另一个示例是具有两种状态的“收藏”操作:
对于不在用户收藏夹列表中的商品,系统会显示收藏。当用户选择此操作时,将其与 Favorited 交换,并使用
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
键调用sendResult
以更新界面。对于用户收藏夹列表中的商品,系统会显示已收藏。当用户选择此操作时,将其与收藏操作交换,并使用
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
键调用sendResult
来更新界面。
这种方法可为用户提供清晰一致的方式来管理其喜爱的商品。这些示例展示了自定义浏览操作的灵活性,以及如何使用它们在汽车的媒体应用中实现各种功能并提供实时反馈,从而提升用户体验。
您可以在 TestMediaApp
项目中查看此功能的全面示例实现。