অডিও গ্লাস ও ডিসপ্লে গ্লাসের জন্য অগমেন্টেড অভিজ্ঞতা
আগে থেকেই থাকা Android Activity ফ্রেমওয়ার্ক API-এর উপর ভিত্তি করে তৈরি করা হয় এবং এতে অতিরিক্ত
ধারণা অন্তর্ভুক্ত থাকে, যা এইসব গ্লাসের অনন্য দিকগুলিকে সাপোর্ট করে। ডিভাইসে সম্পূর্ণ APK রান করে এমন XR হেডসেটের
মতো নয়, অডিও গ্লাস ও ডিসপ্লে গ্লাস একটি
ডেডিকেটেড অ্যাক্টিভিটি ব্যবহার করে যা আপনার ফোনের বর্তমান অ্যাপের মধ্যে রান করে। এই অ্যাক্টিভিটি
হোস্ট ডিভাইস থেকে গ্লাসে প্রজেক্ট করা হয়।
অডিও গ্লাস ও ডিসপ্লে গ্লাসের জন্য আপনার অ্যাপের অভিজ্ঞতা তৈরি করতে, আপনাকে
নতুন প্রজেক্টেড Activity তৈরি করে আপনার বর্তমান ফোন অ্যাপ এক্সটেন্ড করতে হবে। এই
অ্যাক্টিভিটি হল গ্লাসে আপনার অ্যাপ লঞ্চ করার প্রধান এন্ট্রি পয়েন্ট। এই
পদ্ধতি ডেভেলপমেন্টকে সহজ করে তোলে কারণ আপনি ফোন ও গ্লাসে
ব্যবসায়িক লজিক শেয়ার ও আবার ব্যবহার করতে পারেন।
ভার্সন কম্প্যাটিবিলিটি
Jetpack XR SDK-এর জন্য Android SDK-এর মানানসই হওয়ার প্রয়োজনীয়তা চেক করুন।
ডিপেন্ডেন্সি
নিম্নলিখিত অডিও গ্লাস ও ডিসপ্লে গ্লাসের জন্য লাইব্রেরি ডিপেন্ডেন্সি যোগ করুন:
গ্ৰুভি
dependencies {
implementation "androidx.xr.runtime:runtime:1.1.0-alpha01"
implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha18"
implementation "androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha18"
implementation "androidx.xr.projected:projected:1.0.0-alpha09"
implementation "androidx.xr.arcore:arcore:1.0.0-beta02"
}
Kotlin
dependencies {
implementation("androidx.xr.runtime:runtime:1.1.0-alpha01")
implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha18")
implementation("androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha18")
implementation("androidx.xr.projected:projected:1.0.0-alpha09")
implementation("androidx.xr.arcore:arcore:1.0.0-beta02")
}
আপনার অ্যাপের মেনিফেস্টে অ্যাক্টিভিটি ঘোষণা করা
অন্যান্য অ্যাক্টিভিটির মতোই, সিস্টেমকে দেখানোর ও চালানোর জন্য আপনাকে নিজের অ্যাপের ম্যানিফেস্ট ফাইলে অ্যাক্টিভিটি ঘোষণা করতে হবে।
<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 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) @Suppress("DEPRECATION") // TODO: Remove suppression once Android Emulator supports ProjectedActivityCompat.requestPermissions() // 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)) } }
কোড সম্পর্কে গুরুত্বপূর্ণ পয়েন্ট
- Jetpack Projected লাইব্রেরি থেকে অপ্ট-ইন API ব্যবহার করার জন্য অপ্ট-ইন করে।
ProjectedMainActivityComponentActivity-এর এক্সটেনশন, ঠিক যেমন আপনি মোবাইল ডেভেলপমেন্টে আশা করেন।- কারণ, সব গ্লাসে ডিসপ্লে থাকে না, তাই
ProjectedDeviceControllerব্যবহার করে ডিভাইসে ডিসপ্লে আছে কিনা তা চেক করুন। onCreateফাংশনের মধ্যে থাকাsetContentব্লকটি অ্যাক্টিভিটির জন্য কম্পোজ করা যায় এমন UI ট্রি-এর মূল নির্ধারণ করে। আপনি Jetpack Compose Glimmer ব্যবহার করেHomeScreenকম্পোজ করার উপযুক্ত আইটেম ইমপ্লিমেন্ট করবেন।- অ্যাক্টিভিটির
onCreateমেথড চলাকালীন UI ইনিশিয়ালাইজ করে (দেখুন প্রজেক্টেড অ্যাক্টিভিটি লাইফসাইকেল)। - ক্যামেরা-সম্পর্কিত ফিচারের জন্য প্রস্তুত হতে, যা
গ্লাস হার্ডওয়্যার অ্যাক্সেস করে, হার্ডওয়্যার সংক্রান্ত অনুমতির অনুরোধ করে, এর জন্য
অনুমতি লঞ্চার রেজিস্টার করা,
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) { ActionCard( title = { Text("Permission Required") }, action = { Button(onClick = onClose) { Text("Exit") } } ) { Text("Camera access is needed to use display glasses features.") Button(onClick = onRetryPermission) { Text("Retry") } } } else if (isVisualUiSupported) { ActionCard( title = { Text("Android XR") }, action = { Button(onClick = onClose) { Text("Close") } } ) { if (areVisualsOn) { Text("Hello, Display Glasses!") } else { Text("Display is off. Audio guidance active.") } } } else { Text("Audio Guidance Mode Active") } } }
কোড সম্পর্কে গুরুত্বপূর্ণ পয়েন্ট
- আপনি আগে অ্যাক্টিভিটিতে যেভাবে বর্ণনা করেছেন,
HomeScreenফাংশনে কম্পোজ করা যায় এমন কন্টেন্ট অন্তর্ভুক্ত থাকে যা গ্লাসের ডিসপ্লে চালু থাকলে ব্যবহারকারী দেখতে পান। - Jetpack Compose Glimmer
Textকম্পোনেন্ট, গ্লাসের ডিসপ্লেতে "হ্যালো, AI গ্লাস!" টেক্সট দেখায়। - প্রজেক্ট করা অ্যাক্টিভিটিতে Jetpack Compose Glimmer
ButtononClose-এর মাধ্যমেfinish()কল করে অ্যাক্টিভিটি বন্ধ করে দেয়।
অডিও বা ডিসপ্লে গ্লাস কানেক্ট করা আছে কিনা তা চেক করুন
আপনার অ্যাক্টিভিটি লঞ্চ করার আগে কোনও ব্যবহারকারীর অডিও বা ডিসপ্লে গ্লাস তার
ফোনের সাথে কানেক্ট করা আছে কিনা তা নির্ধারণ করতে, ProjectedContext.isProjectedDeviceConnected পদ্ধতি ব্যবহার করুন। এই পদ্ধতিটি
Flow<Boolean> রিটার্ন করে যা আপনার অ্যাপ কানেকশন স্ট্যাটাস সম্পর্কে
রিয়েল-টাইম আপডেট পেতে পর্যবেক্ষণ করতে পারে।
আপনার অ্যাক্টিভিটি শুরু করা
আপনি যেহেতু একটি প্রাথমিক অ্যাক্টিভিটি তৈরি করেছেন, তাই এখন এটি আপনার গ্লাসে লঞ্চ করতে পারবেন। গ্লাসের হার্ডওয়্যার অ্যাক্সেস করতে, আপনার অ্যাপকে অবশ্যই নির্দিষ্ট বিকল্পের সাথে অ্যাক্টিভিটি শুরু করতে হবে যা সিস্টেমকে প্রজেক্ট করা প্রসঙ্গ ব্যবহার করতে বলে, যেমনটি নিম্নলিখিত কোডে দেখানো হয়েছে:
val options = ProjectedContext.createProjectedActivityOptions(context) val intent = Intent(context, ProjectedMainActivity::class.java) context.startActivity(intent, options.toBundle())
ProjectedContext-এর createProjectedActivityOptions পদ্ধতি
প্রজেক্ট করা কন্টেক্সটে আপনার অ্যাক্টিভিটি শুরু করার জন্য প্রয়োজনীয় বিকল্প তৈরি করে।
context প্যারামিটারটি ফোন বা গ্লাস ডিভাইস থেকে নেওয়া কোনও প্রসঙ্গ হতে পারে।
পরবর্তী ধাপ
অডিও গ্লাস ও ডিসপ্লে গ্লাসের জন্য প্রথম অ্যাক্টিভিটি তৈরি করার পরে, এর কার্যকারিতা বাড়ানোর অন্যান্য উপায় এক্সপ্লোর করুন:
- টেক্সট-টু-স্পিচ ব্যবহার করে অডিও আউটপুট ম্যানেজ করা
- অটোমেটিক স্পিচ রিকগনিশন ব্যবহার করে অডিও ইনপুট ম্যানেজ করা
- Jetpack Compose Glimmer-এর মাধ্যমে UI তৈরি করা
- অডিও গ্লাস ও ডিসপ্লে গ্লাসের হার্ডওয়্যার অ্যাক্সেস করা