Дополненная реальность для аудио- и видеоочков создается на основе существующего Activity API фреймворка Android и включает дополнительные концепции, необходимые для поддержки уникальных особенностей этих устройств. В отличие от шлемов XR, которые запускают APK-файл на устройстве, аудиоочки и очки с дисплеем используют специальное действие, выполняемое в существующем приложении на телефоне. Это действие проецируется с основного устройства на очки.
Чтобы создать приложение для аудио- и видеоочков, расширьте существующее приложение для телефона, добавив в него новый проецируемый Activity. Это действие является основной точкой входа для запуска приложения на очках. Такой подход упрощает разработку, поскольку позволяет использовать одну и ту же бизнес-логику в приложениях для телефона и очков.
Совместимость с версиями
Проверьте требования к совместимости Android SDK для Jetpack XR SDK.
Связанные запросы
Добавьте следующие зависимости библиотеки для аудиоочков и очков с дисплеем:
Яркий
dependencies {
implementation "androidx.xr.runtime:runtime:1.1.0-alpha01"
implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha18"
implementation "androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha18"
implementation "androidx.xr.projected:projected:1.0.0-alpha09"
implementation "androidx.xr.arcore:arcore:1.0.0-beta02"
}
Kotlin
dependencies {
implementation("androidx.xr.runtime:runtime:1.1.0-alpha01")
implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha18")
implementation("androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha18")
implementation("androidx.xr.projected:projected:1.0.0-alpha09")
implementation("androidx.xr.arcore:arcore:1.0.0-beta02")
}
Объявите действие в манифесте приложения
Как и в случае с другими типами действий, вам нужно объявить свое действие в файле манифеста приложения, чтобы система могла его обнаружить и запустить.
<application>
<activity
android:name="com.example.xr.projected.ProjectedMainActivity"
android:exported="true"
android:requiredDisplayCategory="android.hardware.display.category.XR_PROJECTED"
android:label="Example activity for audio glasses and display glasses">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.XR_PROJECTED_LAUNCHER"/>
</intent-filter>
</activity>
</application>
Ключевые моменты
- Указывает значение
android.hardware.display.category.XR_PROJECTEDдля атрибутаandroid:requiredDisplayCategory, чтобы сообщить системе, что это спроецированное действие, которое можно проецировать на аудио- и видеоочки. android.intent.action.MAINзадает это действие как действие запуска по умолчанию.android.intent.category.XR_PROJECTED_LAUNCHER– это специальная категория, которая позволяет Gemini находить запланированные вами действия с помощью голосовых команд.Когда пользователь произносит голосовую команду с названием приложения (например, "Открыть образец каталога ИИ", "Запустить образец каталога ИИ" или "Начать работу с образцом каталога ИИ"), система использует эту категорию, чтобы найти и запустить нужное действие на аудио- или видеоочках.
Как создать действие
Затем вы создадите небольшое приложение, которое будет показывать что-либо на экране ИИ-очков при его включении.
@OptIn(ExperimentalProjectedApi::class) class ProjectedMainActivity : ComponentActivity() { private var displayController: ProjectedDisplayController? = null private var isVisualUiSupported by mutableStateOf(false) private var areVisualsOn by mutableStateOf(true) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { displayController?.close() displayController = null } }) initializeGlassesFeatures() setContent { GlimmerTheme { HomeScreen( areVisualsOn = areVisualsOn, isVisualUiSupported = isVisualUiSupported, onClose = { finish() } ) } } } private fun initializeGlassesFeatures() { lifecycleScope.launch { // Check device capabilities val projectedDeviceController = ProjectedDeviceController.create(this@ProjectedMainActivity) isVisualUiSupported = projectedDeviceController.capabilities.contains(CAPABILITY_VISUAL_UI) val controller = ProjectedDisplayController.create(this@ProjectedMainActivity) displayController = controller val observer = GlassesLifecycleObserver( context = this@ProjectedMainActivity, controller = controller, onVisualsChanged = { visualsOn -> areVisualsOn = visualsOn } ) lifecycle.addObserver(observer) } } }
Ключевые моменты
- Включает использование API с запросом согласия из библиотеки Jetpack Projected.
ProjectedMainActivityрасширяетComponentActivity, как и ожидается при разработке для мобильных устройств.- Поскольку не все очки оснащены дисплеем, с помощью
ProjectedDeviceControllerпроверяется, есть ли он у устройства. - Блок
setContentв функцииonCreateопределяет корень дерева Composable UI для действия. Вы реализуетеHomeScreencomposable-функцию с помощью Jetpack Compose Glimmer. - Инициализирует интерфейс во время выполнения метода
onCreateобъекта activity (см. прогнозируемый жизненный цикл объекта activity). - Чтобы подготовиться к использованию функций, связанных с камерой, которые получают доступ к оборудованию очков, запросите разрешения на доступ к оборудованию, зарегистрировав средство запуска разрешений, определив функции
hasCameraPermissionиrequestHardwarePermissionsи проверив, были ли предоставлены разрешения, прежде чем вызывать функциюinitializeGlassesFeatures.
Как реализовать composable-функцию
Созданное вами действие ссылается на HomeScreen composable-функцию, которую вам нужно реализовать. В следующем коде используется Jetpack Compose Glimmer, чтобы определить composable-функцию, которая может отображать текст на дисплее очков:
@Composable fun HomeScreen( areVisualsOn: Boolean, isVisualUiSupported: Boolean, onClose: () -> Unit, modifier: Modifier = Modifier ) { Box( modifier = modifier .surface() .focusable(false) .fillMaxSize(), contentAlignment = Alignment.Center ) { if (isVisualUiSupported) { ActionCard( title = { Text("Android XR") }, action = { Button(onClick = onClose) { Text("Close") } } ) { if (areVisualsOn) { Text("Hello, Display Glasses!") } else { Text("Display is off. Audio guidance active.") } } } else { Text("Audio Guidance Mode Active") } } }
Ключевые моменты
- Как вы определили ранее, функция
HomeScreenвключает контент, который пользователь видит на экране очков. - Компонент Glimmer
Textиз библиотеки Jetpack Compose отображает на экране очков текст "Hello, AI Glasses!" (Привет, ИИ-очки!). - Glimmer
Buttonдля Jetpack Compose закрывает окно, вызываяfinish()черезonCloseв проецируемом окне.
Проверьте, подключены ли аудиоочки или очки для дисплея
Чтобы определить, подключены ли аудио- или видеоочки пользователя к его телефону, прежде чем запускать действие, используйте метод ProjectedContext.isProjectedDeviceConnected. Этот метод возвращает Flow<Boolean>, за которым ваше приложение может наблюдать, чтобы получать обновления статуса подключения в реальном времени.
Как начать тренировку
Теперь, когда вы создали основное действие, вы можете запустить его на очках. Чтобы получить доступ к аппаратной части очков, ваше приложение должно запускать операцию с определенными параметрами, которые указывают системе использовать проецируемый контекст, как показано в следующем коде:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, ProjectedMainActivity::class.java) context.startActivity(intent, options.toBundle())
Метод createProjectedActivityOptions в ProjectedContext создает необходимые параметры для запуска объекта activity в контексте проекции.
Параметр context может представлять собой контекст с телефона или устройства Glass.
Дальнейшие действия
Теперь, когда вы создали первое действие для аудиоочков и дисплейных очков, изучите другие способы расширения его функциональности:
- Как управлять выводом аудио с помощью функции "Синтез речи"
- Как обрабатывать аудиовход с помощью автоматического распознавания речи
- Создание интерфейса с помощью Jetpack Compose Glimmer
- Доступ к оборудованию аудиоочков и видеоочков