পটভূমিতে ডেটা মনিটর করুন

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

প্যাসিভ ডেটা ব্যবহারের উদাহরণের জন্য, GitHub-এ প্যাসিভ ডেটা এবং প্যাসিভ গোলের নমুনাগুলি দেখুন।

নির্ভরতা যোগ করুন

স্বাস্থ্য পরিষেবার উপর নির্ভরতা যোগ করতে, আপনাকে অবশ্যই আপনার প্রকল্পে Google Maven সংগ্রহস্থল যোগ করতে হবে। আরও তথ্যের জন্য, Google এর Maven সংগ্রহস্থল দেখুন।

আপনার মডিউল-স্তরের build.gradle ফাইলে, নিম্নলিখিত নির্ভরতা যোগ করুন:

গ্রোভি

dependencies {
    implementation "androidx.health:health-services-client:1.1.0-alpha03"
}

কোটলিন

dependencies {
    implementation("androidx.health:health-services-client:1.1.0-alpha03")
}

ক্ষমতা পরীক্ষা করুন

ডেটা আপডেটের জন্য নিবন্ধন করার আগে, ডিভাইসটি আপনার অ্যাপের প্রয়োজনীয় ডেটা সরবরাহ করতে পারে কিনা তা পরীক্ষা করুন। ক্ষমতা পরীক্ষা করা আপনাকে নির্দিষ্ট বৈশিষ্ট্যগুলিকে সক্ষম বা অক্ষম করতে বা উপলব্ধ নয় এমন বৈশিষ্ট্যগুলির জন্য ক্ষতিপূরণ দিতে আপনার অ্যাপের UI পরিবর্তন করতে দেয়৷

val healthClient = HealthServices.getClient(this /*context*/)
val passiveMonitoringClient = healthClient.passiveMonitoringClient
lifecycleScope.launchWhenCreated {
    val capabilities = passiveMonitoringClient.capabilities.await()
    // Supported types for passive data collection
    supportsHeartRate =
        DataType.HEART_RATE_BPM in capabilities.supportedDataTypesPassiveMonitoring
    // Supported types for PassiveGoals
    supportsStepsGoal =
        DataType.STEPS_DAILY in capabilities.supportedDataTypesPassiveGoals
}

প্যাসিভ ডেটার জন্য নিবন্ধন করুন

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

আপনি যে পদ্ধতিই ব্যবহার করুন না কেন, প্রথমে একটি PassiveListenerConfig তৈরি করুন যা নির্ধারণ করে যে কোন ধরনের ডেটা গ্রহণ করা হবে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDataTypes(setOf(DataType.HEART_RATE_BPM))
    .build()

একটি কলব্যাক ব্যবহার করে ডেটা গ্রহণ করতে, নিম্নলিখিত উদাহরণে দেখানো হিসাবে কলব্যাকটি সংজ্ঞায়িত করুন এবং নিবন্ধন করুন:

val passiveListenerCallback: PassiveListenerCallback = object : PassiveListenerCallback {
    override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
        // TODO: Do something with dataPoints
    }
}

passiveMonitoringClient.setPassiveListenerCallback(
    passiveListenerConfig,
    passiveListenerCallback
)

// To remove the listener
passiveMonitoringClient.clearPassiveListenerCallbackAsync()

একটি পরিষেবা ব্যবহার করা একই রকম, তবে PassiveListenerCallback থেকে প্রাপ্ত একটি ক্লাস তৈরি করার পরিবর্তে, PassiveListenerService থেকে প্রাপ্ত, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

class PassiveDataService : PassiveListenerService() {
    override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
        // TODO: Do something with dataPoints
    }
}

passiveMonitoringClient.setPassiveListenerServiceAsync(
    PassiveDataService::class.java,
    passiveListenerConfig
)

এরপর, আপনার AndroidManifest.xml ফাইলে পরিষেবাটি ঘোষণা করুন৷ একটি স্বাস্থ্য পরিষেবার অনুমতি প্রয়োজন, যা নিশ্চিত করে যে শুধুমাত্র স্বাস্থ্য পরিষেবাগুলি পরিষেবার সাথে আবদ্ধ হতে পারে:

<service android:name=".PassiveDataService"
    android:permission="com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING"
    android:exported="true" />

সময় ব্যাখ্যা

স্বাস্থ্য পরিষেবাগুলি থেকে আপনি যে ডেটা পান তা ব্যাচ করা হয়, তাই আপনি একই ব্যাচে বিভিন্ন ধরণের ডেটা পয়েন্ট বা একই ধরণের একাধিক ডেটা পয়েন্ট পেতে পারেন। ইভেন্টের সঠিক ক্রম নির্ধারণ করতে আপনার অ্যাপের দ্বারা প্রাপ্ত সময়ের চেয়ে এই বস্তুগুলির মধ্যে অন্তর্ভুক্ত টাইমস্ট্যাম্পগুলি ব্যবহার করুন৷

প্রথম বুট টাইমস্ট্যাম্প গণনা করে প্রতিটি DataPoint জন্য টাইমস্ট্যাম্প পান, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

val bootInstant =
    Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())

এই মান তারপর getStartInstant() বা getEndInstant() এ পাস করা যেতে পারে।

বুট করার পরে নিবন্ধন পুনরুদ্ধার করুন

প্যাসিভ ডেটা রেজিস্ট্রেশন রিবুট জুড়ে স্থায়ী হয় না। একটি ডিভাইস পুনরায় চালু হওয়ার পরে ডেটা পেতে, একটি BroadcastReceiver ব্যবহার করে আপনার নিবন্ধনগুলি পুনরায় তৈরি করুন যা ACTION_BOOT_COMPLETED সিস্টেম সম্প্রচারের জন্য শোনে৷

রিসিভারে, সরাসরি নিবন্ধনগুলি পুনরুদ্ধার করার চেষ্টা করবেন না। পরিবর্তে, একজন WorkManager কর্মীকে এই কার্যকারিতা অর্পণ করুন। যখন ডিভাইসটি চালু হয়, স্বাস্থ্য পরিষেবাগুলি একটি প্যাসিভ ডেটা রেজিস্ট্রেশন অনুরোধ স্বীকার করতে 10 সেকেন্ড বা তার বেশি সময় নিতে পারে এবং এটি একটি BroadcastReceiver এর অনুমোদনযোগ্য সম্পাদনের সময় অতিক্রম করতে পারে৷ বিপরীতে, WorkManager কর্মীদের একটি 10-মিনিট সম্পাদন সীমা আছে।

নিম্নলিখিত স্নিপেট দেখায় একটি BroadcastReceiver দেখতে কেমন হতে পারে:

class StartupReceiver : BroadcastReceiver() {

   override fun onReceive(context: Context, intent: Intent) {
       if (intent.action != Intent.ACTION_BOOT_COMPLETED) return


       // TODO: Check permissions first
       WorkManager.getInstance(context).enqueue(
           OneTimeWorkRequestBuilder<RegisterForPassiveDataWorker>().build()
       )
   }
}

class RegisterForPassiveDataWorker(
   private val appContext: Context,
   workerParams: WorkerParameters
) : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       runBlocking {
           HealthServices.getClient(appContext)
                .passiveMonitoringClient
                .setPassiveListenerCallback(...)
       }
       return Result.success()
   }
}

ডিভাইস বুট হয়ে গেলে সিস্টেমটি এই কোডটি কার্যকর করার ব্যবস্থা করতে, AndroidManifest.xml ফাইলে দুটি পরিবর্তন করুন৷

প্রথমে, <manifest> এর সন্তান হিসাবে নিম্নলিখিত অনুমতি যোগ করুন:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

দ্বিতীয়ত, <application> -এর সন্তান হিসাবে নিম্নলিখিত রিসিভার ইন্টেন্ট ফিল্টার যোগ করুন:

<receiver
    android:name=".StartupReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

কার্যকলাপের অবস্থা

প্যাসিভ ক্লায়েন্ট ব্যবহারকারীর অবস্থার উপর উচ্চ-স্তরের তথ্য প্রদান করতে পারে, যেমন ব্যবহারকারী ঘুমাচ্ছে কিনা। এই আপডেটগুলি পেতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. ACTIVITY_RECOGNITION অনুমতির অনুরোধ করুন৷
  2. PassiveListenerConfig বিল্ডারে setShouldUserActivityInfoBeRequested(true) কল করুন।

আপনার কলব্যাক বা পরিষেবাতে onUserActivityInfoReceived() পদ্ধতিটি ওভাররাইড করুন এবং ফিরে আসা UserActivityInfo ব্যবহার করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

override fun onUserActivityInfoReceived(info: UserActivityInfo) {
    val stateChangeTime: Instant = info.stateChangeTime // may be in the past!
    val userActivityState: UserActivityState = info.userActivityState
    if (userActivityState == UserActivityState.USER_ACTIVITY_ASLEEP) {
        // ...
    }
}

প্যাসিভ লক্ষ্য

আপনি একটি প্যাসিভ ক্লায়েন্ট কনফিগার করতে পারেন যখন প্যাসিভ লক্ষ্যে পৌঁছানো হয়, যেমন ব্যবহারকারী একদিনে 10,000টি ধাপ পূরণ করে অ্যাপটিকে অবহিত করতে।

এটি করার জন্য, নিম্নলিখিত উদাহরণে দেখানো হিসাবে একটি লক্ষ্য তৈরি করুন:

val dailyStepsGoal by lazy {
    val condition = DataTypeCondition(
        dataType = DataType.STEPS_DAILY,
        threshold = 10_000, // Trigger every 10000 steps
        comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
    )
    PassiveGoal(condition)
}

এই লক্ষ্যটি আপনার PassiveListenerConfig এ যোগ করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDailyGoals(setOf(dailyStepsGoal))
    .build()

আপনার কলব্যাক বা পরিষেবাতে onGoalCompleted() পদ্ধতিটি ওভাররাইড করুন এবং ফিরে আসা PassiveGoal ব্যবহার করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

override fun onGoalCompleted(goal: PassiveGoal) {
    when (goal.dataTypeCondition.dataType) {
        DataType.STEPS_DAILY -> {
            // ...
        }
    }
}
{% verbatim %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}