ধাপ ট্র্যাক করা

Health Connect স্টেপ ডেটা টাইপ প্রদান করে যা StepsRecord ব্যবহার করে স্টেপ কাউন্ট রেকর্ড করে। স্বাস্থ্য ও ফিটনেস ট্র্যাকিংয়ের ক্ষেত্রে স্টেপ হল একটি মৌলিক পরিমাপ।

এই গাইড Health Connect ভার্সন ১.১.০-alpha১২ বা তার পরবর্তী ভার্সনের সাথে মানানসই।

মোবাইল স্টেপ সংক্রান্ত ডেটা পড়ুন

Android 14 (API লেভেল 34) এবং SDK এক্সটেনশন ভার্সন 20 বা তার পরবর্তী ভার্সনের সাথে, Health Connect ডিভাইসে স্টেপ কাউন্টিংয়ের সুবিধা প্রদান করে। কোনও অ্যাপকে READ_STEPS অনুমতি দেওয়া হলে, Health Connect, Android-পরিচালিত ডিভাইস থেকে স্টেপ সংক্রান্ত ডেটা ক্যাপচার করা শুরু করে এবং ব্যবহারকারীরা Health Connect স্টেপ এন্ট্রিতে অটোমেটিক যোগ করা স্টেপ সংক্রান্ত ডেটা দেখতে পান।

অন-ডিভাইস স্টেপ কাউন্টিং উপলভ্য কিনা তা চেক করতে, ডিভাইসটি Android 14 (API লেভেল ৩৪) ভার্সনে চলছে কিনা এবং কমপক্ষে SDK এক্সটেনশন ভার্সন ২০ আছে কিনা তা যাচাই করুন:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

আপনার অ্যাপ যদি aggregate ব্যবহার করে মোট স্টেপ কাউন্ট রিড করে এবং DataOrigin-এর মাধ্যমে ফিল্টার না করে, তাহলে অন-ডিভাইস স্টেপ অটোমেটিক মোট স্টেপ কাউন্টে অন্তর্ভুক্ত করা হয় এবং জুন ২০২৬-এর আপডেটের জন্য কোনও পরিবর্তন করার প্রয়োজন নেই।

অন-ডিভাইস স্টেপের জন্য অ্যাট্রিবিউশন পরিবর্তন

জুন ২০২৬ আপডেট থেকে শুরু করে, Health Connect-এর মাধ্যমে নেটিভভাবে ট্র্যাক করা পদক্ষেপগুলি একটি সিন্থেটিক প্যাকেজের নাম (SPN)-এর সাথে অ্যাট্রিবিউট করা হয়, যেমন com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e।

আগে, বিল্ট-ইন স্টেপ android প্যাকেজের নামের সাথে অ্যাট্রিবিউট করা ছিল। জুন ২০২৬-এর আগে রেকর্ড করা ঐতিহাসিক স্টেপ ডেটা android প্যাকেজের নাম সংরক্ষণ করে।

SPN হল ডিভাইস-নির্দিষ্ট এবং ব্যবহারকারীর গোপনীয়তা রক্ষা করার জন্য প্রতিটি অ্যাপ্লিকেশনের ভিত্তিতে স্কোপ করা হয়:

  • স্টেবল: বর্তমান ডিভাইসের SPN আপনার অ্যাপ্লিকেশনের জন্য স্টেবল।
  • অ্যাপ্লিকেশন-স্কোপড: একই ডিভাইসে বিভিন্ন অ্যাপ্লিকেশন অন-ডিভাইস স্টেপ ডেটার জন্য আলাদা আলাদা SPN দেখে।

অন-ডিভাইস ধাপের জন্য কোয়েরি

SPN-এর স্কোপ আছে এবং এটি ডিভাইস-নির্দিষ্ট, তাই আপনি SPN ভ্যালু হার্ডকোড করবেন না। পরিবর্তে, বর্তমান ডিভাইসের জন্য SPN পেতে getCurrentDeviceDataSource API ব্যবহার করুন।

ডিভাইসে স্টেপ কাউন্টিংয়ের জন্য SDK এক্সটেনশন ভার্সন ২০ বা তার পরবর্তী যেকোনও ভার্সন প্রয়োজন হলেও, getCurrentDeviceDataSource() API, Android 14 (API লেভেল ৩৪) ও SDK এক্সটেনশন ভার্সন ২২ বা তার পরবর্তী যেকোনও ভার্সনে উপলভ্য। এই API ব্যবহার করতে, আপনার মডিউল-লেভেল build.gradle.kts বা build.gradle ফাইলে compileSdkExtension-কে 22 বা তার বেশি হিসেবে সেট করুন:

Kotlin

android {
    compileSdk = 35
    compileSdkExtension = 22
}

গ্ৰুভি

android {
    compileSdk 35
    compileSdkExtension 22
}

Health Connect Jetpack লাইব্রেরিতে getCurrentDeviceDataSource() API এখনও উপলভ্য নেই। নিম্নলিখিত উদাহরণে Android ফ্রেমওয়ার্ক API ব্যবহার করা হয়েছে, যার জন্য Executor এবং OutcomeReceiver কলব্যাক প্রয়োজন:

import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.OutcomeReceiver

val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
healthConnectManager?.getCurrentDeviceDataSource(
    context.mainExecutor,
    object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
        override fun onResult(result: DeviceDataSource) {
            val currentDeviceSpn = result.deviceDataOrigin.packageName
        }

        override fun onError(error: HealthConnectException) {
            // Handle error
        }
    }
)

আপনার অ্যাপকে যদি অন-ডিভাইস স্টেপ ডেটা পড়তে হয় অথবা এটি যদি সোর্স অ্যাপ্লিকেশন বা ডিভাইস অনুযায়ী স্টেপ ডেটা দেখায়, তাহলে আপনাকে এমন রেকর্ড কোয়েরি করতে হবে যেখানে DataOrigin হল android অথবা ডিভাইসের SPN-এর সাথে ম্যাচ করে। আপনার অ্যাপ যদি স্টেপ ডেটার জন্য অ্যাট্রিবিউশন দেখায়, তাহলে স্বতন্ত্র রেকর্ডের জন্য সোর্স ডিভাইস শনাক্ত করতে metadata.device ব্যবহার করুন। মোট ডেটায় SPN দ্বারা শনাক্ত করা অন-ডিভাইস ধাপের জন্য, আপনি অ্যাট্রিবিউশনের জন্য DeviceDataSource থেকে model বা manufacturer-এর মতো ডিভাইস মেটাডেটা ব্যবহার করতে পারেন অথবা অন-ডিভাইস ধাপের জন্য "আপনার ফোন"-এর মতো জেনেরিক লেবেল ব্যবহার করতে পারেন।

নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে কীভাবে android এবং বর্তমান ডিভাইসের SPN, উভয়ের জন্য ফিল্টার করে, ডিভাইসে স্টেপ কাউন্টের মোট ডেটা পড়া যায়:

import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.OutcomeReceiver
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine

suspend fun readDeviceStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    context: Context,
    startTime: Instant,
    endTime: Instant
) {
    // 1. Check if SDK Extension 22+ is available for getCurrentDeviceDataSource()
    val isDataSourceApiAvailable =
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
            SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 22

    try {
        val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)

        // 2. Safely fetch the package name only if the API is available
        val currentDeviceSpn = if (isDataSourceApiAvailable && healthConnectManager != null) {
            suspendCancellableCoroutine { continuation ->
                healthConnectManager.getCurrentDeviceDataSource(
                    context.mainExecutor,
                    object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
                        override fun onResult(result: DeviceDataSource) {
                            continuation.resume(result.deviceDataOrigin.packageName)
                        }

                        override fun onError(error: HealthConnectException) {
                            continuation.resumeWithException(error)
                        }
                    }
                )
            }
        } else {
            null
        }

        val dataOriginFilters = mutableSetOf(DataOrigin("android"))

        // 3. Explicit null-safety check using .let
        currentDeviceSpn?.let {
            dataOriginFilters.add(DataOrigin(it))
        }

        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = dataOriginFilters
            )
        )

        val stepCount = response[StepsRecord.COUNT_TOTAL]

    } catch (e: Exception) {
        // Now this catch block only handles actual runtime exceptions,
        // rather than Errors from missing methods.
    }
}

অন-ডিভাইস স্টেপ কাউন্টিং

  • সেন্সর ব্যবহার: Health Connect SensorManager থেকে TYPE_STEP_COUNTER সেন্সর ব্যবহার করে। এই সেন্সরটি কম বিদ্যুৎ খরচের জন্য অপ্টিমাইজ করা হয়েছে, যা এটিকে ক্রমাগত ব্যাকগ্রাউন্ড স্টেপ ট্র্যাকিংয়ের জন্য আদর্শ করে তুলেছে।
  • ডেটা গ্র্যানুলারিটি: ব্যাটারির আয়ু বাঁচাতে, স্টেপ ডেটা সাধারণত ব্যাচ করা হয় এবং Health Connect ডেটাবেসে প্রতি মিনিটে একবারের বেশি লেখা হয় না।
  • অ্যাট্রিবিউশন: জুন ২০২৬-এর আগে এই ফিচারের মাধ্যমে রেকর্ড করা ধাপগুলি DataOrigin-এ android প্যাকেজের নামের সাথে অ্যাট্রিবিউট করা হয়। এই তারিখের পরে, সেগুলি ডিভাইস-নির্দিষ্ট SPN-এ অ্যাট্রিবিউট করা হয়। অন-ডিভাইস স্টেপের জন্য অ্যাট্রিবিউশন পরিবর্তন দেখুন।
  • অ্যাক্টিভেশন: ডিভাইসে অন্তত একটি অ্যাপ্লিকেশনকে Health Connect-এর মধ্যে READ_STEPS অনুমতি দেওয়া হলেই ডিভাইসে স্টেপ গণনা করার মেকানিজম অ্যাক্টিভ হয়।

Health Connect উপলভ্য কিনা তা চেক করা

Health Connect ব্যবহার করার চেষ্টা করার আগে, আপনার অ্যাপকে যাচাই করতে হবে যে ব্যবহারকারীর ডিভাইসে Health Connect উপলভ্য আছে কিনা। সব ডিভাইসে Health Connect আগে থেকে ইনস্টল করা নাও থাকতে পারে অথবা বন্ধ করা থাকতে পারে। আপনি HealthConnectClient.getSdkStatus() পদ্ধতি ব্যবহার করে উপলভ্যতা চেক করতে পারবেন।

Health Connect উপলভ্য কিনা তা কীভাবে চেক করবেন

fun checkHealthConnectAvailability(context: Context) {
    val providerPackageName = "com.google.android.apps.healthdata"
    val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName)

    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
      // Health Connect is not available. Guide the user to install/enable it.
      // For example, show a dialog.
      return // early return as there is no viable integration
    }
    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
      // Health Connect is available but requires an update.
      // Optionally redirect to package installer to find a provider, for example:
      val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
      context.startActivity(
        Intent(Intent.ACTION_VIEW).apply {
          setPackage("com.android.vending")
          data = Uri.parse(uriString)
          putExtra("overlay", true)
          putExtra("callerId", context.packageName)
        }
      )
      return
    }
    // Health Connect is available, obtain a HealthConnectClient instance
    val healthConnectClient = HealthConnectClient.getOrCreate(context)
    // Issue operations with healthConnectClient
}

getSdkStatus()-এর থেকে পাওয়া স্ট্যাটাসের উপর নির্ভর করে, আপনি ব্যবহারকারীকে প্রয়োজন হলে Google Play Store থেকে Health Connect ইনস্টল বা আপডেট করার জন্য নির্দেশ দিতে পারেন।

প্রয়োজনীয় অনুমতি

নিম্নলিখিত অনুমতি দ্বারা ধাপের অ্যাক্সেস সুরক্ষিত করা হয়:

  • android.permission.health.READ_STEPS
  • android.permission.health.WRITE_STEPS

আপনার অ্যাপে স্টেপ সংক্রান্ত ক্ষমতা যোগ করতে, Steps ডেটার ধরনের জন্য অনুমতি চাওয়ার মাধ্যমে শুরু করুন।

স্টেপ লেখার জন্য আপনাকে এই অনুমতি ঘোষণা করতে হবে:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_STEPS" />
...
</application>

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

<application>
  <uses-permission
android:name="android.permission.health.READ_STEPS" />
...
</application>

ব্যবহারকারীর থেকে অনুমতি চাওয়া

ক্লায়েন্ট ইনস্ট্যান্স তৈরি করার পরে, আপনার অ্যাপকে ব্যবহারকারীর থেকে অনুমতি চাইতে হবে। ব্যবহারকারীকে যেকোনও সময় অনুমতি দেওয়া বা প্রত্যাখ্যান করার সুবিধা দিতে হবে। এটি করতে, প্রয়োজনীয় ডেটার ধরনের জন্য অনুমতির একটি সেট তৈরি করুন। সেটে থাকা অনুমতিগুলি আপনার Android ম্যানিফেস্টে প্রথমে ঘোষণা করা হয়েছে কিনা তা নিশ্চিত করুন।

val permissions =
    setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
আপনার অ্যাপে আগে থেকেই প্রয়োজনীয় অনুমতি দেওয়া আছে কিনা তা দেখতে getGrantedPermissions ব্যবহার করুন। যদি না হয়, তাহলে createRequestPermissionResultContract ব্যবহার করে সেইসব অনুমতির জন্য অনুরোধ করুন। এটি Health Connect-এর অনুমতি সংক্রান্ত স্ক্রিন দেখায়।
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
ব্যবহারকারীরা যেকোনও সময় অনুমতি দিতে বা তুলে নিতে পারেন, তাই আপনার অ্যাপকে প্রতিবার ব্যবহার করার আগে অনুমতি চেক করতে হবে এবং অনুমতি না থাকলে পরিস্থিতি সামাল দিতে হবে।

স্টেপ রেকর্ডে অন্তর্ভুক্ত তথ্য

প্রতিটি StepsRecord-এ নিম্নলিখিত তথ্য থাকে:

  • count: সময়ের ব্যবধানে কতগুলি ধাপ নেওয়া হয়েছে, Long হিসেবে।
  • startTime: পরিমাপের ইন্টারভ্যালের শুরুর সময়।
  • endTime: পরিমাপের ইন্টারভ্যাল শেষ হওয়ার সময়।
  • startZoneOffset: শুরুর সময়ের জন্য জোন অফসেট।
  • endZoneOffset: শেষ হওয়ার সময়ের জন্য জোন অফসেট।

যেসব অ্যাগ্রিগেশন ব্যবহার করা যায়

StepsRecord-এর জন্য নিম্নলিখিত মোট ভ্যালু উপলভ্য:

StepsCadenceRecord-এর জন্য নিম্নলিখিত মোট ভ্যালু উপলভ্য:

ব্যবহারের উদাহরণ

StepsRecord ডেটা কীভাবে পড়তে ও লিখতে হয় তা নিম্নলিখিত বিভাগে দেখানো হয়েছে।

পদক্ষেপের ডেটা লিখুন

আপনার অ্যাপ StepsRecord ইনস্ট্যান্স যোগ করে স্টেপ কাউন্ট ডেটা লিখতে পারে। ব্যবহারকারীর নেওয়া ১০০০টি পদক্ষেপ কীভাবে রেকর্ড করতে হয় তা নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

মোট ডেটা পড়া

স্টেপ ডেটা পড়ার সবচেয়ে সাধারণ উপায় হল, নির্দিষ্ট সময়সীমার মধ্যে মোট স্টেপ অ্যাগ্রিগেট করা। নির্দিষ্ট সময়সীমার মধ্যে কোনও ব্যবহারকারীর মোট স্টেপ কাউন্ট কীভাবে পড়তে হয় তা নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long {
    val response = healthConnectClient.aggregate(
        AggregateRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
    return response[StepsRecord.COUNT_TOTAL] ?: 0L
}

প্রসেস না করা ডেটা পড়া

নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে শুরু ও শেষ হওয়ার সময়ের মধ্যে কীভাবে র StepsRecord ডেটা পড়তে হয়:

val response = healthConnectClient.readRecords(
    ReadRecordsRequest(
        StepsRecord::class,
        timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
    )
)
response.records.forEach { record ->
    /* Process records */
}