Erweiterte Funktionen für Audio- und Datenbrillen basieren auf der vorhandenen Android-API Activity und umfassen zusätzliche Konzepte, um die besonderen Aspekte dieser Datenbrillen zu unterstützen. Im Gegensatz zu XR-Headsets, auf denen eine vollständige APK auf dem Gerät ausgeführt wird, verwenden Audio- und Datenbrillen eine spezielle Activity, die in der vorhandenen App auf Ihrem Smartphone ausgeführt wird. Diese Activity wird vom Hostgerät auf die Brille projiziert.
Um die App für Audio- und Displaybrillen zu erstellen, erweitern Sie Ihre vorhandene Smartphone-App, indem Sie ein neues projiziertes Activity erstellen. Diese Aktivität dient als Haupteinstiegspunkt für den Start Ihrer App auf der Brille. Dieser Ansatz vereinfacht die Entwicklung, da Sie Geschäftslogik zwischen Ihren Smartphone- und Brillen-Apps teilen und wiederverwenden können.
Versionskompatibilität
Kompatibilitätsanforderungen für das Android SDK für das Jetpack XR SDK
Abhängigkeiten
Fügen Sie die folgenden Bibliotheksabhängigkeiten für Audio- und Displaybrillen hinzu:
Groovy
dependencies {
implementation "androidx.xr.runtime:runtime:1.0.0-alpha14"
implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha12"
implementation "androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha12"
implementation "androidx.xr.projected:projected:1.0.0-alpha07"
implementation "androidx.xr.arcore:arcore:1.0.0-alpha13"
}
Kotlin
dependencies {
implementation("androidx.xr.runtime:runtime:1.0.0-alpha14")
implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha12")
implementation("androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha12")
implementation("androidx.xr.projected:projected:1.0.0-alpha07")
implementation("androidx.xr.arcore:arcore:1.0.0-alpha13")
}
Aktivität im Manifest Ihrer App deklarieren
Wie bei anderen Arten von Aktivitäten müssen Sie Ihre Aktivität in der Manifestdatei Ihrer App deklarieren, damit das System sie sehen und ausführen kann.
<application>
<activity
android:name="com.example.xr.projected.GlassesMainActivity"
android:exported="true"
android:requiredDisplayCategory="xr_projected"
android:label="Example activity for audio glasses and display glasses">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>
Wichtige Punkte zum Code
- Gibt
xr_projectedfür das Attributandroid:requiredDisplayCategoryan, um dem System mitzuteilen, dass für diese Aktivität ein projizierter Kontext verwendet werden soll, um auf Hardware eines verbundenen Geräts zuzugreifen.
Aktivität erstellen
Als Nächstes erstellen Sie eine kleine Aktivität, die etwas auf der KI-Brille anzeigen kann, wenn das Display eingeschaltet ist.
@OptIn(ExperimentalProjectedApi::class) class GlassesMainActivity : 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@GlassesMainActivity) isVisualUiSupported = projectedDeviceController.capabilities.contains(CAPABILITY_VISUAL_UI) val controller = ProjectedDisplayController.create(this@GlassesMainActivity) displayController = controller val observer = GlassesLifecycleObserver( context = this@GlassesMainActivity, 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)) } }
Wichtige Punkte zum Code
- Aktiviert die Verwendung von Opt-in-APIs aus der Jetpack Projected-Bibliothek.
GlassesMainActivityerweitertComponentActivity, wie Sie es von der mobilen Entwicklung gewohnt sind.- Da nicht alle Brillen ein Display haben, wird mit
ProjectedDeviceControllergeprüft, ob das Gerät ein Display hat. - Der Block
setContentin der FunktiononCreatedefiniert den Stamm des zusammensetzbaren UI-Baums für die Aktivität. Sie implementieren dieHomeScreen-Composable mit Jetpack Compose Glimmer. - Initialisiert die Benutzeroberfläche während der
onCreate-Methode der Aktivität (siehe projizierter Aktivitätslebenszyklus). - Um sich auf kamerabezogene Funktionen vorzubereiten, die auf die Hardware der Brille zugreifen, Hardwareberechtigungen anfordern, indem Sie einen Berechtigungs-Launcher registrieren, die Funktionen
hasCameraPermissionundrequestHardwarePermissionsdefinieren und prüfen, ob Berechtigungen erteilt wurden, bevor SieinitializeGlassesFeaturesaufrufen.
Composable implementieren
Die von Ihnen erstellte Aktivität verweist auf eine zusammensetzbare HomeScreen-Funktion, die Sie implementieren müssen. Im folgenden Code wird Jetpack Compose Glimmer verwendet, um eine zusammensetzbare Funktion zu definieren, mit der Text auf dem Display der Brille angezeigt werden kann:
@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") } } }
Wichtige Punkte zum Code
- Wie Sie in Ihrer Aktivität zuvor definiert haben, enthält die Funktion
HomeScreendie zusammensetzbaren Inhalte, die der Nutzer sieht, wenn das Display der Brille eingeschaltet ist. - Die Jetpack Compose Glimmer-Komponente
Textzeigt den Text „Hallo, KI-Brille!“ auf dem Display der Brille an. - Das Jetpack Compose-Glimmer
Buttonschließt die Aktivität, indem esfinish()überonClosein der projizierten Aktivität aufruft.
Prüfen, ob Audio- oder Displaybrillen verbunden sind
Mit der Methode ProjectedContext.isProjectedDeviceConnected können Sie vor dem Starten Ihrer Aktivität prüfen, ob die Audio- oder Displaybrille eines Nutzers mit seinem Smartphone verbunden ist. Diese Methode gibt ein Flow<Boolean> zurück, das Ihre App beobachten kann, um Echtzeit-Updates zum Verbindungsstatus zu erhalten.
Aktivität starten
Nachdem Sie eine einfache Aktivität erstellt haben, können Sie sie auf Ihrer Brille starten. Damit Ihre App auf die Hardware der Brille zugreifen kann, muss sie Ihre Aktivität mit bestimmten Optionen starten, die dem System mitteilen, dass ein projizierter Kontext verwendet werden soll. Das folgende Codebeispiel zeigt, wie das geht:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, GlassesMainActivity::class.java) context.startActivity(intent, options.toBundle())
Mit der Methode createProjectedActivityOptions in ProjectedContext werden die erforderlichen Optionen zum Starten Ihrer Aktivität in einem projizierten Kontext generiert.
Der Parameter context kann ein Kontext vom Smartphone oder von der Brille sein.
Nächste Schritte
Nachdem Sie Ihre erste Aktivität für Audio- und Displaybrillen erstellt haben, können Sie die Funktionalität auf verschiedene Arten erweitern:
- Audioausgabe mit Text-zu-Sprache verarbeiten
- Audioeingabe mit automatischer Spracherkennung verarbeiten
- Benutzeroberfläche mit Jetpack Compose Glimmer erstellen
- Auf Hardware von Audio- und Displaybrillen zugreifen