Приложения для мультимедиа, использующие шаблоны библиотеки приложений Car App Library, могут настраивать просмотр и воспроизведение контента, обеспечивая при этом оптимизацию для автомобильных экранов и минимизируя отвлекающие факторы во время вождения.
В этом руководстве предполагается, что у вас уже есть мультимедийное приложение, которое воспроизводит аудио на телефоне и соответствует архитектуре мультимедийных приложений Android. Библиотека приложений для автомобилей позволяет заменить интерфейс приложения шаблонами вместо тех, которые созданы с использованием структуры данных Создание мультимедийных приложений для автомобилей
MediaBrowser. Вам по-прежнему нужно предоставить MediaSession для элементов управления воспроизведением и MediaBrowserService или MediaLibraryService для рекомендаций и других умных функций.
Настройте манифест приложения
Помимо шагов, описанных в разделе Использование библиотеки Android for Cars App Library, для мультимедийных приложений на основе шаблонов требуется следующее:
Как объявить поддержку категории в манифесте
В фильтре интентов элемента CarAppService вашего приложения должна быть объявлена androidx.car.app.category.MEDIA
категория приложения для автомобилей.
<application>
...
<service
...
android:name=".MyCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.MEDIA"/>
</intent-filter>
</service>
...
<application>
Чтобы получить доступ к MediaPlaybackTemplate, в файле манифеста приложения также нужно объявить разрешение androidx.car.app.MEDIA_TEMPLATES:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
...
</manifest>
Как задать минимальный уровень Car App API
Мультимедийные приложения, использующие MediaPlaybackTemplate, поддерживаются только в CAL API 8 и более поздних версиях. Убедитесь, что минимальный уровень Car App API level – 8.
<application ...>
...
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="8"/>
...
</application>
Добавьте значок атрибуции
Для мультимедийных приложений, созданных с помощью библиотеки приложений Car App Library, необходимо добавить значок атрибуции.
Как объявить о поддержке Android Auto
Убедитесь, что в манифест приложения включено следующее:
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Затем добавьте объявление template в automotive_app_desc.xml в ресурсах XML. Это должно выглядеть следующим образом:
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
<uses name="media"/>
<uses name="template"/>
</automotiveApp>
Как объявить о поддержке Android Automotive OS
Есть два способа распространения мультимедийного приложения с поддержкой библиотеки приложений для автомобилей на Android Automotive OS: в виде одного APK-файла или двух отдельных. Если вы распространяете один APK-файл, он будет поддерживать автомобили с Android Automotive OS и хостом библиотеки приложений Car App Library. В противном случае будет использоваться приложение MediaBrowserService или MediaLibraryService, даже на более старых версиях Android (Android 10–13). Если вы решите распространять два отдельных APK, то сможете обновлять новые дополнения в версии библиотеки приложений для автомобилей, не опасаясь повлиять на версию приложения для MediaBrowserService или MediaLibraryService.
Распространение одного APK-файла
Если вы распространяете один APK-файл для версий приложения, предназначенных для библиотеки автомобильных приложений и MediaBrowserService или MediaLibraryService, важно установить для android.software.car.templates_host.media значение android:required="false".
<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>
Затем следуйте рекомендациям по использованию библиотеки приложений для автомобилей в AAOS и добавьте запускаемое действие CarAppActivity (или действие-трамплин). В манифесте для действия должно быть задано значение android:enabled="false". Затем добавьте тег метаданных в объявление MediaBrowserService, указав, что компонент CarAppActivity используется в качестве замены. Пример манифеста:
<service android:name=".media.MyMediaService"
android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
</intent-filter>
<!-- Link to Car App Library Activity -->
<meta-data
android:name="androidx.car.app.media.CalMediaActivityComponent"
android:value="com.example.mediaapp.LaunchableTrampoline"/>
</service>
<activity
android:name=".LaunchableTrampoline"
android:exported="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
android:launchMode="singleTask"
android:label="@string/app_name_cal"
android:enabled="false"> <!-- Set to false -->
<meta-data android:name="distractionOptimized" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Распространение в Google Play
Ваш APK-файл с библиотекой приложений для автомобилей и MediaBrowserService или MediaLibraryService должен быть включен с более высоким кодом версии и minSdk, предназначенным для Android 14 (34).
Распространение с помощью двух APK-файлов
Чтобы распространять два отдельных APK-файла, один из которых использует библиотеку приложений Car App Library, а другой – MediaBrowserService или MediaLibraryService, выполните следующие действия. Это позволит обеспечить правильный таргетинг на возможности автомобиля.
При создании отдельного APK-файла для версии приложения, использующей библиотеку приложений Car App Library, необходимо задать для android.software.car.templates_host.media значение android:required=true. Это гарантирует, что приложение будет распространяться только в сборках Android Automotive OS, сертифицированных для поддержки хоста библиотеки приложений для автомобилей.
<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>
Помимо использования android.software.car.templates_host.media и установки значения android:required=true, выполните следующие шаги, чтобы включить Android Automotive OS для запускаемого действия библиотеки приложений Car App Library.
Распространение в Google Play
APK-файл, использующий библиотеку приложений Car App Library, должен распространяться через специальный тип версии для Automotive OS.
Поддержка голосовых команд
Добавьте в приложение голосовое управление, чтобы пользователи могли выполнять распространенные действия без помощи рук.
Подробные инструкции по реализации приведены в статье Поддержка голосовых команд для медиаконтента. Если вы получаете голосовую команду в мультимедийном приложении на основе шаблона, вам не нужно обновлять MediaBrowserService или MediaLibraryService с результатами поиска. Вместо этого добавьте в шаблон воспроизведения медиаконтента действие, которое позволит пользователю найти больше контента на основе этого воспроизведения или поискового запроса. Поддержка голосовых команд – обязательное требование к качеству приложений для VC-1.
Создайте шаблон воспроизведения
Шаблон MediaPlaybackTemplate позволяет показывать информацию о воспроизведении медиаконтента в приложении для мультимедиа из библиотеки приложений Car App Library. В этом шаблоне можно настроить заголовок и настраиваемые действия, а информация о медиаконтенте и элементы управления воспроизведением будут добавляться хостом на основе состояния MediaSession вашего приложения.
Рисунок 1.
MediaPlaybackTemplate с действием в заголовке, позволяющим открыть очередь в верхней части экрана.
В этом примере кода показано, как создать шаблон воспроизведения, который задает действие в заголовке, позволяющее пользователю перейти к экрану с очередью песен.
val playbackTemplate = MediaPlaybackTemplate.Builder()
.setHeader(
Header.Builder()
.setStartHeaderAction(Action.BACK)
.addEndHeaderAction(
Action.Builder()
.setTitle(model.context.getString(R.string.queue_button_title))
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
model.context,
R.drawable.gs_queue_music_vd_theme_24,
))
.build())
.setOnClickListener(showQueueScreen())
.build())
.setTitle(model.context.getString(R.string.media_playback_view_title))
.build())
.build()
При использовании MediaPlaybackTemplate зарегистрируйте токен MediaSession с помощью MediaPlaybackManager в CarAppService. Если этого не сделать, при отправке MediaPlaybackTemplate на хост будет показано сообщение об ошибке.
import androidx.car.app.media.MediaPlaybackManager
…
override fun onCreateSession(sessionInfo: SessionInfo): Session {
return object : Session() {
…
init {
lifecycle.addObserver(
LifecycleEventObserver { _, event ->
if (event == ON_CREATE) {
val token = ... // MediaSessionCompat.Token
(carContext.getCarService(CarContext.MEDIA_PLAYBACK_SERVICE) as MediaPlaybackManager)
.registerMediaPlaybackToken(token)
}
...
}
)
}
}
}
.registerMediaPlaybackToken необходим для передачи информации о воспроизведении медиаконтента и элементов управления в Android Auto. Это также важно для хоста, чтобы создавать уведомления, относящиеся к медиа.
Для приложений, использующих библиотеку Media3, в которой вместо стандартного MediaSessionCompat.Token применяется PlatformToken, вам нужно будет реализовать пользовательский SessionCommand в MediaLibrarySession.Callback, который возвращает базовый токен платформы сеанса: session.platformToken. В CarAppService отправьте эту специальную команду в сеанс. Получив токен платформы, преобразуйте его с помощью MediaSessionCompat.Token.fromToken(platformToken) и передайте токен совместимости в библиотеку приложений Car App Library в .registerMediaPlaybackToken().
Как упорядочить медиафайлы с помощью шаблонов
Чтобы упорядочить медиаконтент, например песни или альбомы, рекомендуем использовать SectionedItemTemplate. С его помощью вы можете объединить GridSection и RowSection, чтобы создать макеты, в которых списки изображений и текстовых элементов будут смешаны.
Рисунок 2. Объект SectionedItemTemplate, содержащий объект RowSection, за которым следует объект GridSection.
Использование SectionedItemTemplate в TabTemplate
Один из удобных способов классифицировать медиаконтент в приложении – использовать SectionedItemTemplate внутри TabTemplate.
val template =
SectionedItemTemplate.Builder()...build();
val tabTemplate =
TabTemplate.Builder(tabCallback)
.setTabContents(TabContents.Builder(template).build)
.setHeaderAction(Action.APP_ICON)
…
.build();
Компоненты и функции библиотеки приложений для автомобилей версии 1.9
В Car App Library API версии 1.9 появились настраиваемые компоненты для уникальных возможностей просмотра, такие как чипы, индикаторы выполнения, сжатые элементы, интерактивный и расширенный заголовок, разделы Spotlight и баннеры.
Рисунок 3. SectionedItemTemplate, содержащий Chips, Condensed Items, Interactive Header, Grid Items и Minimized Control Panel.
Рисунок 4. Два экрана просмотра медиаконтента с элементами Expanded Header, Spotlight Sections и Progress Bars.
Подробнее о том, как разработать пользовательский интерфейс мультимедийного приложения с помощью этих шаблонов, рассказывается в статье Приложения для мультимедиа.
Как перейти к элементам управления воспроизведением
При просмотре медиаконтента пользователю важно иметь возможность быстро перейти к экрану MediaPlaybackTemplate, не отвлекаясь от дороги.Чтобы приложение соответствовало требованиям к качеству MFT-1, в нем должна быть возможность перейти к экрану MediaPlaybackTemplate со всех экранов просмотра медиаконтента.
Если вы используете SectionedItemTemplate, вы можете добавить командную кнопку, которая перенаправляет пользователя на экран воспроизведения медиаконтента. Используйте стандартное действие Action.MEDIA_PLAYBACK из библиотеки приложений Car App Library. В мультимедийном приложении это действие будет отображаться как свернутая панель управления, которая необходима для соответствия требованию к качеству MFT-1, если вы используете Car App Library API версии 1.9 или выше. В других шаблонах для этого можно использовать действие в заголовке.
Обработка системных намерений воспроизведения медиаконтента
Если приложение запускается с системного экрана воспроизведения медиаконтента, например с карточки медиа, пользователь должен быть перенаправлен на MediaPlaybackTemplate. Чтобы обеспечить удобство для пользователей, мультимедийные приложения должны обрабатывать этот Intent Action.
Добавьте действие androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK в фильтр интентов компонента библиотеки приложений Car App Library (CarAppActivity или Activity).
Убедитесь, что в действии используется launchMode со значением singleTask или singleTop, чтобы вызывался метод onNewIntent().
<activity
android:name=".LaunchableTrampoline"
android:exported="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
android:launchMode="singleTask"
android:label="@string/app_name_cal"
android:enabled="false">
<meta-data android:name="distractionOptimized" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
В классе Session переопределите onNewIntent(), чтобы проанализировать входящее намерение.
Если действие входящего намерения совпадает с SHOW_MEDIA_PLAYBACK, перенаправьте пользователя на экран "Что сейчас играет?".
@Override
public void onNewIntent(@NonNull Intent intent) {
super.onNewIntent(intent);
if (SHOW_MEDIA_PLAYBACK.equals(intent.getAction())) {
ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
// Avoid redundant navigation if already on the playing screen
if (screenManager.getTop() instanceof MyMediaPlayScreen) {
return;
}
screenManager.push(MyMediaPlayScreen.createScreenFromPlaying(
getCarContext(), mMediaSessionController));
}
}
Если вы используете промежуточное действие, проверьте действие intent в onCreate(). Передайте это действие в намерение создания CarAppActivity перед вызовом finish().
public class LaunchableTrampoline extends AppCompatActivity {
private static final String SHOW_MEDIA_PLAYBACK = "androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent receivedIntent = getIntent();
String action;
if (SHOW_MEDIA_PLAYBACK.equals(receivedIntent.getAction())) {
action = SHOW_MEDIA_PLAYBACK;
} else {
action = Intent.ACTION_MAIN;
}
Intent intent = new Intent(action);
intent.setClassName(getPackageName(), "androidx.car.app.activity.CarAppActivity");
startActivity(intent);
finish();
}
}