Android Automotive OS позволяет устанавливать приложения в информационно-развлекательной системе автомобиля. Чтобы ваш продукт был доступен пользователям платформы, опубликуйте безопасную для водителя версию приложения, совместимую с Android Automotive OS. Вы можете использовать код и ресурсы приложения Android Auto практически без изменений. Однако нужно будет создать отдельную сборку, которая соответствует требованиям, описанным на этой странице.
Обзор разработки
Чтобы добавить поддержку Android Automotive OS, выполните действия, описанные в разделах ниже.
- Включите функции для автомобилей в Android Studio.
- Создайте автомобильный модуль.
- Обновите зависимости Gradle.
- При необходимости настройте параметры и действия при входе.
- При необходимости ознакомьтесь с подсказками для хостов медиаконтента.
Рекомендации по дизайну
Android Automotive OS отвечает за макет медиаконтента, который получает от сервиса просмотра медиафайлов вашего приложения. Это означает, что приложение не отрисовывает пользовательский интерфейс и не запускает никаких действий, когда пользователь включает воспроизведение медиаконтента.
Если вы реализуете действия, связанные с настройками или входом в аккаунт, они должны быть оптимизированы для автомобиля. При разработке этих разделов приложения следуйте рекомендациям по дизайну для Android Automotive OS.
Настройте проект
Чтобы включить поддержку Android Automotive OS, необходимо настроить несколько компонентов проекта приложения.
Как включить функции для автомобилей в Android Studio
Чтобы все функции Automotive OS были доступны, используйте Android Studio 4.0 или более поздней версии.
Как создать автомобильный модуль
Некоторые компоненты Android Automotive OS, например манифест, имеют требования, зависящие от платформы. Создайте модуль, который позволит хранить код для этих компонентов отдельно от другого кода в проекте, например кода, используемого для приложения на телефоне.
Чтобы добавить автомобильный модуль в проект, выполните следующие действия:
- В Android Studio нажмите File > New > New Module (Файл > Создать > Создать модуль).
- Выберите Automotive Module (Автомобильный модуль) и нажмите Next (Далее).
- Укажите название приложения или библиотеки. Это название приложения, которое пользователи видят в Android Automotive OS.
- Укажите название модуля.
- Измените название пакета, чтобы оно соответствовало вашему приложению.
В поле Minimum SDK (Минимальная версия SDK) выберите API 28: Android 9.0 (Pie) и нажмите Next (Далее).
Все автомобили, поддерживающие Android Automotive OS, работают на Android 9 (уровень API 28) или более поздней версии, поэтому выбор этого значения позволяет ориентироваться на все совместимые автомобили.
Выберите Нет активности и нажмите Готово.
Создав модуль в Android Studio, откройте файл AndroidManifest.xml в новом автомобильном модуле:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.media">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" />
<uses-feature
android:name="android.hardware.type.automotive"
android:required="true" />
</manifest>
Элемент <application> содержит стандартную информацию о приложении, а также элемент <uses-feature>, который объявляет о поддержке Android Automotive OS.
Обратите внимание, что в манифесте не объявлены никакие действия.
Если вы реализовали действия для настроек или входа, добавьте их здесь. Эти действия запускаются системой с помощью явных намерений и являются единственными действиями, которые вы объявляете в манифесте для своего приложения Android Automotive OS.
После добавления настроек или действий по входу завершите файл манифеста, установив для атрибута android:appCategory элемента <application> значение "audio".
<application
...
android:appCategory="audio" />
Объявление требований к функциям
Чтобы распространять приложения для Android Automotive OS через Google Play, они должны соответствовать определенным требованиям. Подробнее о требованиях к функциям Google Play…
Как объявить, что приложение для Android Automotive OS является мультимедийным
Чтобы объявить, что ваше приложение поддерживает Android Automotive OS, добавьте в манифест следующую запись:
<application>
...
<meta-data android:name="com.android.automotive"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Эта запись в манифесте ссылается на XML-файл, в котором указаны функции, поддерживаемые вашим приложением.
Чтобы указать, что у вас есть мультимедийное приложение, добавьте XML-файл с названием automotive_app_desc.xml в каталог res/xml/ в своем проекте. Добавьте в файл следующий контент:
<automotiveApp>
<uses name="media"/>
</automotiveApp>
Фильтры интентов
Android Automotive OS использует явные интенты для запуска Activity в мультимедийном приложении. Не включайте в файл манифеста Activity, у которых есть фильтры интентов CATEGORY_LAUNCHER или ACTION_MAIN.
Действия, подобные описанным в примере ниже, обычно нацелены на телефон или другое мобильное устройство. Объявите эти Activity в модуле, который создает приложение "Телефон", а не в модуле, который создает приложение для Android Automotive OS.
<activity android:name=".MyActivity">
<intent-filter>
<!-- You can't use either of these intents for Android Automotive OS -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--
In their place, you can include other intent filters for any activities
that your app needs for Android Automotive OS, such as settings or
sign-in activities.
-->
</intent-filter>
</activity>
Обновите зависимости Gradle
Рекомендуем хранить сервис просмотра медиаконтента в отдельном модуле, который используется как в приложении "Телефон", так и в автомобильном модуле. Если вы используете этот подход, вам нужно обновить автомобильный модуль, чтобы включить общий модуль, как показано в следующем фрагменте кода:
my-auto-module/build.gradle
Яркий
buildscript { ... dependencies { ... implementation project(':shared_module_name') } }
Kotlin
buildscript { ... dependencies { ... implementation(project(":shared_module_name")) } }
Настройте параметры и действия для входа
Помимо сервиса просмотра медиаконтента, вы можете добавить в приложение для Android Automotive OS настройки и действия для входа, оптимизированные для автомобилей. Они позволяют реализовать функции, которых нет в Android Media API.
Реализуйте эти действия, только если в приложении для Android Automotive OS пользователям нужно входить в аккаунт или задавать настройки. Эти действия не используются в Android Auto.
Рабочие процессы действий
На схеме ниже показано, как пользователь взаимодействует с настройками и действиями для входа в Android Automotive OS.
Рисунок 1. Настройки и рабочие процессы, связанные с действиями при входе.
Как ограничить отвлекающие факторы в настройках и при входе в аккаунт
Чтобы настройки и действия по входу были доступны только во время парковки, убедитесь, что элементы <activity> не содержат элемент <meta-data>. Если мы обнаружим такой элемент, то отклоним приложение.
<!-- NOT ALLOWED -->
<meta-data
android:name="distractionOptimized"
android:value="true"/>
Добавьте действие настроек
Вы можете добавить оптимизированные для автомобиля настройки, чтобы пользователи могли задавать параметры приложения в машине. В настройках также могут быть доступны другие рабочие процессы, например вход в аккаунт пользователя, выход из него или переключение между аккаунтами. Помните, что это действие запускается только приложением, работающим на Android Automotive OS. Приложения на телефоне, подключенные к Android Auto, не используют его.
Как объявить действие настроек
Вы должны объявить действие настроек в файле манифеста приложения, как показано в следующем фрагменте кода:
<application>
...
<activity android:name=".AppSettingsActivity"
android:exported="true"
android:theme="@style/SettingsActivity"
android:label="@string/app_settings_activity_title">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES"/>
</intent-filter>
</activity>
...
</application>
Реализуйте активность настроек
Когда пользователь запускает приложение, Android Automotive OS обнаруживает объявленное вами действие настроек и показывает его в виде значка или другого элемента.
Пользователь может нажать на нее или выбрать на дисплее автомобиля, чтобы перейти к действию. Android Automotive OS отправляет интент ACTION_APPLICATION_PREFERENCES, который сообщает приложению, что нужно запустить объект activity настроек.
В оставшейся части этого раздела показано, как можно адаптировать код из примера приложения Universal Android Music Player (UAMP) для реализации настроек в вашем приложении.
Для начала скачайте образец кода:
# Clone the UAMP repositorygit clone https://github.com/android/uamp.git# Fetch the appropriate pull request to your local repositorygit fetch origin pull/323/head:NEW_LOCAL_BRANCH_NAME# Switch to the new branchgit checkout NEW_LOCAL_BRANCH_NAME
Чтобы реализовать действие, выполните следующие действия:
- Скопируйте папку
automotive/automotive-libв автомобильный модуль. - Определите дерево настроек, как в
automotive/src/main/res/xml/preferences.xml. Реализуйте
PreferenceFragmentCompat, который будет показывать ваши настройки. Дополнительную информацию можно найти в файлахSettingsFragment.ktиSettingsActivity.ktв UAMP и в руководстве по настройкам Android.
При реализации активности настроек рассмотрите эти рекомендации по использованию некоторых компонентов в библиотеке Preference:
- В настройках должно быть не более двух уровней вложенности.
- Не используйте
DropDownPreference. Вместо этого используйтеListPreference. - Организационные компоненты:
PreferenceScreen- Это должен быть верхний уровень дерева настроек.
PreferenceCategory- Используется для группировки объектов
Preference. - Добавьте
title.
- Используется для группировки объектов
- Добавьте
keyиtitleво все перечисленные ниже компоненты. Вы также можете добавитьsummary,iconили оба этих элемента:Preference- Настройте логику в обратном вызове
onPreferenceTreeClick()вашей реализацииPreferenceFragmentCompat.
- Настройте логику в обратном вызове
CheckBoxPreference- Может содержать
summaryOnилиsummaryOffвместоsummaryдля условного текста.
- Может содержать
SwitchPreference- Может содержать
summaryOnилиsummaryOffвместоsummaryдля условного текста. - Может иметь значение
switchTextOnилиswitchTextOff.
- Может содержать
SeekBarPreference- Добавьте
min,maxиdefaultValue.
- Добавьте
EditTextPreference- Включите
dialogTitle,positiveButtonTextиnegativeButtonText. - Может содержать одно или оба значения:
dialogMessageиdialogLayoutResource.
- Включите
com.example.android.uamp.automotive.lib.ListPreference- В основном из
ListPreference. - Используется для показа списка объектов
Preferenceс возможностью выбора одного из них. - Должен содержать массив
entriesи соответствующийentryValues.
- В основном из
com.example.android.uamp.automotive.lib.MultiSelectListPreference- В основном из
MultiSelectListPreference - Используется для показа списка объектов
Preferenceс несколькими вариантами ответа. - Должен содержать массив
entriesи соответствующийentryValues.
- В основном из
Добавьте действие по входу в аккаунт
Если для работы с приложением требуется войти в аккаунт, вы можете добавить оптимизированный для автомобиля процесс входа и выхода. Также можно добавить рабочие процессы входа и выхода в настройки, но если приложение нельзя использовать без входа в аккаунт, лучше добавить отдельный процесс входа. Помните, что это действие запускается только приложением, работающим на Android Automotive OS. Приложения на телефоне, подключенные к Android Auto, не используют его.
Требовать входа в аккаунт при запуске приложения
Чтобы требовать от пользователя входа в аккаунт перед использованием приложения, сервис просмотра медиаконтента должен выполнять следующие действия:
- В методе
onLoadChildren()своего сервиса отправьте результатnullс помощью методаsendResult(). - Задайте для
PlaybackStateCompatмедиасеанса значениеSTATE_ERRORс помощью методаsetState(). Это сообщает Android Automotive OS, что никакие другие операции не могут быть выполнены, пока ошибка не будет устранена. - Задайте для кода ошибки
PlaybackStateCompatсеанса воспроизведения медиаконтента значениеERROR_CODE_AUTHENTICATION_EXPIRED. Это сообщит Android Automotive OS, что пользователю нужно пройти аутентификацию. - Задайте сообщение об ошибке
PlaybackStateCompatдля сеанса воспроизведения медиаконтента с помощью методаsetErrorMessage(). Поскольку это пользовательское сообщение об ошибке, локализуйте его для текущих региональных настроек пользователя. Задайте дополнительные параметры
PlaybackStateCompatсеанса воспроизведения медиаконтента с помощью методаsetExtras(). Добавьте следующие два или три ключа:PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL– строка, которая показывается на кнопке, запускающей процесс входа. Поскольку эта строка видна пользователю, локализуйте ее для текущего региона пользователя.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT– объектPendingIntent, который направляет пользователя к действию по входу, когда пользователь нажимает кнопку, указанную вPLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_USING_CAR_APP_LIBRARY_INTENT–PendingIntent, который направляет пользователя к действию входа в библиотеку приложений для автомобиля. Поскольку хост библиотеки приложений для автомобилей оптимизирован для вождения, намерение автоматически обходит экран устранения ошибок и сразу же отображает экран входа. Если вы задаете это дополнительное значение, также задайте два предыдущих, чтобы обеспечить обратную совместимость со старыми автомобилями.
В приведенном ниже фрагменте кода показано, как настроить приложение, чтобы оно требовало от пользователя войти в аккаунт перед началом работы.
Kotlin
import androidx.media.utils.MediaConstants val signInIntent = Intent(this, SignInActivity::class.java) val signInActivityPendingIntent = PendingIntent.getActivity(this, 0, signInIntent, 0) val extras = Bundle().apply { putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL, "Sign in" ) putParcelable( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT, signInActivityPendingIntent ) } val playbackState = PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f) .setErrorMessage( PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED, "Authentication required" ) .setExtras(extras) .build() mediaSession.setPlaybackState(playbackState)
Java
import androidx.media.utils.MediaConstants; Intent signInIntent = new Intent(this, SignInActivity.class); PendingIntent signInActivityPendingIntent = PendingIntent.getActivity(this, 0, signInIntent, 0); Bundle extras = new Bundle(); extras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL, "Sign in"); extras.putParcelable( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT, signInActivityPendingIntent); PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f) .setErrorMessage( PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED, "Authentication required" ) .setExtras(extras) .build(); mediaSession.setPlaybackState(playbackState);
После успешной аутентификации пользователя верните PlaybackStateCompat в состояние, отличное от STATE_ERROR, а затем верните пользователя в Android Automotive OS, вызвав метод finish().
Реализуйте действие входа
Google предлагает различные инструменты идентификации, которые помогут пользователям входить в ваше приложение в автомобиле. Некоторые инструменты, такие как Firebase Authentication, предоставляют полнофункциональные наборы инструментов, которые могут помочь вам создать настраиваемые возможности аутентификации. Другие инструменты используют существующие учетные данные пользователя или другие технологии, чтобы помочь вам создать удобный интерфейс входа для пользователей.
Следующие инструменты помогут вам упростить вход для пользователей, которые ранее входили в аккаунт на другом устройстве:
- Регистрация и вход в одно нажатие. Если вы уже реализовали вход в одно нажатие для других устройств, например для приложения на телефоне, добавьте эту функцию в приложение для Android Automotive OS, чтобы поддерживать существующих пользователей.
- Вход с аккаунтом Google. Если вы уже реализовали вход с аккаунтом Google для других устройств, например для приложения "Телефон", добавьте его и в приложение для Android Automotive OS, чтобы поддерживать существующих пользователей, использующих вход с аккаунтом Google.
- Автозаполнение от Google. Если пользователи включили Автозаполнение от Google на других устройствах Android, их учетные данные сохраняются в Google Менеджере паролей. Когда эти пользователи входят в ваше приложение для Android Automotive OS, Автозаполнение от Google предлагает им подходящие сохраненные учетные данные. Чтобы использовать Автозаполнение от Google, не нужно разрабатывать приложения. Однако разработчики могут оптимизировать свои приложения, чтобы повысить качество результатов. Автозаполнение от Google поддерживается на всех устройствах с Android 8.0 (уровень API 26) или более поздней версии, включая Android Automotive OS.
Назначить AccountManager
В приложениях для Android Automotive OS, в которых есть аутентификация, необходимо использовать AccountManager по следующим причинам:
- Улучшенный UX и простота управления аккаунтами. Пользователи могут управлять всеми своими аккаунтами в меню "Аккаунты" в системных настройках, в том числе входить в них и выходить из них.
- Гостевой режим. Автомобили – это устройства общего пользования, поэтому производители могут включить в них гостевой режим, в котором нельзя добавлять аккаунты. Для этого используется
DISALLOW_MODIFY_ACCOUNTSдляAccountManager.
Разрешения
Если вам нужно запросить разрешения у пользователя, используйте ту же последовательность действий, что и для аутентификации или настроек, как показано на схеме рабочих процессов в предыдущем разделе.
Как реализовать выход из аккаунта
Независимо от того, как вы реализовали вход, при выходе пользователя вы должны вызвать MediaBrowserServiceCompat#notifyChildrenChanged(rootId), чтобы сделать дерево просмотра недействительным. Это позволит хост-приложению удалить всю информацию, связанную с пользователем, например последний поисковый запрос.
Запустите приложение для трансляции медиаконтента.
Вы можете создать интенты, чтобы открывать приложение для размещения медиаконтента в вашем приложении или контент в вашем приложении. Например:
- Приложение может опубликовать уведомление с отложенным намерением, которое позволяет пользователю открыть приложение и послушать новый контент.
- Приложение может обрабатывать ссылки на контент и открывать основное приложение в наиболее подходящем режиме.
Как определить возможности хоста медиаконтента
Разные версии приложения поддерживают разные возможности. Хосты указывают на поддержку различных возможностей, включая фильтры намерений для следующих действий:
Все приложения для размещения медиаконтента поддерживают намерения MEDIA_TEMPLATE. Чтобы определить, поддерживает ли медиахост интенты MEDIA_TEMPLATE_V2, можно использовать queryIntentActivities() следующим образом:
val isMediaTemplateV2Supported = packageManager.queryIntentActivities(
Intent(MediaIntentExtras.ACTION_MEDIA_TEMPLATE_V2),
// MATCH_DEFAULT_ONLY since the host should be started with implicit intents
// MATCH_SYSTEM_ONLY excludes any apps that aren't preinstalled
PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_SYSTEM_ONLY
).size > 0
Как создать и использовать намерение
В зависимости от того, какие действия intent поддерживаются медиахостом и каков ваш конкретный вариант использования, вы можете предоставить следующие дополнительные возможности при создании intent, который вы используете для запуска приложения медиахоста.
| Дополнительный ключ | Тип | Описание | Доступные действия |
|---|---|---|---|
EXTRA_KEY_MEDIA_COMPONENT |
String |
Упрощенное название компонента MediaBrowserService, к которому должно подключаться приложение – хост медиаконтента. Обычно это название вашего приложения. Если это дополнительное поле не указано, хост медиаконтента по умолчанию использует активный источник медиаконтента. |
MEDIA_TEMPLATE, MEDIA_TEMPLATE_V2 |
EXTRA_KEY_SEARCH_QUERY |
String |
Поисковый запрос, который будет использоваться при вызове | MEDIA_TEMPLATE, MEDIA_TEMPLATE_V2 |
EXTRA_KEY_MEDIA_ID |
String |
Идентификатор мультимедийного объекта, который нужно открыть в режиме просмотра. | MEDIA_TEMPLATE_V2 |
EXTRA_KEY_SEARCH_ACTION |
Integer |
Действие, которое нужно выполнить после завершения поиска EXTRA_KEY_SEARCH_QUERY. |
MEDIA_TEMPLATE_V2 |
Например, если хост поддерживает действия MEDIA_TEMPLATE_V2, следующий код откроет приложение хоста, подключит его к MyMediaBrowserService, выполнит поиск по запросу "Джаз" и воспроизведет первый результат поиска. На всех остальных хостах будет открыто приложение медиахоста и выполнен поиск по запросу "джаз", после чего пользователь сможет выбрать, что воспроизвести.
val startMediaHostIntent = Intent(ACTION_MEDIA_TEMPLATE)
.putExtra(MediaIntentExtras.EXTRA_KEY_MEDIA_COMPONENT, MyMediaBrowserService::class.java)
.putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_QUERY, "Jazz")
.putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_ACTION, MediaIntentExtras.EXTRA_VALUE_PLAY_FIRST_ITEM_FROM_SEARCH)
context.startActivity(startMediaHostIntent)
Поддержка ссылок на контент
Чтобы улучшить работу мультимедийного приложения на устройствах с Android Automotive OS, вы можете добавить в него поддержку ссылок на контент. Например, это позволит пользователям открывать приложение прямо из браузера или при получении URL, отправленного с телефона с помощью Быстрой отправки.
Добавьте фильтры интентов для ссылок на контент
Чтобы сообщить ОС, что ваше приложение может обрабатывать ссылки на контент, в нем должны быть действия с подходящими фильтрами интентов. Информацию о формате фильтров интентов, используемых для ссылок на контент, можно найти в разделе Добавьте фильтры intent для входящих ссылок.
Для удобства пользователей поддерживайте все ссылки на контент, которые поддерживаются в мобильном приложении, если это возможно в приложении для автомобиля. Если в приложении есть настройки или действия для входа, фильтры интентов для обработки настроек и ссылок на контент для входа должны быть объявлены в соответствующих элементах манифеста <activity>. Для воспроизведения медиаконтента и ссылок на контент в браузере можно использовать трамплин-активность, как описано далее в этом разделе.
Как обрабатывать намерения ссылок на контент
Инструкции о том, как считывать и реагировать на намерение, которое использовалось для запуска действия приложения, можно найти в разделе Чтение данных из входящих намерений.
Как обрабатывать ссылки на контент для воспроизведения медиа и просмотра контента
Поскольку интерфейс для просмотра и воспроизведения отрисовывается хост-приложением, у действия, используемого для обработки ссылок на контент для воспроизведения и просмотра, не должно быть собственного интерфейса.
Вместо этого он должен в основном использоваться для создания и использования намерения, чтобы запустить приложение для воспроизведения медиаконтента. При необходимости он также может обрабатывать любые дополнительные изменения в состоянии вашего приложения, например добавление мультимедийных объектов в очередь. Ниже приведен пример реализации трамплин-активности.
fun DeepLinkTrampolineActivity : ComponentActivity() {
override fun onCreate() {
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
// Handle any side effects, such as adding a song to the queue
...
// Build the intent used to start the media host app
val startMediaHostIntent = ...
startActivity(intent)
// Finish the activity immediately so it isn't shown on screen
finish()
}
}
Чтение подсказок хоста медиаконтента
В зависимости от системного приложения (включая его версию), которое подключается к вашему сервису просмотра медиаконтента, ваше приложение может получать следующие дополнительные данные:
Обработка ошибок
Об ошибках в мультимедийных приложениях для Android Automotive OS сообщается с помощью PlaybackStateCompat сеанса воспроизведения. Для всех ошибок задайте подходящий код ошибки и сообщение об ошибке в PlaybackStateCompat. В интерфейсе появится Toast.
Если ошибка не препятствует воспроизведению, отправьте некритическую ошибку. Например, пользователь может слушать музыку в приложении без входа в аккаунт, но чтобы пропустить песню, ему нужно войти. Если вы используете некритическую ошибку, система может предложить пользователю войти в аккаунт, не прерывая воспроизведение текущего мультимедийного объекта.
При выдаче некритической ошибки сохраните остальную часть PlaybackStateCompat без изменений, за исключением кода ошибки и сообщения об ошибке. При таком подходе воспроизведение текущего мультимедийного объекта продолжится, пока пользователь решает, входить ли в систему.
Если воспроизведение невозможно, например нет подключения к интернету и офлайн-контента, задайте для PlaybackStateCompat состояние STATE_ERROR.
При последующих обновлениях PlaybackStateCompat удаляйте коды ошибок и сообщения об ошибках, чтобы не показывать несколько предупреждений об одной и той же ошибке.
Если вы не можете загрузить дерево навигации, например если требуется аутентификация, а пользователь не вошел в аккаунт, отправьте пустое дерево навигации. Чтобы указать на это, верните нулевой результат из onLoadChildren() для корневого узла мультимедиа. В этом случае система показывает полноэкранное сообщение об ошибке, заданное в PlaybackStateCompat.
Ошибки, требующие действий
Если ошибку можно исправить, задайте в PlaybackStateCompat два дополнительных параметра:
PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL– ярлык кнопки, которую нужно нажать, чтобы устранить ошибку. Поскольку эта строка пользовательская, локализуйте ее для текущих региональных настроек пользователя.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT–PendingIntent, который запускается при нажатии кнопки для устранения ошибки, например для запуска действия входа.
Ошибки, требующие действий, помечаются значком Dialog. Пользователи могут устранить их, только когда автомобиль остановлен.
Тестирование ошибок
Убедитесь, что приложение корректно обрабатывает ошибки во всех сценариях, включая следующие:
- Разные уровни продукта. Например, бесплатная и платная версии или версии для пользователей, вошедших в аккаунт и не вошедших в него.
- Разные состояния автомобиля, например парковка и движение.
- Разные состояния подключения. Например, онлайн и офлайн.
Примечание
При разработке приложения для Android Automotive OS учитывайте следующее:
Офлайн-контент
При необходимости реализуйте поддержку офлайн-воспроизведения. Автомобили с Android Automotive OS должны иметь собственное подключение к интернету, то есть тарифный план должен быть включен в стоимость автомобиля или оплачиваться пользователем. Однако в автомобилях связь может быть менее стабильной, чем на мобильных устройствах.
Вот несколько моментов, которые следует учитывать при разработке стратегии офлайн-поддержки:
- Лучше всего скачивать контент, когда приложение используется.
- Не рассчитывайте на то, что Wi-Fi будет доступен. Автомобиль может никогда не оказаться в зоне действия Wi-Fi, или производитель мог отключить Wi-Fi в пользу мобильной сети.
- Хотя кэшировать контент, который, как вы ожидаете, будет использовать пользователь, вполне допустимо, мы рекомендуем разрешить пользователю изменить это поведение в настройках.
- Место на диске в автомобилях может быть разным, поэтому предоставьте пользователям возможность удалять офлайн-контент, например через настройки.
Поддержка WebView
Компоненты WebView поддерживаются в Android Automotive OS, но разрешены только для настроек и входа в аккаунт. В действиях, использующих WebView, должна быть возможность закрыть окно или вернуться назад, не используя WebView.
Вот несколько примеров допустимого использования WebView:
- Показ политики конфиденциальности, условий использования или других юридических ссылок в настройках.
- Веб-версия процесса входа в аккаунт.
При использовании WebView можно включить JavaScript.
Защитите WebView
Примите все возможные меры предосторожности, чтобы компонент WebView не стал точкой входа в интернет. В приведенном ниже фрагменте кода показано, как заблокировать WebView для URL, используемого в вызове loadUrl(), и предотвратить переадресацию. Мы настоятельно рекомендуем использовать такие меры предосторожности, когда это возможно, например при показе ссылок на юридические ресурсы.
Kotlin
override fun shouldOverrideUrlLoading(webView: WebView, webResourceRequest: WebResourceRequest): Boolean { val originalUri: Uri = Uri.parse(webView.originalUrl) // Check for allowed URLs if (originalUri.equals(Uri.parse(BLANK_URL)) || originalUri.equals(webResourceRequest.url)) { return false } if (webResourceRequest.isRedirect) { logger.w("Redirect detected, not following") return true } setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.url) logger.w( String.format( "Navigation prevented to %s original is %s", webResourceRequest.url, originalUri)) return true }
Java
@Override public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) { Uri originalUri = Uri.parse(webView.getOriginalUrl()); // Check for allowed URLs if (originalUri.equals(Uri.parse(BLANK_URL)) || originalUri.equals(webResourceRequest.getUrl())) { return false; } if (webResourceRequest.isRedirect()) { logger.w("Redirect detected, not following"); return true; } setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.getUrl()); logger.w( String.format( "Navigation prevented to %s original is %s", webResourceRequest.getUrl(), originalUri)); return true; }
Названия пакетов
Поскольку для Android Automotive OS вы распространяете отдельный APK-файл, вы можете использовать название пакета из мобильного приложения или создать новое. Если вы используете другое название пакета, у вашего приложения будет две отдельные страницы в Google Play. Если вы используете текущее название пакета, у вашего приложения будет одна страница в обоих магазинах.
Это в основном бизнес-решение. Например, если у вас есть одна команда, работающая над мобильным приложением, и отдельная команда, работающая над приложением для Android Automotive OS, то может иметь смысл использовать отдельные названия пакетов и позволить каждой команде управлять своей собственной страницей в Google Play. С технической точки зрения оба подхода требуют примерно одинаковых усилий.
В таблице ниже приведены другие ключевые различия между сохранением текущего названия пакета и использованием нового.
| Функция | Одинаковые названия пакетов | Новое название пакета |
|---|---|---|
| Страница приложения в Google Play | Одиночный | Несколько |
| Установка с дублированием | Да, быстрая переустановка приложений в мастере настройки. | Нет |
| Процесс проверки в Google Play | Блокировка отзывов. Если один APK не проходит проверку, другие APK, отправленные в том же выпуске, блокируются. | Отдельные отзывы |
| Статистика, показатели и Android Vitals | Комбинированный: вы можете отфильтровать данные, относящиеся к автомобилям. | Разделить |
| Индексирование и ранжирование в Поиске | Опирайтесь на текущую репутацию | Без переноса |
| Интеграция с другими приложениями | Скорее всего, изменения не потребуются, если код медиафайлов используется в обоих APK. | Возможно, потребуется обновить соответствующее приложение, например для воспроизведения URI с помощью Google Ассистента. |
Часто задаваемые вопросы
Ниже приведены ответы на часто задаваемые вопросы об Android Automotive OS.
Аппаратное обеспечение
Может ли мое приложение получить доступ к микрофону?
Если приложение предназначено для Android 10 (уровень API 29) или более поздней версии, ознакомьтесь с документацией по совместному использованию аудиовхода. Это невозможно сделать в API уровня ниже 29.
К каким автомобильным API можно получить доступ и как это сделать?
Вы ограничены API, которые предоставляет OEM. Сейчас разрабатываются процессы, которые позволят стандартизировать доступ к этим API.
Приложения могут получать доступ к API автомобиля с помощью SetProperty() и GetProperty() в CarPropertyManager.
Список всех доступных свойств можно найти в исходном коде или справочной документации. Если свойство аннотировано с помощью @SystemApi, оно ограничено предустановленными системными приложениями.
Какие аудиокодеки поддерживаются?
Подробные сведения об аудиокодеках приведены в документе определения совместимости Android.
Поддерживается ли технология DRM Widevine?
Да. Поддерживается Widevine DRM.
Разработка и тестирование
Есть ли ограничения или рекомендации по использованию сторонних SDK и библиотек?
У нас нет специальных рекомендаций по использованию сторонних SDK и библиотек. Если вы решите использовать сторонние SDK и библиотеки, вы по-прежнему будете нести ответственность за соблюдение всех требований к качеству приложений для автомобилей.
Можно ли использовать активную службу?
Единственный допустимый сценарий использования активной службы – скачивание контента для офлайн-доступа. Если вы хотите, чтобы мы добавили поддержку других сценариев использования активных служб, напишите нам в группе обсуждения Android Automotive OS.
Публикация приложений для Android Automotive OS
Как опубликовать приложение для Android Automotive OS в Google Play Console?
Подробную информацию о том, как опубликовать приложение для Android Automotive OS с помощью Google Play Console, можно найти в статье Распространение приложений для автомобилей.
Дополнительные ресурсы
Дополнительную информацию об Android Automotive OS можно найти в следующих ресурсах:
Образцы
Руководства
- Дизайн автомобильных интерфейсов
- Как использовать тестовое приложение Media Controller
- Уведомления в Android Automotive OS
- Качество приложений Android для автомобилей
Блоги
Видео
- Как создавать мультимедийные приложения для автомобилей (Саммит для разработчиков Android '19)
- Как создавать приложения Android для автомобилей (Google I/O 2019)
Как сообщить о проблеме с мультимедиа в Android Automotive OS
Если при разработке мультимедийного приложения для Android Automotive OS у вас возникнут проблемы, сообщите о них с помощью системы отслеживания ошибок Google. Обязательно укажите всю необходимую информацию в шаблоне.
Прежде чем отправить запрос, проверьте список существующих вопросов. Чтобы подписаться на проблему и проголосовать за нее, нажмите на звездочку рядом с ней. Подробнее о том, как подписаться на проблему…