অডিও গ্লাস এবং ডিসপ্লে গ্লাসের জন্য আপনার প্রথম অ্যাক্টিভিটি তৈরি করুন

প্রযোজ্য এক্সআর ডিভাইস
এই নির্দেশিকা আপনাকে এই ধরনের এক্সআর ডিভাইসগুলির জন্য অভিজ্ঞতা তৈরি করতে সাহায্য করে।
অডিও এবং
ডিসপ্লে গ্লাস

অডিও গ্লাস এবং ডিসপ্লে গ্লাসের জন্য অগমেন্টেড এক্সপেরিয়েন্সগুলো বিদ্যমান অ্যান্ড্রয়েড Activity ফ্রেমওয়ার্ক এপিআই-এর উপর ভিত্তি করে তৈরি করা হয়েছে এবং এই গ্লাসগুলোর অনন্য বৈশিষ্ট্যগুলোকে সমর্থন করার জন্য এতে অতিরিক্ত ধারণা অন্তর্ভুক্ত রয়েছে । এক্সআর হেডসেটের মতো নয়, যেগুলো ডিভাইসে একটি সম্পূর্ণ এপিকে চালায়, অডিও গ্লাস এবং ডিসপ্লে গ্লাস একটি ডেডিকেটেড অ্যাক্টিভিটি ব্যবহার করে যা আপনার ফোনের বিদ্যমান অ্যাপের মধ্যেই চলে। এই অ্যাক্টিভিটিটি হোস্ট ডিভাইস থেকে গ্লাসগুলোতে প্রজেক্ট করা হয়।

অডিও গ্লাস এবং ডিসপ্লে গ্লাসের জন্য আপনার অ্যাপের অভিজ্ঞতা তৈরি করতে, আপনি একটি নতুন প্রোজেক্টেড Activity তৈরি করার মাধ্যমে আপনার বিদ্যমান ফোন অ্যাপটিকে প্রসারিত করেন। এই অ্যাক্টিভিটিটি গ্লাসে আপনার অ্যাপের প্রধান লঞ্চ এন্ট্রি পয়েন্ট হিসেবে কাজ করে। এই পদ্ধতিটি ডেভেলপমেন্টকে সহজ করে তোলে, কারণ আপনি আপনার ফোন এবং গ্লাসের অভিজ্ঞতার মধ্যে বিজনেস লজিক শেয়ার ও পুনঃব্যবহার করতে পারেন।

সংস্করণ সামঞ্জস্যতা

Jetpack XR SDK-এর জন্য Android 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>

কোড সম্পর্কে মূল বিষয়গুলো

  • android:requiredDisplayCategory অ্যাট্রিবিউটের জন্য xr_projected নির্দিষ্ট করা হয়, যা সিস্টেমকে জানায় যে এই অ্যাক্টিভিটি সংযুক্ত ডিভাইস থেকে হার্ডওয়্যার অ্যাক্সেস করার জন্য একটি প্রোজেক্টেড কনটেক্সট ব্যবহার করবে।

আপনার কার্যকলাপ তৈরি করুন

এরপরে, আপনি একটি ছোট অ্যাক্টিভিটি তৈরি করবেন যা ডিসপ্লে চালু হলেই এআই গ্লাসে কিছু একটা প্রদর্শন করতে পারবে।

@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))
    }
}

কোড সম্পর্কে মূল বিষয়গুলো

কম্পোজেবল বাস্তবায়ন করুন

আপনার তৈরি করা অ্যাক্টিভিটিটি একটি HomeScreen কম্পোজেবল ফাংশনকে রেফারেন্স করে, যা আপনাকে ইমপ্লিমেন্ট করতে হবে। নিম্নলিখিত কোডটি জেটপ্যাক কম্পোজ গ্লিমার ব্যবহার করে এমন একটি কম্পোজেবল সংজ্ঞায়িত করে যা চশমার ডিসপ্লেতে কিছু টেক্সট প্রদর্শন করতে পারে:

@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 ফাংশনটিতে সেই কম্পোজেবল কন্টেন্ট অন্তর্ভুক্ত থাকে যা ব্যবহারকারী চশমার ডিসপ্লে চালু থাকা অবস্থায় দেখতে পান।
  • Jetpack Compose-এর Glimmer Text কম্পোনেন্টটি চশমার ডিসপ্লেতে "Hello, AI Glasses!" লেখাটি প্রদর্শন করে।
  • Jetpack Compose Glimmer Button প্রজেক্টেড অ্যাক্টিভিটির onClose এর মাধ্যমে finish() কল করে অ্যাক্টিভিটিটি বন্ধ করে।

অডিও বা ডিসপ্লে গ্লাস সংযুক্ত আছে কিনা তা পরীক্ষা করুন।

আপনার অ্যাক্টিভিটি চালু করার আগে ব্যবহারকারীর অডিও বা ডিসপ্লে গ্লাস তার ফোনের সাথে সংযুক্ত আছে কিনা তা নির্ধারণ করতে, ProjectedContext.isProjectedDeviceConnected মেথডটি ব্যবহার করুন। এই মেথডটি একটি Flow<Boolean> রিটার্ন করে, যা আপনার অ্যাপ সংযোগের অবস্থার রিয়েল-টাইম আপডেট পেতে পর্যবেক্ষণ করতে পারে।

আপনার কার্যকলাপ শুরু করুন

এখন যেহেতু আপনি একটি বেসিক অ্যাক্টিভিটি তৈরি করেছেন, আপনি এটি আপনার চশমায় চালু করতে পারেন। চশমার হার্ডওয়্যার অ্যাক্সেস করার জন্য, আপনার অ্যাপকে অবশ্যই নির্দিষ্ট অপশনসহ অ্যাক্টিভিটি শুরু করতে হবে, যা সিস্টেমকে একটি প্রোজেক্টেড কনটেক্সট ব্যবহার করতে নির্দেশ দেয়, যেমনটি নিম্নলিখিত কোডে দেখানো হয়েছে:

val options = ProjectedContext.createProjectedActivityOptions(context)
val intent = Intent(context, GlassesMainActivity::class.java)
context.startActivity(intent, options.toBundle())

ProjectedContext এর createProjectedActivityOptions মেথডটি আপনার অ্যাক্টিভিটিকে একটি প্রোজেক্টেড কনটেক্সটে শুরু করার জন্য প্রয়োজনীয় অপশনগুলো তৈরি করে। context প্যারামিটারটি ফোন বা চশমা ডিভাইসের একটি কনটেক্সট হতে পারে।

পরবর্তী পদক্ষেপ

এখন যেহেতু আপনি অডিও গ্লাস এবং ডিসপ্লে গ্লাসের জন্য আপনার প্রথম অ্যাক্টিভিটি তৈরি করে ফেলেছেন, এর কার্যকারিতা আরও বাড়ানোর অন্যান্য উপায়গুলো অন্বেষণ করুন: