Подобно тому, как вы используете пользовательские действия воспроизведения для поддержки уникальных возможностей в режиме просмотра воспроизведения, вы можете использовать пользовательские действия просмотра для поддержки уникальных возможностей в режимах просмотра. Например, вы можете использовать пользовательские действия просмотра, чтобы пользователи могли загружать плейлисты или добавлять элемент в очередь.
Если количество пользовательских действий превышает количество, отображаемое производителем оригинального оборудования (OEM), пользователю отображается дополнительное меню. Каждое пользовательское действие просмотра определяется следующим образом:
- Идентификатор действия: Уникальный строковый идентификатор
- Метка действия: Текст, отображаемый пользователю.
- Идентификатор ресурса (URI) значка действия: векторный рисунок, который можно раскрашивать.

Рисунок 1. Переполнение пользовательского действия просмотра.
Вы определяете список пользовательских действий просмотра глобально в рамках вашего BrowseRoot . Затем прикрепляете подмножество этих действий к отдельным MediaItem .
Когда пользователь взаимодействует с пользовательским действием просмотра, ваше приложение получает обратный вызов в onCustomAction . Затем вы обрабатываете это действие и при необходимости обновляете список действий для MediaItem . Это полезно для действий с сохранением состояния, таких как «Избранное» и «Загрузка». Для действий, которые не требуют обновления, например, «Воспроизвести радио», вам не нужно обновлять список действий.

Рисунок 2. Настраиваемая панель инструментов для действий просмотра.
Вы также можете прикрепить пользовательские действия просмотра к корневому узлу просмотра. Эти действия отображаются на дополнительной панели инструментов под основной панелью инструментов.
Чтобы добавить в приложение пользовательские действия просмотра:
Переопределите два метода в вашей реализации
MediaBrowserServiceCompat:Анализ ограничений на количество действий во время выполнения:
В
onGetRootполучите максимальное количество разрешенных действий для каждогоMediaItem, используя ключBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMITиз пакетаrootHintsBundle. Ограничение, равное 0, указывает на то, что эта функция не поддерживается системой.Создайте глобальный список пользовательских действий просмотра. Для каждого действия создайте объект
Bundleсо следующими ключами:- Идентификатор действия
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID - Метка действия
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL - URI значка действия
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
- Идентификатор действия
Добавьте все объекты действия
Bundleв список.Добавьте глобальный список в ваш
BrowseRoot. ВBundleBrowseRootextras Bundle добавьте список действий в видеParcelableArrayList, используя ключBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST.Добавьте действия к объектам
MediaItem. Вы можете добавить действия к отдельным объектамMediaItem, включив список идентификаторов действий в параметрыMediaDescriptionCompatextras с помощью ключаDESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST. Этот список должен быть подмножеством глобального списка действий, определенного вBrowseRoot.Обрабатывайте действия и возвращайте информацию о ходе выполнения или результатах:
В
onCustomActionобработайте действие на основе идентификатора действия и любых других необходимых данных. ИдентификаторMediaItem, вызвавшего действие, можно получить из дополнительных параметров, используя ключEXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID.Вы можете обновить список действий для
MediaItem, добавив ключEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMв пакет прогресса или результата.
Обновите состояние действия
Чтобы переопределить эти методы в 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 .
Идентификатор действия:
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 должны быть подмножеством глобального списка действий просмотра, заданного в 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);
Build onCustomAction result
Для получения результата:
Анализ
mediaIdиз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); }Для асинхронных результатов отсоедините результат,
result.detach.Сформируйте пакет результатов:
Вывести сообщение пользователю:
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).Состояние «Загрузка» указывает на то, что загрузка находится в процессе. Вы можете использовать это состояние для отображения индикатора выполнения или другого показателя для пользователя.
Состояние «Загружено» указывает на то, что загрузка завершена. После завершения загрузки вы можете поменять местами состояния «Загрузка» и «Загружено» и вызвать
sendResultс ключомEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, чтобы указать, что элемент должен быть обновлен. Кроме того, вы можете использовать ключEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGEдля отображения сообщения об успешном завершении пользователю.
Этот подход позволяет предоставлять пользователю четкую обратную связь о процессе загрузки и ее текущем состоянии. Можно добавить больше деталей с помощью значков, отображающих 25%, 50% и 75% загрузки.
Пример любимого действия
Другой пример — избранное действие с двумя состояниями:
Функция «Избранное» отображается для элементов, отсутствующих в списке избранных пользователя. Когда пользователь выбирает это действие, замените его на «Избранное» и вызовите
sendResultс ключомEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMдля обновления пользовательского интерфейса.«Избранное» отображается для элементов в списке избранных пользователя. Когда пользователь выбирает это действие, замените его на «Избранное» и вызовите функцию
sendResultс ключомEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEMдля обновления пользовательского интерфейса.
Этот подход обеспечивает пользователям понятный и последовательный способ управления избранными элементами. Приведенные примеры демонстрируют гибкость пользовательских действий просмотра и то, как их можно использовать для реализации различных функций с обратной связью в реальном времени для улучшения пользовательского опыта в мультимедийном приложении автомобиля.
Подробный пример реализации этой функции можно увидеть в проекте TestMediaApp .