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

Android Automotive OS позволяет пользователям устанавливать приложения в автомобиле. Чтобы охватить пользователей на этой платформе, вам необходимо распространить оптимизированное для водителя приложение, совместимое с 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

Используйте Android Studio 4.0 или более поздней версии, чтобы обеспечить включение всех функций автомобильной ОС.

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

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

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

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

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

  7. Выберите Нет активности , а затем нажмите Готово .

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

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

Ява

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 по следующим причинам:

  • Улучшенный пользовательский интерфейс и простота управления учетными записями: пользователи могут легко управлять всеми своими учетными записями из меню учетных записей в настройках системы, включая вход и выход.
  • «Гостевой» опыт: автомобили являются общими устройствами, что означает, что OEM-производители могут включить «гостевой» опыт в автомобиле, где нельзя добавлять учетные записи. Это ограничение достигается с помощью 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

Создайте и используйте намерение

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

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

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

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

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

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

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

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

Поддержка WebView

WebViews поддерживаются в Android Automotive OS, но разрешены только для ваших настроек и действий входа в систему. Действия, которые используют 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
}

Ява

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Да. 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, ознакомьтесь со следующими дополнительными ресурсами.

Образцы

Руководства

Блоги

Видео

Сообщить о проблеме с Android Automotive OS Media

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

Создать новый выпуск

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