ประสบการณ์การใช้งานแบบเสริมสำหรับแว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผลสร้างขึ้นบน
API เฟรมเวิร์ก Activity ของ Android ที่มีอยู่ และ รวมแนวคิดเพิ่มเติมเพื่อรองรับลักษณะเฉพาะของแว่นตาเหล่านี้ แว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผลต่างจากชุดหูฟัง XR ที่เรียกใช้ APK แบบเต็มบนอุปกรณ์ตรงที่ใช้กิจกรรมเฉพาะที่ทำงานภายในแอปที่มีอยู่ของโทรศัพท์ โดยกิจกรรมนี้จะแสดงจากอุปกรณ์โฮสต์ไปยังแว่นตา
หากต้องการสร้างประสบการณ์การใช้งานแว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผลของแอป คุณต้อง
ขยายแอปโทรศัพท์ที่มีอยู่โดยสร้าง Activity ใหม่ที่แสดง กิจกรรมนี้ทำหน้าที่เป็นจุดแรกเข้าหลักในการเปิดแอปของคุณบนแว่นตา แนวทางนี้ช่วยลดความซับซ้อนในการพัฒนาเนื่องจากคุณแชร์และนำตรรกะทางธุรกิจระหว่างประสบการณ์การใช้งานโทรศัพท์และแว่นตามาใช้ซ้ำได้
ความเข้ากันได้กับเวอร์ชัน
ตรวจสอบข้อกำหนดด้านความเข้ากันได้ของ Android SDK สำหรับ Jetpack XR SDK
ความสัมพันธ์
เพิ่มความสัมพันธ์ของไลบรารีต่อไปนี้สำหรับแว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผล
ดึงดูด
dependencies {
implementation "androidx.xr.runtime:runtime:1.0.0-alpha14"
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-alpha14")
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")
}
ประกาศกิจกรรมในไฟล์ Manifest ของแอป
เช่นเดียวกับกิจกรรมประเภทอื่นๆ คุณต้องประกาศกิจกรรมในไฟล์ Manifest ของแอปเพื่อให้ระบบมองเห็นและเรียกใช้ได้
<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 ค้นพบกิจกรรมที่แสดงได้เมื่อผู้ใช้ส่งคำสั่งเสียงโดยใช้ชื่อแอป (เช่น "เปิดตัวอย่างแคตตาล็อก AI", "เปิดตัวอย่างแคตตาล็อก AI" หรือ "เริ่มตัวอย่างแคตตาล็อก AI") ระบบจะใช้หมวดหมู่นี้เพื่อค้นหาและเริ่มกิจกรรมที่กำหนดบนแว่นตาที่มีระบบเสียงหรือแว่นตาที่มีจอแสดงผล
สร้างกิจกรรม
จากนั้นคุณจะสร้างกิจกรรมเล็กๆ ที่แสดงสิ่งต่างๆ บนแว่นตา AI ได้เมื่อใดก็ตามที่เปิดจอแสดงผล
@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)) } }
ประเด็นสำคัญเกี่ยวกับโค้ด
- เลือกใช้ API ที่เลือกใช้ จากไลบรารี Jetpack Projected
GlassesMainActivityขยายComponentActivityเช่นเดียวกับที่คุณ คาดหวังในการพัฒนาแอปบนมือถือ- เนื่องจากแว่นตาบางรุ่นไม่มีจอแสดงผล จึงต้องตรวจสอบว่าอุปกรณ์มีจอแสดงผลหรือไม่โดยใช้
ProjectedDeviceController - บล็อก
setContentภายในฟังก์ชันonCreateจะกำหนดรูทของแผนผัง UI ของฟังก์ชันที่ประกอบกันได้สำหรับกิจกรรม คุณจะใช้ฟังก์ชันที่ประกอบกันได้HomeScreenโดยใช้ Jetpack Compose Glimmer - เริ่มต้น UI ในระหว่างเมธอด
onCreateของกิจกรรม (ดู วงจรกิจกรรมที่แสดง) - หากต้องการเตรียมพร้อมสำหรับฟีเจอร์ที่เกี่ยวข้องกับกล้องที่
เข้าถึงฮาร์ดแวร์ของแว่นตา ให้ขอสิทธิ์เข้าถึงฮาร์ดแวร์โดย
ลงทะเบียนตัวเปิดสิทธิ์ กำหนดฟังก์ชัน
hasCameraPermissionและrequestHardwarePermissionsรวมถึงตรวจสอบว่าได้รับสิทธิ์แล้วหรือไม่ก่อนที่จะเรียกinitializeGlassesFeatures
ใช้ฟังก์ชันที่ประกอบกันได้
กิจกรรมที่คุณสร้างจะอ้างอิงฟังก์ชันที่ประกอบกันได้ HomeScreen ซึ่งคุณต้องใช้ โค้ดต่อไปนี้ใช้ Jetpack Compose Glimmer เพื่อ
กำหนดฟังก์ชันที่ประกอบกันได้ ซึ่งแสดงข้อความบนจอแสดงผลของแว่นตาได้
@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") } } }
ประเด็นสำคัญเกี่ยวกับโค้ด
- ตามที่คุณกำหนดไว้ในกิจกรรมก่อนหน้านี้ ฟังก์ชัน
HomeScreenประกอบด้วยเนื้อหาที่ประกอบกันได้ซึ่งผู้ใช้เห็นเมื่อจอแสดงผลของแว่นตาเปิดอยู่ - คอมโพเนนต์
Textของ Jetpack Compose Glimmer จะแสดงข้อความ "Hello, AI Glasses!" ในจอแสดงผลของแว่นตา - คอมโพเนนต์
Buttonของ Jetpack Compose Glimmer จะปิดกิจกรรมโดยเรียกใช้finish()ผ่านonCloseในกิจกรรมที่แสดง
ตรวจสอบว่าแว่นตาที่มีระบบเสียงหรือแว่นตาที่มีจอแสดงผลเชื่อมต่ออยู่หรือไม่
หากต้องการตรวจสอบว่าแว่นตาที่มีระบบเสียงหรือแว่นตาที่มีจอแสดงผลของผู้ใช้เชื่อมต่อกับโทรศัพท์หรือไม่ ก่อนเปิดกิจกรรม ให้ใช้เมธอด
ProjectedContext.isProjectedDeviceConnected เมธอดนี้
จะส่งคืน Flow<Boolean> ที่แอปของคุณสามารถสังเกตเพื่อรับข้อมูลอัปเดตแบบเรียลไทม์เกี่ยวกับ
สถานะการเชื่อมต่อ
เริ่มกิจกรรม
เมื่อสร้างกิจกรรมพื้นฐานแล้ว คุณก็เปิดใช้กิจกรรมในแว่นตาได้ หากต้องการเข้าถึงฮาร์ดแวร์ของแว่นตา แอปของคุณต้องเริ่มกิจกรรมด้วยตัวเลือกที่เฉพาะเจาะจง ซึ่งบอกให้ระบบใช้บริบทที่คาดการณ์ไว้ ดังที่แสดงใน โค้ดต่อไปนี้
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, GlassesMainActivity::class.java) context.startActivity(intent, options.toBundle())
เมธอด createProjectedActivityOptions ใน ProjectedContext
จะสร้างตัวเลือกที่จำเป็นเพื่อเริ่มกิจกรรมในบริบทที่แสดง
พารามิเตอร์ context อาจเป็นบริบทจากโทรศัพท์หรือแว่นตา
ขั้นตอนถัดไป
เมื่อสร้างกิจกรรมแรกสำหรับแว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผลแล้ว ให้ลองดูวิธีอื่นๆ ที่คุณสามารถขยายฟังก์ชันการทำงานได้
- จัดการเอาต์พุตเสียงโดยใช้การอ่านออกเสียงข้อความ
- จัดการอินพุตเสียงโดยใช้การจดจำคำพูดอัตโนมัติ
- สร้าง UI ด้วย Jetpack Compose Glimmer
- เข้าถึงฮาร์ดแวร์บนแว่นตาที่มีระบบเสียงและแว่นตาที่มีจอแสดงผล