Добавьте поддержку Android Automotive OS в свое мультимедийное приложение.

Операционная система Android Automotive позволяет пользователям устанавливать приложения в автомобиль. Для распространения приложений на этой платформе необходимо использовать оптимизированное для драйверов приложение, совместимое с Android Automotive OS. Вы можете повторно использовать практически весь код и ресурсы вашего приложения Android Auto, но необходимо создать отдельную сборку, отвечающую требованиям, указанным на этой странице.

Обзор разработки

Для добавления поддержки Android Automotive OS достаточно выполнить всего несколько шагов, описанных в следующих разделах:

  1. Включите автомобильные функции в Android Studio .
  2. Создайте автомобильный модуль .
  3. Обновите зависимости Gradle .
  4. При желании можно реализовать настройки и действия по входу в систему .
  5. При желании можно прочитать подсказки хоста мультимедиа .

Вопросы проектирования

Android Automotive OS берет на себя размещение медиаконтента, получаемого от службы просмотра мультимедиа вашего приложения. Это означает, что ваше приложение не отрисовывает пользовательский интерфейс и не запускает никаких действий, когда пользователь инициирует воспроизведение мультимедиа.

Если вы внедряете настройки или вход в систему , эти действия должны быть оптимизированы для вашего автомобиля . При проектировании этих разделов приложения руководствуйтесь рекомендациями по дизайну для Android Automotive OS.

Настройте свой проект

Для включения поддержки Android Automotive OS необходимо настроить несколько частей проекта вашего приложения.

Включите автомобильные функции в Android Studio

Для включения всех функций Automotive OS используйте Android Studio 4.0 или более позднюю версию.

Создайте автомобильный модуль.

Некоторые компоненты Android Automotive OS, такие как манифест, имеют специфические для платформы требования. Создайте модуль, который позволит отделить код этих компонентов от остального кода в вашем проекте, например, от кода, используемого для вашего мобильного приложения.

Чтобы добавить автомобильный модуль в свой проект, выполните следующие действия:

  1. В Android Studio нажмите Файл > Создать > Новый модуль .
  2. Выберите «Автомобильный модуль» , затем нажмите «Далее» .
  3. Введите название приложения/библиотеки . Это название, которое пользователи будут видеть для вашего приложения в операционной системе Android Automotive.
  4. Введите название модуля .
  5. Измените имя пакета в соответствии с вашим приложением.
  6. Выберите API 28: Android 9.0 (Pie) в качестве минимального набора SDK , а затем нажмите «Далее» .

    Все автомобили, поддерживающие ОС Android Automotive, работают на Android 9 (уровень API 28) или выше, поэтому выбор этого значения будет применяться ко всем совместимым автомобилям.

  7. Выберите «Без действий» , а затем нажмите «Готово» .

После создания модуля в Android Studio откройте файл AndroidManifest.xml в вашем новом модуле Automotive:

<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:

<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 использует явные интенты для запуска действий в вашем медиаприложении. Не включайте в файл манифеста действия, имеющие фильтры интентов CATEGORY_LAUNCHER или ACTION_MAIN .

Действия, подобные приведенному ниже примеру, обычно нацелены на телефон или другое мобильное устройство. Объявляйте эти действия в модуле, который собирает приложение для телефона, а не в модуле, который собирает ваше приложение для 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')
    }
}

Котлин

buildscript {
    ...
    dependencies {
        ...
        implementation(project(":shared_module_name"))
    }
}

Реализуйте настройки и действия по входу в систему.

В дополнение к службе просмотра мультимедиа, вы также можете предоставлять оптимизированные для автомобиля настройки и действия входа в систему для вашего приложения Android Automotive OS. Эти действия позволяют предоставлять функциональность приложения, которая не включена в API Android Media.

Внедряйте эти действия только в том случае, если вашему приложению для Android Auto OS необходимо разрешить пользователям входить в систему или указывать настройки приложения. Эти действия не используются Android Auto.

Рабочие процессы выполнения задач

На следующей диаграмме показано, как пользователь взаимодействует с вашими настройками и действиями при входе в систему, используя операционную систему Android Automotive:

Рабочие процессы для настроек и входа в систему.

Рисунок 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 , который сообщает вашему приложению о необходимости запустить действие настроек.

В оставшейся части этого раздела показано, как можно адаптировать код из примера приложения Universal Android Music Player (UAMP) для реализации активности настроек в вашем приложении.

Для начала скачайте пример кода:

# Clone the UAMP repository
git clone https://github.com/android/uamp.git

# Fetch the appropriate pull request to your local repository
git fetch origin pull/323/head:NEW_LOCAL_BRANCH_NAME

# Switch to the new branch
git checkout NEW_LOCAL_BRANCH_NAME

Для реализации вашей инициативы выполните следующие шаги:

  1. Скопируйте папку automotive/automotive-lib в ваш модуль automotive.
  2. Определите дерево настроек, как в файле automotive/src/main/res/xml/preferences.xml .
  3. Реализуйте PreferenceFragmentCompat , который будет отображаться в вашем окне настроек. Дополнительную информацию см. в файлах SettingsFragment.kt и SettingsActivity.kt в UAMP и в руководстве по настройкам Android .

При настройке параметров учитывайте следующие рекомендации по использованию некоторых компонентов библиотеки настроек:

  • В настройках вашего приложения глубина не должна превышать двух уровней ниже основного окна.
  • Не используйте DropDownPreference . Вместо него используйте ListPreference .
  • Организационные компоненты:
    • PreferenceScreen
      • Это должен быть верхний уровень дерева ваших настроек.
    • PreferenceCategory
      • Используется для группировки объектов Preference .
      • Укажите title .
  • Включите в каждый из следующих компонентов key и title . Вы также можете добавить summary , icon или и то, и другое:
    • Preference
      • Настройте логику в функции обратного вызова onPreferenceTreeClick() вашей реализации PreferenceFragmentCompat .
    • CheckBoxPreference
      • Вместо summary для условного текста можно использовать summaryOn или summaryOff .
    • SwitchPreference
      • Вместо summary для условного текста можно использовать summaryOn или summaryOff .
      • Может иметь 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, его не используют.

Требовать входа в систему при запуске приложения

Чтобы пользователю требовалось авторизоваться перед использованием вашего приложения, служба просмотра мультимедиа должна выполнять следующие действия:

  1. В методе onLoadChildren() вашего сервиса отправьте результат null , используя метод sendResult() .
  2. Установите для параметра PlaybackStateCompat медиасессии значение STATE_ERROR с помощью метода setState() . Это сообщит операционной системе Android Automotive, что никакие другие операции не могут быть выполнены до устранения ошибки.
  3. Установите код ошибки PlaybackStateCompat для медиасессии в значение ERROR_CODE_AUTHENTICATION_EXPIRED . Это сообщит Android Automotive OS о необходимости аутентификации пользователя.
  4. Установите сообщение об ошибке PlaybackStateCompat для сеанса воспроизведения медиафайлов с помощью метода setErrorMessage() . Поскольку это сообщение об ошибке предназначено для пользователя, локализуйте его для текущей локали пользователя.
  5. Установите дополнительные параметры 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 .

Приведенный ниже фрагмент кода показывает, как ваше приложение может потребовать от пользователя авторизации перед использованием:

Котлин

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, предоставляют комплексные наборы инструментов, которые помогут вам создать персонализированные системы аутентификации. Другие инструменты используют существующие учетные данные пользователя или другие технологии, чтобы помочь вам создать бесперебойный процесс входа в систему для пользователей.

Следующие инструменты помогут вам упростить процесс входа в систему для пользователей, которые ранее входили в систему с другого устройства:

  • Вход и регистрация в один клик: если вы уже внедрили One Tap для других устройств, например, для своего мобильного приложения, внедрите его и для своего приложения Android Automotive OS, чтобы поддерживать существующих пользователей One Tap.
  • Вход через Google: если вы уже реализовали вход через 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 по следующим причинам:

  • Улучшенный пользовательский интерфейс и упрощенное управление учетными записями: пользователи могут управлять всеми своими учетными записями из меню «Учетные записи» в системных настройках, включая вход и выход из системы.
  • «Гостевые» возможности: автомобили — это устройства общего пользования, а это значит, что производители могут включать в автомобиле «гостевые» возможности, при которых добавление учетных записей невозможно. Это ограничение достигается с помощью DISALLOW_MODIFY_ACCOUNTS для AccountManager .

Разрешения

Если вам необходимо запросить у пользователя разрешения, используйте тот же алгоритм действий, что и для аутентификации или настройки, представленный на диаграмме рабочих процессов действий в предыдущем разделе.

Запустите приложение для размещения медиафайлов.

Вы можете создавать интенты для открытия приложения-хостинга медиафайлов для доступа к вашему приложению или контенту внутри вашего приложения. Например:

  • Ваше приложение может отправлять уведомление с ожидающим запросом, которое позволит пользователю открыть приложение, чтобы прослушать новый контент.
  • Ваше приложение может обрабатывать прямые ссылки и открывать основное приложение в наиболее подходящем для него режиме просмотра.

Определите возможности медиахоста.

Различные версии приложения для управления медиафайлами поддерживают разные возможности. Поддержка различных возможностей указывается путем включения фильтров намерений для следующих действий намерений:

Все приложения, использующие медиахостинг, поддерживают интенты 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 , выполнит поиск по запросу "Jazz", а затем воспроизведет первый элемент из результатов поиска. На всех остальных хостах он просто откроет приложение медиахостинга и выполнит поиск по запросу "Jazz", предоставив пользователю возможность выбрать элемент для воспроизведения из результатов.

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-адреса, отправленного с телефона с помощью функции Quick Share .

Добавить фильтры намерений для прямых ссылок

Чтобы сообщить операционной системе, что ваше приложение способно обрабатывать прямые ссылки, ему необходимы действия с соответствующими фильтрами намерений. См. раздел «Добавление фильтров намерений для входящих ссылок» для получения рекомендаций по формату фильтров намерений, используемых для прямых ссылок.

Для обеспечения наилучшего пользовательского опыта поддерживайте все доступные для вашего мобильного приложения прямые ссылки, если это возможно реализовать в вашем автомобильном приложении. Если ваше приложение содержит настройки или действия входа в систему , фильтры намерений для обработки прямых ссылок на настройки и вход в систему следует объявить в соответствующих элементах манифеста <activity> . Для воспроизведения мультимедиа и просмотра прямых ссылок можно использовать действие «трамплин», как описано далее в этом разделе.

См. раздел «Чтение данных из входящих интентов» для получения рекомендаций о том, как считывать и реагировать на интент, использованный для запуска активности вашего приложения.

Поскольку пользовательский интерфейс для просмотра и воспроизведения отрисовывается основным приложением, активность, используемая для обработки прямых ссылок для воспроизведения и просмотра, не должна иметь собственного пользовательского интерфейса.

Вместо этого его следует использовать в первую очередь для создания и использования Intent для запуска приложения, управляющего медиафайлами . При необходимости он также может обрабатывать любые дополнительные изменения состояния вашего приложения, такие как добавление медиафайлов в очередь. Следующий фрагмент кода демонстрирует пример реализации активности-трамплина:

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 удалите все коды ошибок и сообщения об ошибках, чтобы избежать отображения нескольких предупреждений для одной и той же ошибки.

Если в какой-либо момент вам не удаётся загрузить дерево просмотра — например, если требуется аутентификация, а пользователь не авторизован, — отправьте пустое дерево просмотра. Чтобы обозначить это, верните значение null из 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 будут иметь собственное подключение к интернету, то есть тарифный план на передачу данных будет включен в стоимость автомобиля или оплачиваться пользователем. Однако ожидается, что автомобили будут иметь более вариативный набор параметров подключения, чем мобильные устройства.

Вот несколько моментов, которые следует учитывать при разработке стратегии офлайн-поддержки:

  • Лучшее время для загрузки контента — это когда приложение используется.
  • Не стоит предполагать, что Wi-Fi доступен. Автомобиль может никогда не попасть в зону действия Wi-Fi, или производитель мог отключить Wi-Fi в пользу мобильной сети.
  • Хотя кэширование контента, который, как вы ожидаете, будут использовать пользователи, допустимо, мы рекомендуем предоставить пользователю возможность изменить это поведение через настройки.
  • Объем дискового пространства в автомобилях может различаться, поэтому предоставьте пользователям возможность удалять контент, недоступный в автономном режиме, например, через опцию в настройках.

Поддержка WebView

В Android Automotive OS поддерживаются WebView, но они разрешены только для настроек и действий входа в систему. Действия, использующие WebView, должны иметь кнопки «закрыть» или «назад» вне WebView.

Вот несколько примеров допустимого использования WebViews:

  • Отображение вашей политики конфиденциальности, условий обслуживания или других юридических ссылок в разделе настроек.
  • Веб-ориентированный процесс авторизации.

При использовании WebView можно включить JavaScript .

Защитите свой WebView

Примите все возможные меры предосторожности, чтобы ваш WebView не стал точкой входа в интернет. В следующем фрагменте кода приведен пример того, как заблокировать WebView по URL-адресу, используемому в вызове loadUrl() , и предотвратить перенаправления. Мы настоятельно рекомендуем внедрять подобные меры защиты, когда это возможно, например, при отображении ссылок, связанных с юридической информацией.

Котлин

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 (APK) для Android Automotive OS, вы можете повторно использовать имя пакета из своего мобильного приложения или создать новое имя пакета. Если вы используете другое имя пакета, у вашего приложения будет две отдельные записи в Play Store. Если вы используете текущее имя пакета, у вашего приложения будет одна запись на обеих платформах.

Это преимущественно бизнес-решение. Например, если одна команда работает над мобильным приложением, а другая — над приложением для Android Automotive OS, то может быть целесообразно использовать отдельные имена пакетов и позволить каждой команде управлять своим собственным списком в Play Store. Разница в технических затратах на использование обоих подходов невелика.

В следующей таблице приведены некоторые другие ключевые различия между сохранением текущего имени пакета и использованием нового имени пакета:

Особенность То же название пакета Новое название пакета
Список магазинов Одинокий Несколько
Зеркальная установка Да: "быстрая переустановка приложения" во время работы мастера установки. Нет
Процесс проверки в Play Store Блокировка проверки: если проверка одного APK-файла не пройдена, другие APK-файлы, отправленные в рамках того же релиза, блокируются. Отдельные обзоры
Статистика, показатели и жизненно важные параметры В совокупности вы можете отфильтровать данные, относящиеся к конкретной автомобильной отрасли. Отдельный
Индексирование и ранжирование в поисковой выдаче Опираясь на текущее положение дел Перенос невозможен
Интеграция с другими приложениями Скорее всего, никаких изменений не потребуется, если предположить, что медиакод используется в обоих APK-файлах. Возможно, потребуется обновить соответствующее приложение, например, для воспроизведения URI с помощью Google Ассистента.

Часто задаваемые вопросы

В следующих разделах вы найдете ответы на часто задаваемые вопросы об операционной системе Android Automotive.

Аппаратное обеспечение

Может ли моё приложение получить доступ к микрофону?

Для приложений, ориентированных на Android 10 (уровень API 29) или выше, обратитесь к документации по совместному использованию аудиовхода . Это невозможно для версий API ниже 29.

К каким API для автомобилей мы можем получить доступ и как?

Вы ограничены API, предоставляемыми производителем оборудования. Разрабатываются процессы для стандартизации доступа к этим API.

Приложения могут получать доступ к API автомобилей, используя SetProperty() и GetProperty() в CarPropertyManager . Список всех доступных свойств можно найти в исходном коде или справочной документации . Если свойство аннотировано @SystemApi , доступ к нему ограничен предустановленными системными приложениями.

Какие типы аудиокодеков поддерживаются?

Подробную информацию об аудиокодеках см. на диске Android CDD.

Поддерживается ли DRM-защита Widevine?

Да. Поддерживается DRM-защита Widevine .

Разработка и тестирование

Существуют ли какие-либо ограничения или рекомендации по использованию сторонних SDK и библиотек?

У нас нет конкретных рекомендаций по использованию сторонних SDK и библиотек. Если вы решите использовать сторонние SDK и библиотеки, вы по-прежнему будете нести ответственность за соблюдение всех требований к качеству автомобильных приложений.

Могу ли я использовать службу переднего плана?

Единственный допустимый сценарий использования службы переднего плана — загрузка контента для использования в автономном режиме. Если у вас есть другой сценарий использования службы переднего плана, для которого вы хотели бы видеть поддержку, свяжитесь с нами через группу обсуждений Android Automotive OS .

Публикация приложений для Android Automotive OS

Как опубликовать приложение для Android Automotive OS с помощью Google Play Console?

Подробную информацию о том, как опубликовать приложение для Android Automotive OS с помощью консоли Google Play, см. в разделе «Распространение в автомобилях» .

Дополнительные ресурсы

Чтобы узнать больше об операционной системе Android Automotive OS, ознакомьтесь со следующими дополнительными ресурсами.

Образцы

Гиды

Блоги

Видео

Сообщить о проблеме с мультимедиа в Android Automotive OS

Если при разработке вашего медиаприложения для Android Automotive OS у вас возникнут проблемы, вы можете сообщить о них, используя систему отслеживания ошибок Google . Обязательно заполните всю необходимую информацию в шаблоне сообщения об ошибке.

Создать новую задачу

Перед созданием новой темы проверьте, не была ли она уже зарегистрирована в списке тем. Вы можете подписаться на темы и голосовать за них, нажав на звездочку рядом с темой в трекере. Для получения дополнительной информации см. раздел «Подписка на тему» .