AI 眼鏡體驗是以現有的 Android Activity 架構 API 為基礎,並納入其他概念,支援 AI 眼鏡的獨特功能。與在裝置上執行完整 APK 的 XR 頭戴式裝置不同,AI 眼鏡會使用專屬活動,在手機現有的應用程式中執行。這項活動會從主機裝置投影到 AI 眼鏡。
如要建立應用程式的 AI 眼鏡體驗,請為 AI 眼鏡建立新的投影 Activity,藉此擴充現有的手機應用程式。這項活動是 AI 眼鏡上應用程式的主要啟動進入點。這種做法可簡化開發作業,因為您可以在手機和 AI 眼鏡體驗之間共用及重複使用商業邏輯。
版本相容性
請參閱 Jetpack XR SDK 的 Android SDK 相容性需求。
依附元件
Groovy
dependencies { implementation "androidx.xr.runtime:runtime:1.0.0-alpha11" implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha08" implementation "androidx.xr.projected:projected:1.0.0-alpha05" implementation "androidx.xr.arcore:arcore:1.0.0-alpha11" }
Kotlin
dependencies { implementation("androidx.xr.runtime:runtime:1.0.0-alpha11") implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha08") implementation("androidx.xr.projected:projected:1.0.0-alpha05") implementation("androidx.xr.arcore:arcore:1.0.0-alpha11") }
在應用程式資訊清單中宣告活動
與其他類型的活動一樣,您需要在應用程式的資訊清單檔案中宣告活動,系統才能查看及運作執行活動。
<application>
<activity
android:name="com.example.xr.projected.GlassesMainActivity"
android:exported="true"
android:requiredDisplayCategory="xr_projected"
android:label="Example AI Glasses activity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>
程式碼重點
- 為
android:requiredDisplayCategory屬性指定xr_projected,告知系統這項活動應使用投影背景資訊,從連結裝置存取硬體。
建立活動
接著,您將建立小型活動,在螢幕開啟時,於 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)) } }
程式碼重點
- 選擇使用 Jetpack Projected 程式庫中的選擇加入 API。
GlassesMainActivity會擴充ComponentActivity,就像您在行動開發中預期的一樣。- 由於並非所有 AI 眼鏡都有螢幕,請使用
ProjectedDeviceController檢查裝置是否配備螢幕。 onCreate函式中的setContent區塊會定義活動的可組合 UI 樹狀結構根層級。您將使用 Jetpack Compose Glimmer 實作HomeScreen可組合函式。- 在活動的
onCreate方法中初始化 UI (請參閱預計活動生命週期)。 - 如要準備使用存取智慧眼鏡硬體的相機相關功能,請要求硬體權限,方法是註冊權限啟動器、定義
hasCameraPermission和requestHardwarePermissions函式,並在呼叫initializeGlassesFeatures前檢查是否已授予權限。
實作可組合函式
您建立的活動會參照您需要實作的 HomeScreen 可組合函式。下列程式碼使用 Jetpack Compose Glimmer 定義可組合函式,在 AI 眼鏡的螢幕上顯示部分文字:
@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函式包含 AI 眼鏡螢幕開啟時,使用者會看到的可組合內容。 - Jetpack Compose Glimmer
Text元件會在眼鏡螢幕上顯示「Hello, AI Glasses!」。 - Jetpack Compose Glimmer
Button會透過 AI 眼鏡活動中的onClose呼叫finish(),關閉活動。
確認 AI 眼鏡是否已連線
如要判斷使用者的 AI 眼鏡是否已連線至手機,請在啟動活動前使用 ProjectedContext.isProjectedDeviceConnected 方法。這個方法會傳回 Flow<Boolean>,應用程式可觀察這個物件,即時取得連線狀態的更新資訊。
開始活動
您已建立基本活動,現在可以將其啟動到眼鏡上。 如要存取眼鏡的硬體,應用程式必須使用特定選項啟動活動,告知系統使用投影內容,如下列程式碼所示:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, GlassesMainActivity::class.java) context.startActivity(intent, options.toBundle())
ProjectedContext 中的 createProjectedActivityOptions 方法會產生必要選項,以便在投影情境中啟動活動。context 參數可以是手機或智慧眼鏡裝置的內容。
後續步驟
現在您已為 AI 眼鏡建立第一個活動,接下來請探索其他擴充功能的方法: