Pengalaman augmented untuk kacamata pintar audio dan kacamata pintar dengan layar dibangun berdasarkan
Android Activity framework API yang ada dan menyertakan konsep
tambahan untuk mendukung aspek unik dari kacamata pintar ini. Tidak seperti headset XR yang menjalankan APK lengkap di perangkat, kacamata pintar audio dan kacamata pintar dengan layar menggunakan aktivitas khusus yang berjalan dalam aplikasi yang ada di ponsel Anda. Aktivitas ini diproyeksikan dari perangkat host ke kacamata pintar.
Untuk membuat pengalaman aplikasi Anda untuk kacamata pintar audio dan kacamata pintar dengan layar, Anda
memperluas aplikasi ponsel yang ada dengan membuat Activityyang diproyeksikan baru. Aktivitas ini berfungsi sebagai titik entri peluncuran utama untuk aplikasi Anda di kacamata pintar. Pendekatan ini menyederhanakan pengembangan karena Anda dapat berbagi dan menggunakan kembali logika bisnis antara pengalaman ponsel dan kacamata pintar.
Kompatibilitas versi
Periksa persyaratan kompatibilitas Android SDK untuk Jetpack XR SDK.
Dependensi
Tambahkan dependensi library berikut untuk kacamata pintar audio dan kacamata pintar dengan layar:
Groovy
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")
}
Mendeklarasikan aktivitas di manifes aplikasi
Sama seperti jenis aktivitas lainnya, Anda perlu mendeklarasikan aktivitas di file manifes aplikasi agar sistem dapat melihat dan menjalankannya.
<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>
Poin-poin penting tentang kode
- Menentukan
android.hardware.display.category.XR_PROJECTEDuntuk atributandroid:requiredDisplayCategoryguna memberi tahu sistem bahwa ini adalah aktivitas yang diproyeksikan dan dapat diproyeksikan ke kacamata pintar audio dan kacamata pintar dengan layar. android.intent.action.MAINmenetapkan aktivitas ini sebagai aktivitas peluncuran default.android.intent.category.XR_PROJECTED_LAUNCHERadalah kategori khusus yang membuat aktivitas yang diproyeksikan dapat ditemukan oleh perintah suara Gemini.Saat pengguna mengeluarkan perintah suara menggunakan nama aplikasi (misalnya, "Buka contoh katalog AI", "Luncurkan contoh katalog AI", atau "Mulai contoh katalog AI"), sistem akan menggunakan kategori ini untuk menemukan dan memulai aktivitas yang ditentukan di kacamata pintar audio atau kacamata pintar dengan layar.
Membuat aktivitas
Selanjutnya, Anda akan membuat aktivitas kecil yang dapat menampilkan sesuatu di kacamata pintar AI setiap kali layar diaktifkan.
@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)) } }
Poin-poin penting tentang kode
- Memilih untuk menggunakan API pilihan dari library Jetpack Projected.
ProjectedMainActivitymemperluasComponentActivity, seperti yang Anda harapkan dalam pengembangan seluler.- Karena tidak semua kacamata pintar memiliki layar, periksa apakah perangkat memiliki a
layar menggunakan
ProjectedDeviceController. - Blok
setContentdalam fungsionCreatemenentukan root pohon UI Composable untuk aktivitas. Anda akan mengimplementasikanHomeScreencomposable menggunakan Jetpack Compose Glimmer. - Menginisialisasi UI selama metode
onCreateaktivitas (lihat siklus proses aktivitas yang diproyeksikan). - Untuk mempersiapkan fitur terkait kamera yang
mengakses hardware kacamata pintar, minta izin hardware dengan
mendaftarkan peluncur izin, menentukan fungsi
hasCameraPermissiondanrequestHardwarePermissions, serta memeriksa apakah izin telah diberikan sebelum memanggilinitializeGlassesFeatures.
Mengimplementasikan composable
Aktivitas yang Anda buat mereferensikan fungsi composable HomeScreen yang perlu Anda implementasikan. Kode berikut menggunakan Jetpack Compose Glimmer untuk
menentukan composable yang dapat menampilkan beberapa teks di layar kacamata pintar:
@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") } } }
Poin-poin penting tentang kode
- Seperti yang Anda tentukan dalam aktivitas sebelumnya, fungsi
HomeScreenmenyertakan konten composable yang dilihat pengguna saat layar kacamata pintar aktif. - Komponen
TextJetpack Compose Glimmer menampilkan teks "Hello, AI Glasses!" ke layar kacamata pintar. ButtonJetpack Compose Glimmer menutup aktivitas dengan memanggilfinish()melaluionClosedalam aktivitas yang diproyeksikan.
Memeriksa apakah kacamata pintar audio atau kacamata pintar dengan layar terhubung
Untuk menentukan apakah kacamata pintar audio atau kacamata pintar dengan layar pengguna terhubung ke
ponselnya sebelum meluncurkan aktivitas Anda, gunakan metode
ProjectedContext.isProjectedDeviceConnected. Metode ini
menampilkan Flow<Boolean> yang dapat diamati aplikasi Anda untuk mendapatkan update status koneksi secara real-time.
Memulai aktivitas
Setelah membuat aktivitas dasar, Anda dapat meluncurkannya ke kacamata pintar. Untuk mengakses hardware kacamata pintar, aplikasi Anda harus memulai aktivitas dengan opsi tertentu yang memberi tahu sistem untuk menggunakan konteks yang diproyeksikan, seperti ditunjukkan dalam kode berikut:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, ProjectedMainActivity::class.java) context.startActivity(intent, options.toBundle())
Metode createProjectedActivityOptions di ProjectedContext
menghasilkan opsi yang diperlukan untuk memulai aktivitas Anda dalam konteks yang diproyeksikan.
Parameter context dapat berupa konteks dari ponsel atau perangkat kacamata pintar.
Langkah berikutnya
Setelah membuat aktivitas pertama untuk kacamata pintar audio dan kacamata pintar dengan layar, pelajari cara lain untuk memperluas fungsinya:
- Menangani output audio menggunakan Text to Speech
- Menangani input audio menggunakan Pengenalan Ucapan Otomatis
- Membangun UI dengan Jetpack Compose Glimmer
- Mengakses hardware di kacamata pintar audio dan kacamata pintar dengan layar