Sesli gözlükler ve görüntülü gözlükler için artırılmış gerçeklik deneyimleri, mevcut Android Activity framework API'si üzerine kurulur ve bu gözlüklerin benzersiz yönlerini desteklemek için ek kavramlar içerir. Cihazda tam APK çalıştıran XR kulaklıkların aksine, ses gözlükleri ve ekran gözlükleri, telefonunuzdaki mevcut uygulamada çalışan özel bir etkinlik kullanır. Bu etkinlik, ana cihazdan gözlüğe yansıtılır.
Uygulamanızın ses gözlüğü ve ekranlı gözlük deneyimini oluşturmak için yeni bir yansıtılan Activity oluşturarak mevcut telefon uygulamanızı genişletirsiniz. Bu etkinlik, uygulamanızın gözlüklerdeki ana başlatma giriş noktası olarak işlev görür. Bu yaklaşım, telefon ve gözlük deneyimleriniz arasında iş mantığını paylaşmanıza ve yeniden kullanmanıza olanak tanıdığı için geliştirme sürecini basitleştirir.
Sürüm uyumluluğu
Jetpack XR SDK'sı için Android SDK uyumluluk koşullarını kontrol edin.
Bağımlılıklar
Aşağıdaki sesli gözlük ve görüntülü gözlük kitaplığı bağımlılıklarını ekleyin:
Modern
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")
}
Uygulamanızın manifest dosyasında etkinliğinizi beyan edin
Diğer etkinlik türlerinde olduğu gibi, sistemin etkinliğinizi görmesi ve çalıştırması için uygulamanızın manifest dosyasında etkinliğinizi beyan etmeniz gerekir.
<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>
Kodla ilgili önemli noktalar
- Bunun planlanmış bir etkinlik olduğunu ve ses ve ekran gözlüklerine yansıtılabileceğini sisteme bildirmek için
android:requiredDisplayCategoryözelliği içinandroid.hardware.display.category.XR_PROJECTEDdeğerini belirtir. android.intent.action.MAINbu etkinliği varsayılan başlatma etkinliği olarak ayarlar.android.intent.category.XR_PROJECTED_LAUNCHER, planladığınız etkinliğin Gemini sesli komutlarıyla bulunmasını sağlayan özel bir kategoridir.Bir kullanıcı, uygulamanın adını kullanarak sesli komut verdiğinde (örneğin, "Open the AI catalog sample" [Yapay zeka kataloğu örneğini aç], "Launch the AI catalog sample" [Yapay zeka kataloğu örneğini başlat] veya "Start the AI catalog sample" [Yapay zeka kataloğu örneğini başlat]), sistem bu kategoriyi kullanarak sesli veya ekranlı gözlüklerdeki belirlenen etkinliği bulup başlatır.
Etkinliğinizi oluşturma
Ardından, ekran her açıldığında yapay zeka gözlüklerinde bir şeyler gösterebilen küçük bir etkinlik oluşturacaksınız.
@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)) } }
Kodla ilgili önemli noktalar
- Jetpack Projected kitaplığındaki opt-in API'lerini kullanmayı etkinleştirir.
GlassesMainActivity, mobil geliştirmede beklediğiniz gibiComponentActivity'i genişletir.- Tüm gözlüklerde ekran bulunmadığından
ProjectedDeviceControllerkullanarak cihazda ekran olup olmadığını kontrol eder. onCreateişlevi içindekisetContentbloğu, etkinlik için Composable kullanıcı arayüzü ağacının kökünü tanımlar.HomeScreencomposable'ı Jetpack Compose Glimmer kullanarak uygulayacaksınız.- Etkinliğin
onCreateyöntemi sırasında kullanıcı arayüzünü başlatır (bkz. tahmini etkinlik yaşam döngüsü). - Gözlük donanımına erişen kamera özelliklerine hazırlanmak için izin başlatıcı kaydederek,
hasCameraPermissionverequestHardwarePermissionsişlevlerini tanımlayarak veinitializeGlassesFeaturesişlevi çağrılmadan önce izinlerin verilip verilmediğini kontrol ederek donanım izinleri isteyin.
Composable'ı uygulama
Oluşturduğunuz etkinlik, uygulamanız gereken bir HomeScreen composable işlevine referans veriyor. Aşağıdaki kod, gözlüğün ekranında metin görüntüleyebilen bir composable tanımlamak için Jetpack Compose Glimmer'ı kullanır:
@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") } } }
Kodla ilgili önemli noktalar
- Etkinliğinizde daha önce tanımladığınız gibi,
HomeScreenişlevi, gözlüğün ekranı açıkken kullanıcının gördüğü birleştirilebilir içeriği içerir. - Jetpack Compose Glimmer
Textbileşeni, gözlüğün ekranında "Merhaba, Yapay Zeka Gözlükleri!" metnini gösterir. - Jetpack Compose Glimmer
Button, yansıtılan etkinliktekionClosearacılığıylafinish()çağrısı yaparak etkinliği kapatır.
Ses veya ekran gözlüğünün bağlı olup olmadığını kontrol etme
Etkinliğinizi başlatmadan önce kullanıcının ses veya ekran gözlüğünün telefonuna bağlı olup olmadığını belirlemek için ProjectedContext.isProjectedDeviceConnected yöntemini kullanın. Bu yöntem, bağlantı durumuyla ilgili anlık güncellemeler almak için uygulamanızın gözlemleyebileceği bir Flow<Boolean> döndürür.
Etkinliğinizi başlatma
Temel bir etkinlik oluşturduğunuza göre artık bunu gözlüğünüzde başlatabilirsiniz. Gözlüğün donanımına erişmek için uygulamanız, etkinliğinizi aşağıdaki kodda gösterildiği gibi sisteme yansıtılmış bağlam kullanmasını söyleyen belirli seçeneklerle başlatmalıdır:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, GlassesMainActivity::class.java) context.startActivity(intent, options.toBundle())
ProjectedContext içindeki createProjectedActivityOptions yöntemi, etkinliğinizi öngörülen bir bağlamda başlatmak için gereken seçenekleri oluşturur. context parametresi, telefondaki veya gözlük cihazındaki bir bağlam olabilir.
Sonraki adımlar
Ses gözlüğü ve ekran gözlüğü için ilk etkinliğinizi oluşturduğunuza göre, işlevselliğini genişletebileceğiniz diğer yöntemleri keşfedin:
- Metin okuma özelliğini kullanarak ses çıkışını yönetme
- Otomatik Konuşma Tanıma'yı kullanarak ses girişini işleme
- Jetpack Compose Glimmer ile kullanıcı arayüzü oluşturma
- Sesli gözlüklerde ve görüntülü gözlüklerde donanıma erişme