Пользовательский интерфейс представлен графом объектов модели, которые могут быть организованы вместе различными способами, как это разрешено шаблоном, к которому они принадлежат. Шаблоны — это подмножество моделей, которые могут выступать в качестве корня в этих графах. Модели включают информацию, которая должна отображаться пользователю в виде текста и изображений, а также атрибуты для настройки аспектов визуального представления такой информации, например, цвета текста или размеры изображений. Хост преобразует модели в представления, которые разработаны для соответствия стандартам отвлечения внимания водителя, и заботится о таких деталях, как различные факторы экрана автомобиля и модальности ввода.
Хозяин
Хост — это внутренний компонент, который реализует функциональность, предлагаемую API библиотеки, чтобы ваше приложение могло работать в автомобиле. Обязанности хоста варьируются от обнаружения вашего приложения и управления его жизненным циклом до преобразования ваших моделей в представления и уведомления вашего приложения о взаимодействиях с пользователем. На мобильных устройствах этот хост реализуется Android Auto. В Android Automotive OS этот хост устанавливается как системное приложение.
Ограничения шаблона
Различные шаблоны накладывают ограничения на содержание своих моделей. Например, шаблоны списков имеют ограничения на количество элементов, которые могут быть представлены пользователю. Шаблоны также имеют ограничения на способ их соединения для формирования потока задачи. Например, приложение может вывести на экранный стек не более пяти шаблонов. Подробнее см. в разделе Ограничения шаблонов .
Screen
Screen — это класс, предоставляемый библиотекой, который приложения реализуют для управления пользовательским интерфейсом, представленным пользователю. Screen имеет жизненный цикл и предоставляет механизм для отправки шаблона для отображения, когда экран виден. Экземпляры Screen также могут быть помещены в стек Screen и извлечены из него, что гарантирует их соответствие ограничениям потока шаблонов .
CarAppService
CarAppService — это абстрактный класс Service , который ваше приложение должно реализовать и экспортировать, чтобы хост мог его обнаружить и управлять им. CarAppService вашего приложения отвечает за проверку того, что хост-подключение может быть доверенным, с помощью createHostValidator и за последующее предоставление экземпляров Session для каждого подключения с помощью onCreateSession .
Session
Session — это абстрактный класс, который ваше приложение должно реализовать и вернуть с помощью CarAppService.onCreateSession . Он служит точкой входа для отображения информации на экране автомобиля. Он имеет жизненный цикл , который информирует о текущем состоянии вашего приложения на экране автомобиля, например, когда ваше приложение видимо или скрыто.
При запуске Session , например при первом запуске приложения, хост запрашивает отображение начального Screen с помощью метода onCreateScreen .
Установите библиотеку автомобильных приложений
Инструкции по добавлению библиотеки в приложение см. на странице выпуска библиотеки Jetpack.
Настройте файлы манифеста вашего приложения
Прежде чем создать автомобильное приложение, настройте файлы манифеста вашего приложения следующим образом.
Заявите о своем CarAppService
Хост подключается к вашему приложению через реализацию CarAppService . Вы объявляете эту службу в своем манифесте, чтобы хост мог обнаружить и подключиться к вашему приложению.
Вам также необходимо объявить категорию вашего приложения в элементе <category> фильтра намерений вашего приложения. Ознакомьтесь со списком поддерживаемых категорий приложений для значений, разрешенных для этого элемента.
В следующем фрагменте кода показано, как объявить службу автомобильного приложения для приложения точки интереса в вашем манифесте:
Объявите категорию своего приложения, добавив одно или несколько из следующих значений категории в фильтр намерений при объявлении CarAppService , как описано в предыдущем разделе :
androidx.car.app.category.POI : приложение, которое предоставляет функциональность, относящуюся к поиску точек интереса, таких как парковочные места, зарядные станции и заправочные станции. См. Создание приложений точек интереса для автомобилей .
androidx.car.app.category.IOT : приложение, которое позволяет пользователям выполнять соответствующие действия на подключенных устройствах из автомобиля. См. Создание приложений Интернета вещей для автомобилей .
androidx.car.app.category.WEATHER : приложение, которое позволяет пользователям видеть соответствующую информацию о погоде, связанную с их текущим местоположением или по маршруту. См. Создание погодных приложений для автомобилей .
androidx.car.app.category.MEDIA : Медиа-приложения позволяют пользователям просматривать и воспроизводить музыку, радио, аудиокниги и другой аудиоконтент в автомобиле. См. Создание шаблонных медиа-приложений для автомобилей .
Вам необходимо указать имя приложения и значок, которые хост сможет использовать для представления вашего приложения в пользовательском интерфейсе системы.
Вы можете указать имя приложения и значок, которые будут использоваться для представления вашего приложения, используя атрибуты label и icon вашего CarAppService :
Библиотека приложений для автомобилей определяет собственные уровни API, чтобы вы могли узнать, какие функции библиотеки поддерживаются хостом шаблона на транспортном средстве. Чтобы получить наивысший уровень API приложений для автомобилей, поддерживаемый хостом, используйте метод getCarAppApiLevel() .
Укажите минимальный уровень API приложения для автомобиля, поддерживаемый вашим приложением, в файле AndroidManifest.xml :
Подробную информацию о том, как поддерживать обратную совместимость и объявлять минимальный уровень API, необходимый для использования функции, см. в документации по аннотации RequiresCarApi Определение того, какой уровень API требуется для использования определенной функции Car App Library, см. в справочной документации по CarAppApiLevels .
Создайте свой CarAppService и сеанс
Вашему приложению необходимо расширить класс CarAppService и реализовать его метод onCreateSession , который возвращает экземпляр Session , соответствующий текущему подключению к хосту:
Для обработки сценариев, в которых ваше автомобильное приложение должно запускаться с экрана, который не является домашним или целевым экраном вашего приложения, например, для обработки глубоких ссылок, вы можете предварительно заполнить стек экранов с помощью ScreenManager.push перед возвратом из onCreateScreen . Предварительное заполнение позволяет пользователям переходить к предыдущим экранам с первого экрана, который показывает ваше приложение.
Создайте свой стартовый экран
Вы создаете экраны, отображаемые вашим приложением, определяя классы, расширяющие класс Screen , и реализуя его метод onGetTemplate , который возвращает экземпляр Template , представляющий состояние пользовательского интерфейса для отображения на экране автомобиля.
В следующем фрагменте показано, как объявить Screen , использующий шаблон PaneTemplate для отображения простой строки «Hello world!»:
Полный список функций библиотеки, доступных для навигационных приложений, см. в разделе Доступ к шаблонам навигации .
CarContext также предлагает другие функции, такие как возможность загрузки ресурсов с помощью конфигурации с экрана автомобиля, запуск приложения в автомобиле с использованием намерений и указание того, должно ли ваше приложение отображать свою карту в темной теме .
Реализовать экранную навигацию
Приложения часто представляют собой несколько различных экранов, каждый из которых может использовать различные шаблоны, по которым пользователь может перемещаться, взаимодействуя с интерфейсом, отображаемым на экране.
Класс ScreenManager предоставляет стек экранов, который можно использовать для выдвижения экранов, которые могут автоматически выдвигаться, когда пользователь выбирает кнопку «Назад» на экране автомобиля или использует аппаратную кнопку «Назад», имеющуюся в некоторых автомобилях.
В следующем фрагменте показано, как добавить действие «Назад» в шаблон сообщения, а также действие, которое открывает новый экран при выборе пользователем:
Чтобы обеспечить безопасность использования приложения во время вождения, стек экранов может иметь максимальную глубину в пять экранов. Подробнее см. в разделе Ограничения шаблонов .
Обновить содержимое шаблона
Ваше приложение может запросить аннулирование содержимого Screen , вызвав метод Screen.invalidate . Хост затем вызывает метод Screen.onGetTemplate вашего приложения, чтобы получить шаблон с новым содержимым.
При обновлении Screen важно понимать, какой конкретный контент в шаблоне может быть обновлен, чтобы хост не учитывал новый шаблон в квоте шаблонов. Подробнее см. в разделе Ограничения шаблонов .
Мы рекомендуем вам структурировать экраны таким образом, чтобы между Screen и типом шаблона, который он возвращает через реализацию onGetTemplate , существовало однозначное соответствие.
Рисовать карты
Приложения для навигации, точек интереса (POI) и погоды, использующие следующие шаблоны, могут рисовать карты, получая доступ к Surface .
Чтобы использовать следующие шаблоны, ваше приложение должно иметь одно из соответствующих разрешений, объявленных в элементе <uses-permission> в файле AndroidManifest.xml .
Помимо разрешения, необходимого для шаблона, который использует ваше приложение, ваше приложение должно объявить разрешение androidx.car.app.ACCESS_SURFACE в своем файле AndroidManifest.xml , чтобы получить доступ к поверхности:
Чтобы получить доступ к Surface , который предоставляет хост, необходимо реализовать SurfaceCallback и предоставить эту реализацию службе AppManager car. Текущая Surface передается в ваш SurfaceCallback в параметре SurfaceContainer обратных вызовов onSurfaceAvailable() и onSurfaceDestroyed() .
Хост может рисовать элементы пользовательского интерфейса для шаблонов поверх карты. Хост сообщает область поверхности, которая гарантированно будет свободна и полностью видна пользователю, вызывая метод SurfaceCallback.onVisibleAreaChanged . Также, чтобы минимизировать количество изменений, хост вызывает метод SurfaceCallback.onStableAreaChanged с наименьшим прямоугольником, который всегда виден на основе текущего шаблона.
Например, когда навигационное приложение использует NavigationTemplate с полосой действий сверху, полоса действий может скрыть себя, когда пользователь некоторое время не взаимодействовал с экраном, чтобы освободить больше места для карты. В этом случае есть обратный вызов onStableAreaChanged и onVisibleAreaChanged с тем же прямоугольником. Когда полоса действий скрыта, вызывается только onVisibleAreaChanged с большей областью. Если пользователь взаимодействует с экраном, то снова вызывается только onVisibleAreaChanged с первым прямоугольником.
Поддержка темной темы
Приложения должны перерисовывать свою карту на экземпляре Surface с использованием соответствующих темных цветов, когда хост определяет, что условия требуют этого, как описано в разделе Качество приложений Android для автомобилей .
Позвольте пользователям взаимодействовать с вашей картой
Используя следующие шаблоны, вы можете добавить поддержку взаимодействия пользователей с нарисованными вами картами, например, позволяя им видеть различные части карты с помощью масштабирования и панорамирования.
Шаблон
Интерактивность поддерживается начиная с уровня API приложения для автомобиля
NavigationTemplate
2
PlaceListNavigationTemplate ( устарело )
4
RoutePreviewNavigationTemplate ( устарело )
4
MapTemplate ( устарело )
5 (введение шаблона)
MapWithContentTemplate
7 (введение шаблона)
Реализуйте интерактивные обратные вызовы
Интерфейс SurfaceCallback имеет несколько методов обратного вызова, которые можно реализовать для добавления интерактивности к картам, созданным с использованием шаблонов из предыдущего раздела:
onScale (с коэффициентом масштабирования, определяемым хостом шаблона)
2
Вращательное движение в режиме панорамирования
onScroll (с коэффициентом расстояния, определяемым хостом шаблона)
2
Добавить полосу действий карты
Эти шаблоны могут иметь полосу действий карты для действий, связанных с картой, таких как увеличение и уменьшение масштаба, центрирование, отображение компаса и других действий, которые вы выбираете для отображения. Полоса действий карты может иметь до четырех кнопок только со значками, которые можно обновлять, не влияя на глубину задачи. Она скрывается в состоянии бездействия и снова появляется в активном состоянии.
Чтобы получать обратные вызовы интерактивности карты, необходимо добавить кнопку Action.PAN в полосу действий карты. Когда пользователь нажимает кнопку панорамирования, хост переходит в режим панорамирования, как описано в следующем разделе.
Если в вашем приложении отсутствует кнопка Action.PAN на полосе действий карты, оно не получает пользовательский ввод от методов SurfaceCallback , а хост выходит из любого ранее активированного режима панорамирования.
На сенсорном экране кнопка панорамирования не отображается.
Понять режим панорамирования
В режиме панорамирования хост шаблона преобразует пользовательский ввод с несенсорных устройств ввода, таких как поворотные контроллеры и сенсорные панели, в соответствующие методы SurfaceCallback . Отвечайте на действие пользователя для входа или выхода из режима панорамирования с помощью метода setPanModeListener в NavigationTemplate.Builder . Хост может скрыть другие компоненты пользовательского интерфейса в шаблоне, пока пользователь находится в режиме панорамирования.
Взаимодействие с пользователем
Ваше приложение может взаимодействовать с пользователем, используя шаблоны, аналогичные мобильным приложениям.
Обработка пользовательского ввода
Ваше приложение может реагировать на пользовательский ввод, передавая соответствующие прослушиватели моделям, которые их поддерживают. В следующем фрагменте показано, как создать модель Action , которая устанавливает OnClickListener , который вызывает метод, определенный кодом вашего приложения:
Некоторые действия, например те, которые требуют направления пользователя для продолжения взаимодействия на его мобильных устройствах, разрешены только когда автомобиль припаркован. Вы можете использовать ParkedOnlyOnClickListener для реализации этих действий. Если автомобиль не припаркован, хост отображает пользователю указание, что действие в этом случае не разрешено. Если автомобиль припаркован, код выполняется нормально. В следующем фрагменте показано, как использовать ParkedOnlyOnClickListener для открытия экрана настроек на мобильном устройстве:
Уведомления, отправленные на мобильное устройство, отображаются на экране автомобиля, только если они расширены с помощью CarAppExtender . Некоторые атрибуты уведомления, такие как заголовок контента, текст, значок и действия, можно задать в CarAppExtender , переопределяя атрибуты уведомления при их появлении на экране автомобиля.
В следующем фрагменте показано, как отправить уведомление на экран автомобиля, на котором отображается заголовок, отличный от того, который отображается на мобильном устройстве:
Уведомления могут влиять на следующие части пользовательского интерфейса:
Пользователю может быть показано уведомление (HUN).
Можно добавить запись в центре уведомлений, при желании можно разместить значок на панели.
Для навигационных приложений уведомление может отображаться в виджете железнодорожного транспорта, как описано в разделе Уведомления о поворотах .
Вы можете выбрать способ настройки уведомлений вашего приложения, чтобы они влияли на каждый из этих элементов пользовательского интерфейса, используя приоритет уведомлений, как описано в документации CarAppExtender .
Дополнительную информацию о том, как разработать уведомления для вашего автомобильного приложения, см. в руководстве Google Design for Driving по уведомлениям .
Показать тосты
Ваше приложение может отображать тост с помощью CarToast , как показано в этом фрагменте:
Преимущество использования CarContext.requestPermissions() , в отличие от использования стандартных API Android , заключается в том, что вам не нужно запускать собственную Activity для создания диалога разрешений. Более того, вы можете использовать один и тот же код как на Android Auto, так и на Android Automotive OS, вместо того, чтобы создавать потоки, зависящие от платформы.
Стиль диалогового окна разрешений в Android Auto
В Android Auto диалоговое окно разрешений для пользователя появится на телефоне. По умолчанию за диалоговым окном не будет фона. Чтобы задать пользовательский фон, объявите тему автомобильного приложения в файле AndroidManifest.xml и задайте атрибут carPermissionActivityLayout для темы автомобильного приложения.
В следующем примере показано, как создать уведомление с действием, которое открывает ваше приложение с экраном, на котором отображаются сведения о бронировании парковки. Вы расширяете экземпляр уведомления с намерением контента, которое содержит PendingIntent , оборачивающий явное намерение для действия вашего приложения:
Ваше приложение также должно объявить BroadcastReceiver , который вызывается для обработки намерения, когда пользователь выбирает действие в интерфейсе уведомлений и вызывает CarContext.startCarApp с намерением, включающим URI данных:
Наконец, метод Session.onNewIntent в вашем приложении обрабатывает это намерение, помещая экран бронирования парковки в стек, если он еще не находится наверху:
Дополнительную информацию о том, как обрабатывать уведомления для автомобильного приложения, см. в разделе Отображение уведомлений .
Ограничения шаблона
Хост ограничивает количество шаблонов, отображаемых для данной задачи, максимум пятью, из которых последний шаблон должен быть одного из следующих типов:
Обратите внимание, что это ограничение применяется к количеству шаблонов, а не к количеству экземпляров Screen в стеке. Например, если приложение отправляет два шаблона, находясь на экране A, а затем отправляет экран B, теперь оно может отправить еще три шаблона. В качестве альтернативы, если каждый экран структурирован для отправки одного шаблона, то приложение может отправить пять экземпляров screen в стек ScreenManager .
Существуют особые случаи этих ограничений: обновления шаблонов, а также операции возврата и сброса.
Шаблон обновляется
Некоторые обновления контента не учитываются в лимите шаблонов. В общем случае, если приложение отправляет новый шаблон того же типа и содержит тот же основной контент, что и предыдущий шаблон, новый шаблон не учитывается в квоте. Например, обновление состояния переключения строки в ListTemplate не учитывается в квоте. Ознакомьтесь с документацией по отдельным шаблонам, чтобы узнать больше о том, какие типы обновлений контента можно считать обновлением.
Операции по восстановлению
Чтобы включить подпотоки в задаче, хост определяет, когда приложение извлекает Screen из стека ScreenManager , и обновляет оставшуюся квоту на основе количества шаблонов, на которые приложение переходит в обратном направлении.
Например, если приложение отправляет два шаблона, находясь на экране A, затем выталкивает экран B и отправляет еще два шаблона, у приложения остается одна квота. Если приложение затем возвращается к экрану A, хост сбрасывает квоту до трех, поскольку приложение откатилось на два шаблона назад.
Обратите внимание, что при возврате на экран приложение должно отправить шаблон того же типа, что и последний отправленный этим экраном. Отправка любого другого типа шаблона приводит к ошибке. Однако, пока тип остается тем же во время операции возврата, приложение может свободно изменять содержимое шаблона, не влияя на квоту.
Сброс операций
Некоторые шаблоны имеют особую семантику, которая обозначает окончание задачи. Например, NavigationTemplate — это представление, которое, как ожидается, останется на экране и будет обновляться новыми пошаговыми инструкциями для потребления пользователем. Когда он достигает одного из этих шаблонов, хост сбрасывает квоту шаблона, рассматривая этот шаблон так, как будто это первый шаг новой задачи. Это позволяет приложению начать новую задачу. См. документацию отдельных шаблонов, чтобы узнать, какие из них вызывают сброс на хосте.
Если хост получает намерение запустить приложение из действия уведомления или из средства запуска, квота также сбрасывается. Этот механизм позволяет приложению начать новый поток задач из уведомлений, и он остается верным, даже если приложение уже привязано и находится на переднем плане.
Вы можете определить, работает ли ваше приложение на Android Auto или Android Automotive OS, используя API CarConnection для получения информации о подключении во время выполнения.
Например, в Session вашего автомобильного приложения инициализируйте CarConnection и подпишитесь на обновления LiveData :
В наблюдателе вы можете реагировать на изменения состояния соединения:
Котлин
funonConnectionStateUpdated(connectionState:Int){valmessage=when(connectionState){CarConnection.CONNECTION_TYPE_NOT_CONNECTED->"Not connected to a head unit"CarConnection.CONNECTION_TYPE_NATIVE->"Connected to Android Automotive OS"CarConnection.CONNECTION_TYPE_PROJECTION->"Connected to Android Auto"else->"Unknown car connection type"}CarToast.makeText(carContext,message,CarToast.LENGTH_SHORT).show()}
Ява
privatevoidonConnectionStateUpdated(intconnectionState){Stringmessage;switch(connectionState){caseCarConnection.CONNECTION_TYPE_NOT_CONNECTED:message="Not connected to a head unit";break;caseCarConnection.CONNECTION_TYPE_NATIVE:message="Connected to Android Automotive OS";break;caseCarConnection.CONNECTION_TYPE_PROJECTION:message="Connected to Android Auto";break;default:message="Unknown car connection type";break;}CarToast.makeText(getCarContext(),message,CarToast.LENGTH_SHORT).show();}
API ограничений
Различные автомобили могут позволять пользователю отображать разное количество экземпляров Item одновременно. Используйте ConstraintManager для проверки лимита содержимого во время выполнения и установки соответствующего количества элементов в шаблонах.
Начнем с получения ConstraintManager из CarContext :
Затем вы можете запросить извлеченный объект ConstraintManager для соответствующего ограничения контента. Например, чтобы получить количество элементов, которые могут быть отображены в сетке, вызовите getContentLimit с CONTENT_LIMIT_TYPE_GRID :
Если ваше приложение предлагает пользователям возможность входа в систему, вы можете использовать такие шаблоны, как SignInTemplate и LongMessageTemplate с API приложения для автомобилей уровня 2 и выше, чтобы обрабатывать вход в ваше приложение на головном устройстве автомобиля.
Чтобы создать SignInTemplate , определите SignInMethod . В настоящее время библиотека приложений Car App Library поддерживает следующие методы входа:
PinSignInMethod для входа с помощью PIN-кода, при котором пользователь привязывает свою учетную запись к телефону, используя PIN-код, отображаемый на головном устройстве.
QRCodeSignInMethod для входа с помощью QR-кода, где пользователь сканирует QR-код для завершения входа на своем телефоне. Это доступно с Car API уровня 4 и выше.
Например, чтобы реализовать шаблон, собирающий пароль пользователя, начните с создания InputCallback для обработки и проверки введенных пользователем данных:
Котлин
valcallback=object:InputCallback{overridefunonInputSubmitted(text:String){// You will receive this callback when the user presses Enter on the keyboard.}overridefunonInputTextChanged(text:String){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}}
Ява
InputCallbackcallback=newInputCallback(){@OverridepublicvoidonInputSubmitted(@NonNullStringtext){// You will receive this callback when the user presses Enter on the keyboard.}@OverridepublicvoidonInputTextChanged(@NonNullStringtext){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}};
Для InputSignInMethodBuilder требуется InputCallback .
Наконец, используйте новый InputSignInMethod для создания SignInTemplate .
Котлин
SignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build()
Ява
newSignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build();
Использовать AccountManager
Приложения Android Automotive OS, имеющие аутентификацию, должны использовать AccountManager по следующим причинам:
Улучшенный пользовательский интерфейс и простота управления учетными записями : пользователи могут легко управлять всеми своими учетными записями из меню учетных записей в настройках системы, включая вход и выход.
«Гостевой» опыт : поскольку автомобили являются устройствами общего пользования, производители оригинального оборудования могут предоставлять гостевой опыт в транспортном средстве, при котором невозможно добавлять учетные записи.
Добавить варианты текстовой строки
Различные размеры экрана автомобиля могут отображать разное количество текста. С Car App API уровня 2 и выше вы можете указать несколько вариантов текстовой строки, чтобы наилучшим образом соответствовать экрану. Чтобы узнать, где принимаются варианты текста, найдите шаблоны и компоненты, которые принимают CarText .
Добавьте строки в порядке от наиболее к наименее предпочтительному — например, от самой длинной к самой короткой. Хост выбирает строку подходящей длины в зависимости от количества свободного места на экране автомобиля.
Добавить встроенные CarIcons для строк
Вы можете добавлять значки в текст, чтобы улучшить визуальную привлекательность вашего приложения с помощью CarIconSpan . См. документацию по CarIconSpan.create для получения дополнительной информации о создании этих span-ов. См. Spantastic text style with Spans для обзора того, как работает text style with span-ы.
Котлин
valrating=SpannableString("Rating: 4.5 stars")rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.ALIGN_BASELINE),// The start index of the span (index of the character '4')8,// The end index of the span (index of the last 's' in "stars")16,Spanned.SPAN_INCLUSIVE_INCLUSIVE)valrow=Row.Builder()....addText(rating).build()
Ява
SpannableStringrating=newSpannableString("Rating: 4.5 stars");rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsnewCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.ALIGN_BASELINE),// The start index of the span (index of the character '4')8,// The end index of the span (index of the last 's' in "stars")16,Spanned.SPAN_INCLUSIVE_INCLUSIVE);Rowrow=newRow.Builder()....addText(rating).build();
API автомобильного оборудования
Начиная с уровня 3 API приложения автомобиля, библиотека приложений автомобиля содержит API, которые можно использовать для доступа к свойствам и датчикам автомобиля.
Требования
Чтобы использовать API с Android Auto, начните с добавления зависимости от androidx.car.app:app-projected в файл build.gradle для вашего модуля Android Auto. Для Android Automotive OS добавьте зависимость от androidx.car.app:app-automotive в файл build.gradle для вашего модуля Android Automotive OS.
Кроме того, в файле AndroidManifest.xml вам необходимо объявить соответствующие разрешения, необходимые для запроса данных автомобиля, которые вы хотите использовать. Обратите внимание, что эти разрешения также должны быть предоставлены вам пользователем. Вы можете использовать один и тот же код как на Android Auto, так и на Android Automotive OS, вместо того, чтобы создавать потоки, зависящие от платформы. Однако необходимые разрешения различаются.
CarInfo
В этой таблице описаны свойства, отображаемые API CarInfo , и разрешения, которые необходимо запросить для их использования:
Предупреждение: метод getOdometerMeters класса Mileage назван неверно и возвращает километры, а не метры.
Расстояние по одометру
com.google.android.gms.permission.CAR_MILEAGE
Эти данные недоступны в Android Automotive OS для приложений, установленных из Play Store.
3
Например, чтобы получить оставшийся диапазон, создайте экземпляр объекта CarInfo , затем создайте и зарегистрируйте OnCarDataAvailableListener :
Котлин
valcarInfo=carContext.getCarService(CarHardwareManager::class.java).carInfovallistener=OnCarDataAvailableListener<EnergyLevel>{data->
if(data.rangeRemainingMeters.status==CarValue.STATUS_SUCCESS){valrangeRemaining=data.rangeRemainingMeters.value}else{// Handle error}}carInfo.addEnergyLevelListener(carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener)
Ява
CarInfocarInfo=getCarContext().getCarService(CarHardwareManager.class).getCarInfo();OnCarDataAvailableListener<EnergyLevel>listener=(data)->{if(data.getRangeRemainingMeters().getStatus()==CarValue.STATUS_SUCCESS){floatrangeRemaining=data.getRangeRemainingMeters().getValue();}else{// Handle error}};carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener);
Не думайте, что данные из автомобиля доступны в любое время. Если вы получили ошибку, проверьте статус запрошенного вами значения, чтобы лучше понять, почему запрошенные вами данные не могут быть получены. Обратитесь к справочной документации для полного определения класса CarInfo .
Датчики автомобиля
Класс CarSensors предоставляет вам доступ к акселерометру автомобиля, гироскопа, компаса и данных о местоположении. Доступность этих значений может зависеть от OEM. Формат для данных от акселерометра, гироскопа и компаса, такой же, как вы получите от API SensorManager . Например, чтобы проверить заголовок транспортного средства:
Котлин
valcarSensors=carContext.getCarService(CarHardwareManager::class.java).carSensorsvallistener=OnCarDataAvailableListener<Compass>{data->
if(data.orientations.status==CarValue.STATUS_SUCCESS){valorientation=data.orientations.value}else{// Data not available, handle error}}carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL,carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarSensors.removeCompassListener(listener)
Ява
CarSensorscarSensors=getCarContext().getCarService(CarHardwareManager.class).getCarSensors();OnCarDataAvailableListener<Compass>listener=(data)->{if(data.getOrientations().getStatus()==CarValue.STATUS_SUCCESS){List<Float>orientations=data.getOrientations().getValue();}else{// Data not available, handle error}};carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL,getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarSensors.removeCompassListener(listener);
Чтобы получить доступ к данным местоположения от автомобиля, вам также необходимо объявить и запросить разрешение android.permission.ACCESS_FINE_LOCATION .
Тестирование
Для моделирования данных датчика при тестировании на Android Auto см. В разделе «Датчики и конфигурацию датчиков» направляющего подразделения настольного настольного блока. Для моделирования данных датчика при тестировании на Android Automotive OS см. В разделе «Эмулятное оборудование» в Руководстве по эмулятору Android Automotive OS.
Жизненные циклы Carappservice, сеанса и экрана
Классы Session и Screen реализуют интерфейс LifecycleOwner . Когда пользователь взаимодействует с приложением, вызывает обратные вызовы на жизненный цикл вашего Session и Screen , как описано на следующих диаграммах.
Жизненные циклы караппервика и сеанс
Рисунок 1. Жизненный цикл Session .
Для получения полной информации см. Документацию для метода Session.getLifecycle .
Жизненный цикл экрана
Рисунок 2. Жизненный цикл Screen .
Для получения полной информации см. Документацию для метода Screen.getLifecycle .
Запись из автомобильного микрофона
Используя CarAppService вашего приложения и API CarAudioRecord , вы можете предоставить своему приложению доступ к автомобильному микрофону пользователя. Пользователи должны дать вашему приложению разрешение на доступ к автомобильному микрофону. Ваше приложение может записывать и обработать ввод пользователя в вашем приложении.
Разрешение на запись
Перед записи какого -либо аудио вы должны сначала объявить разрешение на запись в вашем AndroidManifest.xml и попросить пользователя его предоставили.
Вам нужно запросить разрешение на запись во время выполнения. См. Раздел «Разрешения на запрос» для получения подробной информации о том, как запросить разрешение в приложении вашего автомобиля.
Запись аудио
После того, как пользователь дает разрешение на запись, вы можете записать аудио и обработать запись.
Котлин
valcarAudioRecord=CarAudioRecord.create(carContext)carAudioRecord.startRecording()valdata=ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)while(carAudioRecord.read(data,0,CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)>=0){// Use data array// Potentially call carAudioRecord.stopRecording() if your processing finds end of speech}carAudioRecord.stopRecording()
Ява
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());carAudioRecord.startRecording();byte[]data=newbyte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE];while(carAudioRecord.read(data,0,CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)>=0){// Use data array// Potentially call carAudioRecord.stopRecording() if your processing finds end of speech}carAudioRecord.stopRecording();
Аудио фокус
При записи из автомобильного микрофона сначала приобретайте аудио фокусировку, чтобы гарантировать, что любые текущие носители будут остановлены. Если вы потеряете аудио фокусировку, прекратите запись.
Вот пример того, как приобрести аудио фокусировку:
Котлин
valcarAudioRecord=CarAudioRecord.create(carContext)// Take audio focus so that user's media is not recordedvalaudioAttributes=AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build()valaudioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener{state:Int->
if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording()}}.build()if(carContext.getSystemService(AudioManager::class.java).requestAudioFocus(audioFocusRequest)!=AudioManager.AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn}carAudioRecord.startRecording()// Process the audio and abandon the AudioFocusRequest when done
Ява
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());// Take audio focus so that user's media is not recordedAudioAttributesaudioAttributes=newAudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build();AudioFocusRequestaudioFocusRequest=newAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener(state->{if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording();}}).build();if(getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)!=AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn;}carAudioRecord.startRecording();// Process the audio and abandon the AudioFocusRequest when done
Тестовая библиотека
Библиотека тестирования Android для автомобилей предоставляет вспомогательные классы, которые вы можете использовать для проверки поведения вашего приложения в тестовой среде. Например, SessionController позволяет имитировать соединение с хостом и проверить, что правильный Screen и Template создаются и возвращаются.
Если вы найдете проблему с библиотекой, сообщите о ней, используя The Google Tracker . Обязательно заполните всю запрошенную информацию в шаблоне выпуска.
Перед подачей новой проблемы, пожалуйста, проверьте, указано ли он в записях библиотеки или сообщена в списке проблем. Вы можете подписаться и проголосовать за проблемы, щелкнув Star за проблему в трекере. Для получения дополнительной информации см. Подписку на проблему .
Контент и образцы кода на этой странице предоставлены по лицензиям. Java и OpenJDK – это зарегистрированные товарные знаки корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2025-05-22 UTC.
[[["Прост для понимания","easyToUnderstand","thumb-up"],["Помог мне решить мою проблему","solvedMyProblem","thumb-up"],["Другое","otherUp","thumb-up"]],[["Отсутствует нужная мне информация","missingTheInformationINeed","thumb-down"],["Слишком сложен/слишком много шагов","tooComplicatedTooManySteps","thumb-down"],["Устарел","outOfDate","thumb-down"],["Проблема с переводом текста","translationIssue","thumb-down"],["Проблемы образцов/кода","samplesCodeIssue","thumb-down"],["Другое","otherDown","thumb-down"]],["Последнее обновление: 2025-05-22 UTC."],[],[]]