تجربیات افزوده برای عینکهای صوتی و عینکهای نمایشی بر اساس API موجود در چارچوب Activity اندروید ساخته شدهاند و شامل مفاهیم اضافی برای پشتیبانی از جنبههای منحصر به فرد این عینکها هستند. برخلاف هدستهای XR که یک APK کامل را روی دستگاه اجرا میکنند، عینکهای صوتی و عینکهای نمایشی از یک فعالیت اختصاصی استفاده میکنند که در برنامه موجود تلفن شما اجرا میشود. این فعالیت از دستگاه میزبان به عینکها منتقل میشود.
برای ایجاد تجربه برنامه خود برای عینکهای صوتی و عینکهای نمایشی، شما برنامه تلفن موجود خود را با ایجاد یک Activity جدید projected گسترش میدهید. این activity به عنوان نقطه ورود اصلی راهاندازی برای برنامه شما روی عینک عمل میکند. این رویکرد توسعه را ساده میکند زیرا میتوانید منطق کسبوکار را بین تجربیات تلفن و عینک خود به اشتراک بگذارید و دوباره استفاده کنید.
سازگاری نسخه
الزامات سازگاری Android SDK را برای Jetpack XR SDK بررسی کنید.
وابستگیها
وابستگیهای کتابخانهای زیر را برای عینکهای صوتی و عینکهای نمایشی اضافه کنید:
گرووی
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"
}
کاتلین
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")
}
فعالیت خود را در مانیفست برنامه خود اعلام کنید
درست مانند سایر انواع اکتیویتیها، شما باید اکتیویتی خود را در فایل مانیفست برنامه خود تعریف کنید تا سیستم آن را ببیند و اجرا کند.
<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>
نکات کلیدی در مورد کد
-
xr_projectedبرای ویژگیandroid:requiredDisplayCategoryمشخص میکند تا به سیستم بگوید که این فعالیت باید از یک زمینهی پیشبینیشده برای دسترسی به سختافزار از یک دستگاه متصل استفاده کند.
فعالیت خود را ایجاد کنید
در مرحله بعد، یک فعالیت کوچک ایجاد خواهید کرد که میتواند هر زمان که صفحه نمایش روشن میشود، چیزی را روی عینک هوش مصنوعی نمایش دهد.
@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ریشه درخت رابط کاربری Composable را برای اکتیویتی تعریف میکند. شما ComposableHomeScreenبا استفاده از Jetpack Compose Glimmer پیادهسازی خواهید کرد. - رابط کاربری را در طول متد
onCreateمربوط به اکتیویتی مقداردهی اولیه میکند (به چرخه حیات اکتیویتی پیشبینیشده مراجعه کنید). - برای آمادهسازی ویژگیهای مرتبط با دوربین که به سختافزار عینک دسترسی دارند ، با ثبت یک لانچر مجوزها، تعریف توابع
hasCameraPermissionوrequestHardwarePermissionsو بررسی اینکه آیا مجوزها قبل از فراخوانیinitializeGlassesFeaturesاعطا شدهاند یا خیر ، مجوزهای سختافزاری را درخواست میکند .
پیادهسازی composable
اکتیویتی که شما ایجاد کردهاید به یک تابع قابل ترکیب 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") } } }
نکات کلیدی در مورد کد
- همانطور که قبلاً در activity خود تعریف کردید، تابع
HomeScreenشامل محتوای قابل ترکیبی است که کاربر هنگام روشن بودن صفحه نمایش عینک میبیند. - کامپوننت Jetpack Compose Glimmer
Textمتن «سلام، عینک هوش مصنوعی!» را روی نمایشگر عینک نمایش میدهد. -
ButtonJetpack Compose Glimmer با فراخوانیfinish()از طریقonCloseدر activity مورد نظر، activity را میبندد.
بررسی کنید که آیا عینکهای صوتی یا تصویری متصل هستند یا خیر
برای اینکه قبل از اجرای اکتیویتی خود، مشخص کنید که آیا عینک صوتی یا تصویری کاربر به تلفن همراهش متصل است یا خیر، از متد ProjectedContext.isProjectedDeviceConnected استفاده کنید. این متد یک Flow<Boolean> برمیگرداند که برنامه شما میتواند آن را مشاهده کند تا بهروزرسانیهای بلادرنگ در مورد وضعیت اتصال را دریافت کند.
فعالیت خود را شروع کنید
اکنون که یک اکتیویتی پایه ایجاد کردهاید، میتوانید آن را روی عینک خود اجرا کنید. برای دسترسی به سختافزار عینک، برنامه شما باید اکتیویتی شما را با گزینههای خاصی که به سیستم میگوید از یک زمینهی پیشبینیشده استفاده کند، همانطور که در کد زیر نشان داده شده است، آغاز کند:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, GlassesMainActivity::class.java) context.startActivity(intent, options.toBundle())
متد createProjectedActivityOptions در ProjectedContext گزینههای لازم برای شروع فعالیت شما در یک زمینهی پیشبینیشده را تولید میکند. پارامتر context میتواند زمینهای از تلفن یا دستگاه عینک باشد.
مراحل بعدی
حالا که اولین فعالیت خود را برای عینکهای صوتی و عینکهای نمایشی ایجاد کردهاید، روشهای دیگری را که میتوانید عملکرد آن را گسترش دهید، بررسی کنید:
- مدیریت خروجی صدا با استفاده از تبدیل متن به گفتار
- مدیریت ورودی صدا با استفاده از تشخیص خودکار گفتار
- ساخت رابط کاربری با Jetpack Compose Glimmer
- دسترسی به سختافزار روی عینکهای صوتی و عینکهای نمایشگر