একটি Wear OS মডিউল ইন্টিগ্রেট করুন

Wear OS দ্বারা চালিত পরিধানযোগ্য ডিভাইসগুলিতে এটিকে প্রসারিত করে আপনার অ্যাপের স্বাস্থ্য এবং ফিটনেস অভিজ্ঞতা উন্নত করুন৷

একটি Wear OS মডিউল যোগ করুন

Android স্টুডিও আপনার অ্যাপে একটি Wear OS মডিউল যোগ করার জন্য একটি সহজ উইজার্ড প্রদান করে। ফাইল > নতুন মডিউল মেনুতে, নিম্নলিখিত ছবিতে দেখানো হিসাবে Wear OS নির্বাচন করুন:

অ্যান্ড্রয়েড স্টুডিওতে ওএস মডিউল উইজার্ড পরিধান করুন
চিত্র 1 : একটি Wear OS মডিউল তৈরি করুন

এটা মনে রাখা গুরুত্বপূর্ণ যে আপনাকে স্বাস্থ্য পরিষেবার সর্বশেষ সংস্করণ ব্যবহার করতে দিতে ন্যূনতম SDK অবশ্যই API 30 বা তার বেশি হতে হবে। স্বাস্থ্য পরিষেবা স্বয়ংক্রিয়ভাবে স্বাস্থ্য সেন্সর কনফিগার করে মেট্রিক্স ট্র্যাক করা এবং ডেটা রেকর্ড করা সহজ করে তোলে।

আপনি উইজার্ড সম্পূর্ণ করার পরে, আপনার প্রকল্প সিঙ্ক করুন। নিম্নলিখিত রান কনফিগারেশন প্রদর্শিত হবে:

Wear OS অ্যাপ রান বোতাম দেখানো একটি ছবি
ছবি 2 : নতুন Wear OS মডিউলের জন্য রান বোতাম

এটি আপনাকে পরিধানযোগ্য ডিভাইসে Wear OS মডিউল চালাতে দেয়। আপনার দুটি বিকল্প আছে:

কনফিগারেশনটি চালানোর ফলে অ্যাপটিকে Wear OS এমুলেটর বা ডিভাইসে স্থাপন করা হয় এবং একটি "হ্যালো ওয়ার্ল্ড" অভিজ্ঞতা দেখায়। এটি হল বেসিক UI সেটআপ, কম্পোজ ফর Wear OS ব্যবহার করে, আপনার অ্যাপ শুরু করতে।

স্বাস্থ্য পরিষেবা এবং হিল্ট যোগ করুন

আপনার Wear OS মডিউলে নিম্নলিখিত লাইব্রেরিগুলিকে একীভূত করুন:

  • স্বাস্থ্য পরিষেবা : ঘড়িতে সেন্সর এবং ডেটা অ্যাক্সেস করা খুব সুবিধাজনক এবং আরও শক্তি-দক্ষ করে তোলে।
  • হিল্ট : কার্যকর নির্ভরতা ইনজেকশন এবং পরিচালনার জন্য অনুমতি দেয়।

স্বাস্থ্য পরিষেবা ম্যানেজার তৈরি করুন

স্বাস্থ্য পরিষেবাগুলিকে আরও কিছুটা সুবিধাজনক করতে এবং একটি ছোট এবং মসৃণ API প্রকাশ করতে, আপনি এইরকম একটি মোড়ক তৈরি করতে পারেন:

private const val TAG = "WATCHMAIN"

class HealthServicesManager(context: Context) {
    private val measureClient = HealthServices.getClient(context).measureClient

    suspend fun hasHeartRateCapability() = runCatching {
        val capabilities = measureClient.getCapabilities()
        (DataType.HEART_RATE_BPM in capabilities.supportedDataTypesMeasure)
    }.getOrDefault(false)

    /**
     * Returns a cold flow. When activated, the flow will register a callback for heart rate data
     * and start to emit messages. When the consuming coroutine is canceled, the measure callback
     * is unregistered.
     *
     * [callbackFlow] creates a  bridge between a callback-based API and Kotlin flows.
     */
    @ExperimentalCoroutinesApi
    fun heartRateMeasureFlow(): Flow<MeasureMessage> = callbackFlow {
        val callback = object : MeasureCallback {
            override fun onAvailabilityChanged(dataType: DeltaDataType<*, *>, availability: Availability) {
                // Only send back DataTypeAvailability (not LocationAvailability)
                if (availability is DataTypeAvailability) {
                    trySendBlocking(MeasureMessage.MeasureAvailability(availability))
                }
            }

            override fun onDataReceived(data: DataPointContainer) {
                val heartRateBpm = data.getData(DataType.HEART_RATE_BPM)
                Log.d(TAG, "💓 Received heart rate: ${heartRateBpm.first().value}")
                trySendBlocking(MeasureMessage.MeasureData(heartRateBpm))
            }
        }

        Log.d(TAG, "⌛ Registering for data...")
        measureClient.registerMeasureCallback(DataType.HEART_RATE_BPM, callback)

        awaitClose {
            Log.d(TAG, "👋 Unregistering for data")
            runBlocking {
                measureClient.unregisterMeasureCallback(DataType.HEART_RATE_BPM, callback)
            }
        }
    }
}

sealed class MeasureMessage {
    class MeasureAvailability(val availability: DataTypeAvailability) : MeasureMessage()
    class MeasureData(val data: List<SampleDataPoint<Double>>) : MeasureMessage()
}

একবার আপনি নিম্নলিখিত স্নিপেট ব্যবহার করে এটি পরিচালনা করার জন্য হিল্ট মডিউল তৈরি করেছেন:

@Module
@InstallIn(SingletonComponent::class)
internal object DataModule {
    @Provides
    @Singleton
    fun provideHealthServices(@ApplicationContext context: Context): HealthServicesManager = HealthServicesManager(context)
}

আপনি অন্য যেকোন হিল্ট নির্ভরতা হিসাবে HealthServicesManager ইনজেক্ট করতে পারেন।

নতুন HealthServicesManager একটি heartRateMeasureFlow() পদ্ধতি প্রদান করে যা হার্ট মনিটরের জন্য একজন শ্রোতাকে নিবন্ধন করে এবং প্রাপ্ত ডেটা নির্গত করে।

পরিধানযোগ্য ডিভাইসে ডেটা আপডেট সক্ষম করুন

ফিটনেস-সম্পর্কিত ডেটা আপডেটের জন্য BODY_SENSORS অনুমতি প্রয়োজন। যদি আপনি ইতিমধ্যে এটি না করে থাকেন, তাহলে আপনার অ্যাপের ম্যানিফেস্ট ফাইলে BODY_SENSORS অনুমতি ঘোষণা করুন৷ তারপরে, এই স্নিপেটে দেখানো হিসাবে, অনুমতির জন্য অনুরোধ করুন:

val permissionState = rememberPermissionState(
    permission = Manifest.permission.BODY_SENSORS,
    onPermissionResult = { granted -> /* do something */ }
)

[...]

if (permissionState.status.isGranted) {
    // do something
} else {
    permissionState.launchPermissionRequest()
}

আপনি যদি কোনও শারীরিক ডিভাইসে আপনার অ্যাপটি পরীক্ষা করেন তবে ডেটা আপডেট হওয়া শুরু করা উচিত।

Wear OS 4 থেকে শুরু করে, এমুলেটরগুলি স্বয়ংক্রিয়ভাবে পরীক্ষার ডেটাও দেখায়। পূর্ববর্তী সংস্করণগুলিতে, আপনি সেন্সর থেকে ডেটা স্ট্রিম অনুকরণ করতে পারেন। একটি টার্মিনাল উইন্ডোতে, এই ADB কমান্ডটি চালান:

adb shell am broadcast \
-a "whs.USE_SYNTHETIC_PROVIDERS" \
com.google.android.wearable.healthservices

হার্টের হারের বিভিন্ন মান দেখতে, বিভিন্ন ব্যায়াম অনুকরণ করার চেষ্টা করুন। এই কমান্ডটি হাঁটার অনুকরণ করে:

adb shell am broadcast \
-a "whs.synthetic.user.START_WALKING" \
com.google.android.wearable.healthservices

এই কমান্ডটি চলমান অনুকরণ করে:

adb shell am broadcast \
-a "whs.synthetic.user.START_RUNNING" \
com.google.android.wearable.healthservices

ডেটা অনুকরণ বন্ধ করতে, এই কমান্ডটি চালান:

adb shell am broadcast -a \
"whs.USE_SENSOR_PROVIDERS" \
com.google.android.wearable.healthservices

হার্ট রেট ডেটা পড়ুন

BODY_SENSORS অনুমতি দিয়ে, আপনি HealthServicesManager এ ব্যবহারকারীর হৃদস্পন্দন ( heartRateMeasureFlow() ) পড়তে পারেন৷ Wear OS অ্যাপের UI-তে, পরিধানযোগ্য ডিভাইসে সেন্সর দ্বারা পরিমাপ করা হচ্ছে, বর্তমান হার্ট রেট মান প্রদর্শিত হয়।

আপনার ViewModel , হার্ট রেট ফ্লো অবজেক্ট ব্যবহার করে ডেটা সংগ্রহ করা শুরু করুন, যেমনটি নিম্নলিখিত স্নিপেটে দেখানো হয়েছে:

val hr: MutableState<Double> = mutableStateOf(0.0)

[...]

healthServicesManager
    .heartRateMeasureFlow()
    .takeWhile { enabled.value }
    .collect { measureMessage ->
        when (measureMessage) {
            is MeasureData -> {
                val latestHeartRateValue = measureMessage.data.last().value
                hr.value = latestHeartRateValue
            }

            is MeasureAvailability -> availability.value =
                    measureMessage.availability
        }
    }

আপনার অ্যাপের UI-তে লাইভ ডেটা প্রদর্শন করতে নিম্নলিখিতগুলির মতো একটি রচনাযোগ্য বস্তু ব্যবহার করুন:

val heartRate by viewModel.hr

Text(
  text = "Heart Rate: $heartRate",
  style = MaterialTheme.typography.display1
)

একটি হ্যান্ডহেল্ড ডিভাইসে ডেটা পাঠান

একটি হ্যান্ডহেল্ড ডিভাইসে স্বাস্থ্য এবং ফিটনেস ডেটা পাঠাতে, স্বাস্থ্য পরিষেবাগুলিতে DataClient ক্লাস ব্যবহার করুন। নিম্নলিখিত কোড স্নিপেট দেখায় যে কীভাবে আপনার অ্যাপটি আগে সংগৃহীত হার্ট রেট ডেটা পাঠাতে হয়:

class HealthServicesManager(context: Context) {
    private val dataClient by lazy { Wearable.getDataClient(context) }

[...]

    suspend fun sendToHandheldDevice(heartRate: Int) {
        try {
            val result = dataClient
                .putDataItem(PutDataMapRequest
                    .create("/heartrate")
                    .apply { dataMap.putInt("heartrate", heartRate) }
                    .asPutDataRequest()
                    .setUrgent())
                .await()

            Log.d(TAG, "DataItem saved: $result")
        } catch (cancellationException: CancellationException) {
            throw cancellationException
        } catch (exception: Exception) {
            Log.d(TAG, "Saving DataItem failed: $exception")
        }
    }
}

ফোনে ডেটা গ্রহণ করুন

ফোনে ডেটা পেতে, একটি WearableListenerService তৈরি করুন:

@AndroidEntryPoint
class DataLayerListenerService : WearableListenerService() {

    @Inject
    lateinit var heartRateMonitor: HeartRateMonitor

    override fun onDataChanged(dataEvents: DataEventBuffer) {

        dataEvents.forEach { event ->
            when (event.type) {
                DataEvent.TYPE_CHANGED -> {
                    event.dataItem.run {
                        if (uri.path?.compareTo("/heartrate") == 0) {
                            val heartRate = DataMapItem.fromDataItem(this)
                                    .dataMap.getInt(HR_KEY)
                            Log.d("DataLayerListenerService",
                                    "New heart rate value received: $heartRate")
                            heartRateMonitor.send(heartRate)
                        }
                    }
                }

                DataEvent.TYPE_DELETED -> {
                    // DataItem deleted
                }
            }
        }
    }
}

এই ধাপটি সম্পূর্ণ করার পরে, কয়েকটি আকর্ষণীয় বিবরণ লক্ষ্য করুন:

  • @AndroidEntryPoint টীকাটি আমাদের এই ক্লাসে হিল্ট ব্যবহার করতে দেয়
  • @Inject lateinit var heartRateMonitor: HeartRateMonitor প্রকৃতপক্ষে এই ক্লাসে একটি নির্ভরতা ইনজেক্ট করবে
  • ক্লাসটি onDataChanged() প্রয়োগ করে এবং ইভেন্টগুলির একটি সংগ্রহ পায় যা আপনি পার্স এবং ব্যবহার করতে পারেন

নিম্নলিখিত HeartRateMonitor যুক্তি আপনাকে আপনার অ্যাপের কোডবেসের অন্য অংশে প্রাপ্ত হার্ট রেট মান পাঠাতে দেয়:

class HeartRateMonitor {
    private val datapoints = MutableSharedFlow<Int>(extraBufferCapacity = 10)

    fun receive(): SharedFlow<Int> = datapoints.asSharedFlow()

    fun send(hr: Int) {
        datapoints.tryEmit(hr)
    }
}

একটি ডেটা বাস onDataChanged() পদ্ধতি থেকে ইভেন্টগুলি গ্রহণ করে এবং একটি SharedFlow ব্যবহার করে ডেটা পর্যবেক্ষকদের কাছে উপলব্ধ করে।

চূড়ান্ত বিট হল ফোন অ্যাপ্লিকেশন AndroidManifest.xmlService ঘোষণা:

<service
    android:name=".DataLayerListenerService"
    android:exported="true">
    <intent-filter>
        <!-- listeners receive events that match the action and data filters -->
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
        <data
            android:host="*"
            android:pathPrefix="/heartrate"
            android:scheme="wear" />
    </intent-filter>
</service>

একটি হ্যান্ডহেল্ড ডিভাইসে রিয়েল-টাইম ডেটা দেখান

আপনার অ্যাপের যে অংশটি একটি হ্যান্ডহেল্ড ডিভাইসে চলে, সেখানে আপনার ভিউ মডেলের কনস্ট্রাক্টরে HeartRateMonitor ইনজেক্ট করুন। এই HeartRateMonitor অবজেক্ট হার্ট রেট ডেটা পর্যবেক্ষণ করে এবং প্রয়োজন অনুযায়ী UI আপডেট নির্গত করে।