Rozszerzone funkcje okularów z dźwiękiem i wyświetlaczem są oparte na
istniejącym interfejsie API frameworka Androida Activity i obejmują dodatkowe
koncepcje, które obsługują unikalne aspekty tych okularów. W przeciwieństwie do zestawów słuchawkowych XR, które uruchamiają pełny plik APK na urządzeniu, okulary z dźwiękiem i wyświetlaczem używają specjalnej aktywności, która działa w ramach istniejącej aplikacji na telefonie. Ta aktywność jest wyświetlana z urządzenia hosta na okulary.
Aby utworzyć aplikację na okulary audio i okulary z wyświetlaczem, rozszerz istniejącą aplikację na telefon, tworząc nową aktywność Activity. Ta aktywność służy jako główny punkt uruchamiania aplikacji na okularach. Takie podejście upraszcza proces tworzenia, ponieważ możesz udostępniać i ponownie wykorzystywać logikę biznesową między aplikacjami na telefon i okulary.
Zgodność wersji
Sprawdź wymagania dotyczące zgodności pakietu Android SDK z pakietem Jetpack XR SDK.
Zależności
Dodaj te zależności biblioteki dla okularów audio i okularów z wyświetlaczem:
Dynamiczny
dependencies {
implementation "androidx.xr.runtime:runtime:1.0.0-alpha15"
implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha13"
implementation "androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha13"
implementation "androidx.xr.projected:projected:1.0.0-alpha08"
implementation "androidx.xr.arcore:arcore:1.0.0-alpha14"
}
Kotlin
dependencies {
implementation("androidx.xr.runtime:runtime:1.0.0-alpha15")
implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha13")
implementation("androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha13")
implementation("androidx.xr.projected:projected:1.0.0-alpha08")
implementation("androidx.xr.arcore:arcore:1.0.0-alpha14")
}
Zadeklaruj aktywność w pliku manifestu aplikacji
Podobnie jak w przypadku innych typów aktywności, musisz zadeklarować aktywność w pliku manifestu aplikacji, aby system mógł ją zobaczyć i uruchomić.
<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>
Najważniejsze informacje o kodzie
- Określa
android.hardware.display.category.XR_PROJECTEDdla atrybutuandroid:requiredDisplayCategory, aby poinformować system, że jest to aktywność wyświetlana i może być wyświetlana na okularach z dźwiękiem i wyświetlaczem. android.intent.action.MAINustawia tę aktywność jako domyślną aktywność uruchamiania.android.intent.category.XR_PROJECTED_LAUNCHERto specjalna kategoria, która sprawia, że aktywność wyświetlana jest wykrywalna przez polecenia głosowe Gemini.Gdy użytkownik wyda polecenie głosowe, używając nazwy aplikacji (np. „Otwórz próbkę katalogu AI”, „Uruchom próbkę katalogu AI” lub „Uruchom próbkę katalogu AI”), system używa tej kategorii do zlokalizowania i uruchomienia wyznaczonej aktywności na okularach z wyświetlaczem.
Utwórz aktywność
Następnie utworzysz małą aktywność, która będzie mogła wyświetlać coś na okularach AI, gdy wyświetlacz jest włączony.
@OptIn(ExperimentalProjectedApi::class) class ProjectedMainActivity : ComponentActivity() { private var displayController: ProjectedDisplayController? = null private var isVisualUiSupported by mutableStateOf(false) private var areVisualsOn by mutableStateOf(true) private var isPermissionDenied by mutableStateOf(false) // Register the permissions launcher using the ProjectedPermissionsResultContract. private val requestPermissionLauncher: ActivityResultLauncher<List<ProjectedPermissionsRequestParams>> = registerForActivityResult(ProjectedPermissionsResultContract()) { results -> if (results[Manifest.permission.CAMERA] == true) { isPermissionDenied = false initializeGlassesFeatures() } else { // Handle permission denial. isPermissionDenied = true } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { displayController?.close() displayController = null } }) if (hasCameraPermission()) { initializeGlassesFeatures() } else { requestHardwarePermissions() } setContent { GlimmerTheme { HomeScreen( areVisualsOn = areVisualsOn, isVisualUiSupported = isVisualUiSupported, isPermissionDenied = isPermissionDenied, onRetryPermission = { requestHardwarePermissions() }, 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) } } private fun hasCameraPermission(): Boolean { return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED } private fun requestHardwarePermissions() { val params = ProjectedPermissionsRequestParams( permissions = listOf(Manifest.permission.CAMERA), rationale = "Camera access is required to overlay digital content on your physical environment." ) requestPermissionLauncher.launch(listOf(params)) } }
Najważniejsze informacje o kodzie
- Wybiera korzystanie z interfejsów API w bibliotece Jetpack Projected.
ProjectedMainActivityrozszerzaComponentActivity, tak jak można oczekiwać w przypadku tworzenia aplikacji mobilnych.- Ponieważ nie wszystkie okulary mają wyświetlacz, sprawdza, czy urządzenie ma
wyświetlacz, za pomocą
ProjectedDeviceController. - Blok
setContentw funkcjionCreateokreśla główny element drzewa interfejsu Composable dla aktywności. Zaimplementujesz elementHomeScreencomposable za pomocą Jetpack Compose Glimmer. - Inicjuje interfejs podczas metody
onCreateaktywności (zobacz cykl życia działania). - Aby przygotować się na funkcje związane z aparatem, które
mają dostęp do sprzętu okularów, prosi o uprawnienia do sprzętu przez
zarejestrowanie programu uruchamiającego uprawnienia, zdefiniowanie funkcji
hasCameraPermissionirequestHardwarePermissionsoraz sprawdzenie, czy uprawnienia zostały przyznane przed wywołanieminitializeGlassesFeatures.
Zaimplementuj element typu „composable”
Utworzona aktywność odwołuje się do funkcji typu „composable” HomeScreen, którą musisz zaimplementować. Poniższy kod używa Jetpack Compose Glimmer do
zdefiniowania elementu typu „composable”, który może wyświetlać tekst na wyświetlaczu okularów:
@Composable fun HomeScreen( areVisualsOn: Boolean, isVisualUiSupported: Boolean, isPermissionDenied: Boolean, onRetryPermission: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier ) { Box( modifier = modifier .surface() .focusable(false) .fillMaxSize(), contentAlignment = Alignment.Center ) { if (isPermissionDenied) { Card( title = { Text("Permission Required") }, action = { Button(onClick = onClose) { Text("Exit") } } ) { Text("Camera access is needed to use AI glasses features.") Button(onClick = onRetryPermission) { Text("Retry") } } } else if (isVisualUiSupported) { Card( title = { Text("Android XR") }, action = { Button(onClick = onClose) { Text("Close") } } ) { if (areVisualsOn) { Text("Hello, AI Glasses!") } else { Text("Display is off. Audio guidance active.") } } } else { Text("Audio Guidance Mode Active") } } }
Najważniejsze informacje o kodzie
- Jak zdefiniowano wcześniej w aktywności, funkcja
HomeScreenzawiera treść typu „composable”, którą użytkownik widzi, gdy wyświetlacz okularów jest włączony. - Komponent
TextJetpack Compose Glimmer wyświetla tekst "Hello, AI Glasses!" na wyświetlaczu okularów. - Komponent
ButtonJetpack Compose Glimmer zamyka aktywność, wywołującfinish()przezonClosew aktywności wyświetlanej.
Sprawdź, czy okulary z dźwiękiem lub wyświetlaczem są połączone
Aby sprawdzić, czy okulary z dźwiękiem lub okulary z wyświetlaczem użytkownika są połączone z ich
telefonem przed uruchomieniem aktywności, użyj
ProjectedContext.isProjectedDeviceConnected metody. Ta metoda
zwraca Flow<Boolean>, którą aplikacja może obserwować, aby otrzymywać aktualizacje w czasie rzeczywistym o
stanie połączenia.
Uruchom aktywność
Po utworzeniu podstawowej aktywności możesz ją uruchomić na okularach. Aby uzyskać dostęp do sprzętu okularów, aplikacja musi uruchomić aktywność z określonymi opcjami, które informują system o użyciu kontekstu wyświetlanego, jak pokazano w tym kodzie:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, ProjectedMainActivity::class.java) context.startActivity(intent, options.toBundle())
Metoda createProjectedActivityOptions w ProjectedContext
generuje opcje niezbędne do uruchomienia aktywności w kontekście wyświetlanym.
Parametr context może być kontekstem z telefonu lub okularów.
Dalsze kroki
Po utworzeniu pierwszej Activity na okulary audio i okulary z wyświetlaczem możesz poznać inne sposoby rozszerzania jej funkcjonalności:
- Obsługa wyjścia audio za pomocą zamiany tekstu na mowę
- Obsługa danych wejściowych audio za pomocą automatycznego rozpoznawania mowy
- Tworzenie interfejsu za pomocą Jetpack Compose Glimmer
- Dostęp do sprzętu na okularach audio i okularach z wyświetlaczem