همگام سازی داده ها

این راهنما با Health Connect نسخه ۱.۱.۰-alpha۱۲ سازگار است.

اکثر برنامه‌هایی که با Health Connect ادغام می‌شوند، پایگاه داده مخصوص به خود را دارند که به عنوان منبع اطلاعات عمل می‌کند. Health Connect روش‌هایی را برای همگام‌سازی برنامه شما فراهم می‌کند.

بسته به معماری برنامه شما، فرآیند همگام‌سازی ممکن است شامل برخی یا همه اقدامات زیر باشد:

  • داده‌های جدید یا به‌روز شده را از پایگاه داده برنامه خود به Health Connect ارسال کنید.
  • تغییرات داده‌ها را از Health Connect به پایگاه داده برنامه خود منتقل کنید.
  • وقتی داده‌ها از فروشگاه داده برنامه شما حذف شدند، آنها را از Health Connect حذف کنید.

در هر مورد، مطمئن شوید که فرآیند همگام‌سازی، هم Health Connect و هم پایگاه داده برنامه شما را هماهنگ نگه می‌دارد.

داده‌ها را به Health Connect ارسال کنید

اولین بخش از فرآیند همگام‌سازی، ارسال داده‌ها از پایگاه داده برنامه شما به پایگاه داده Health Connect است.

داده‌های خود را آماده کنید

معمولاً رکوردهای موجود در پایگاه داده برنامه شما دارای جزئیات زیر هستند:

  • یک کلید منحصر به فرد، مانند UUID .
  • یک نسخه یا مهر زمانی.

هنگام همگام‌سازی داده‌ها با Health Connect، فقط داده‌هایی را که از آخرین همگام‌سازی وارد، به‌روزرسانی یا حذف شده‌اند، شناسایی و وارد کنید.

نوشتن داده‌ها در Health Connect

برای وارد کردن داده‌ها به Health Connect، مراحل زیر را انجام دهید:

  1. فهرستی از ورودی‌های جدید، به‌روزرسانی‌شده یا حذف‌شده را از پایگاه داده برنامه خود دریافت کنید.
  2. برای هر ورودی، یک شیء Record متناسب با آن نوع داده ایجاد کنید. برای مثال، یک شیء WeightRecord برای داده‌های مربوط به وزن ایجاد کنید.
  3. برای هر Record یک شیء Metadata مشخص کنید. این شامل clientRecordId می‌شود که یک شناسه از پایگاه داده برنامه شماست و می‌توانید از آن برای شناسایی منحصر به فرد رکورد استفاده کنید. می‌توانید از کلید منحصر به فرد موجود خود برای این کار استفاده کنید. اگر داده‌های شما نسخه‌بندی شده‌اند، یک clientRecordVersion نیز ارائه دهید که با نسخه‌بندی استفاده شده در داده‌های شما همسو باشد. اگر نسخه‌بندی نشده است، می‌توانید از مقدار Long مربوط به timestamp فعلی به عنوان جایگزین استفاده کنید.

    val recordVersion = 0L
    // Specify as needed
    // The clientRecordId is an ID that you choose for your record. This
    // is often the same ID you use in your app's datastore.
    val clientRecordId = "<your-record-id>"
    
    val record = WeightRecord(
        metadata = Metadata.activelyRecorded(
            clientRecordId = clientRecordId,
            clientRecordVersion = recordVersion,
            device = Device(type = Device.TYPE_SCALE)
        ),
        weight = Mass.kilograms(62.0),
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
    )
    healthConnectClient.insertRecords(listOf()(record))
    
    
  4. با استفاده از insertRecords داده‌ها را به Health Connect اضافه کنید . اضافه کردن داده‌ها به این معنی است که هر داده موجود در Health Connect تا زمانی که مقادیر clientRecordId در datastore Health Connect وجود داشته باشد و clientRecordVersion بالاتر از مقدار موجود باشد، رونویسی می‌شود. در غیر این صورت، داده‌های اضافه شده به عنوان داده جدید نوشته می‌شوند.

    healthConnectClient.insertRecords(arrayListOf(record))
    

برای آشنایی با ملاحظات عملی برای تغذیه داده‌ها، بهترین شیوه‌ها برای نوشتن داده‌ها را بررسی کنید.

شناسه‌های فروشگاه Health Connect

اگر برنامه شما داده‌ها را از Health Connect نیز می‌خواند، id Health Connect را برای رکوردها پس از درج آنها ذخیره کنید. برای پردازش حذف‌ها هنگام دریافت تغییرات داده‌ها از Health Connect به این id نیاز دارید.

تابع insertRecords یک InsertRecordsResponse برمی‌گرداند که شامل لیستی از مقادیر id است. از پاسخ برای دریافت شناسه‌های رکورد و ذخیره آنها استفاده کنید.

val response = healthConnectClient.insertRecords(arrayListOf(record))

for (recordId in response.recordIdsList) {
    // Store recordId to your app's datastore
}

داده‌ها را از Health Connect دریافت کنید

بخش دوم فرآیند همگام‌سازی، انتقال هرگونه تغییر داده از Health Connect به پایگاه داده برنامه شما است. این تغییرات داده می‌تواند شامل به‌روزرسانی‌ها و حذف‌ها باشد.

دریافت توکن تغییرات

برای دریافت لیستی از تغییرات و دریافت آنها از Health Connect، برنامه شما باید توکن‌های Changes را پیگیری کند. می‌توانید هنگام درخواست Changes از آنها برای بازگرداندن لیستی از تغییرات داده‌ها و یک توکن Changes جدید که دفعه بعد استفاده خواهد شد، استفاده کنید.

برای دریافت توکن تغییرات ، getChangesToken را فراخوانی کنید و انواع داده‌های مورد نیاز را ارائه دهید.

val changesToken = healthConnectClient.getChangesToken(
    ChangesTokenRequest(recordTypes = setOf(WeightRecord::class))
)

بررسی تغییرات داده‌ها

اکنون که توکن تغییرات را دریافت کرده‌اید، از آن برای دریافت همه تغییرات استفاده کنید. توصیه می‌کنیم یک حلقه ایجاد کنید تا همه تغییرات را بررسی کند و بررسی کند که آیا تغییرات داده‌ای موجود است یا خیر. مراحل زیر را دنبال کنید:

  1. برای دریافت لیستی از تغییرات getChanges با استفاده از توکن فراخوانی کنید.
  2. هر تغییر را بررسی کنید که آیا نوع آن UpsertionChange است یا DeletionChange ، و عملیات لازم را انجام دهید.
    • برای UpsertionChange ، فقط تغییراتی را اعمال کنید که از برنامه فراخوانی کننده نیامده باشند تا مطمئن شوید که داده‌ها را دوباره وارد نمی‌کنید.
  3. توکن تغییرات بعدی را به عنوان توکن جدید خود اختصاص دهید.
  4. مراحل ۱ تا ۳ را تا زمانی که هیچ تغییری باقی نمانده باشد، تکرار کنید.
  5. توکن بعدی را ذخیره کنید و آن را برای واردات بعدی رزرو کنید.
suspend fun processChanges(token: String): String {
    var nextChangesToken = token
    do {
        val response = healthConnectClient.getChanges(nextChangesToken)
        response.changes.forEach { change ->
            when (change) {
                is UpsertionChange ->
                    if (change.record.metadata.dataOrigin.packageName != context.packageName) {
                        processUpsertionChange(change)
                    }
                is DeletionChange -> processDeletionChange(change)
            }
        }
        nextChangesToken = response.nextChangesToken
    } while (response.hasMore)
    // Return and store the changes token for use next time.
    return nextChangesToken
}

برای آشنایی با ملاحظات عملی برای دریافت داده‌ها، بهترین شیوه‌ها برای همگام‌سازی داده‌ها را بررسی کنید.

تغییرات داده‌های فرآیند

تغییرات را به پایگاه داده برنامه خود منعکس کنید. برای UpsertionChange ، از id و lastModifiedTime از metadata آن برای upsert کردن رکورد استفاده کنید. برای DeletionChange ، از id ارائه شده برای حذف رکورد استفاده کنید. این امر مستلزم آن است که id رکورد را همانطور که در Store Health Connect IDs ذکر شده است، ذخیره کرده باشید.

حذف داده‌ها از Health Connect

وقتی کاربری داده‌های خود را از برنامه شما حذف می‌کند، مطمئن شوید که داده‌ها از Health Connect نیز حذف می‌شوند. برای انجام این کار deleteRecords استفاده کنید. این تابع یک نوع رکورد و لیستی از مقادیر id و clientRecordId را دریافت می‌کند که حذف دسته‌ای چندین داده را آسان می‌کند. یک deleteRecords جایگزین که یک timeRangeFilter را دریافت می‌کند نیز موجود است.

همگام‌سازی با تأخیر کم از طریق دستگاه‌های پوشیدنی

برای همگام‌سازی داده‌ها از یک دستگاه تناسب اندام پوشیدنی با Health Connect با تأخیر کم، از CompanionDeviceService استفاده کنید. این رویکرد برای دستگاه‌هایی که از اعلان‌ها یا نشانه‌های BLE GATT پشتیبانی می‌کنند و اندروید ۸.۰ (سطح API ۲۶) یا بالاتر را هدف قرار می‌دهند، کار می‌کند. CompanionDeviceService به برنامه شما اجازه می‌دهد داده‌ها را از دستگاه‌های پوشیدنی دریافت کرده و آنها را در Health Connect بنویسد، حتی زمانی که برنامه در حال اجرا نیست. برای جزئیات بیشتر در مورد بهترین شیوه‌های BLE، به مرور کلی Bluetooth Low Energy مراجعه کنید.

دستگاه را مرتبط کنید

ابتدا، برنامه شما باید کاربر را از طریق یک فرآیند یک‌باره برای مرتبط کردن دستگاه پوشیدنی با برنامه شما با استفاده از CompanionDeviceManager راهنمایی کند. این کار به برنامه شما مجوزهای لازم برای تعامل با دستگاه را می‌دهد. برای اطلاعات بیشتر، به جفت‌سازی دستگاه همراه مراجعه کنید.

سرویس را در مانیفست اعلام کنید

سپس، CompanionDeviceService در فایل manifest برنامه خود تعریف کنید. کد زیر را به AndroidManifest.xml خود اضافه کنید:

<manifest ...>
   <application ...>
       <service
           android:name=".MyWearableService"
           android:exported="true"
           android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE">
           <intent-filter>
               <action android:name="android.companion.CompanionDeviceService" />
           </intent-filter>
       </service>
   </application>
</manifest>

ایجاد CompanionDeviceService

در نهایت، یک کلاس ایجاد کنید که CompanionDeviceService ارث‌بری کند. این سرویس اتصال به دستگاه پوشیدنی را مدیریت می‌کند و داده‌ها را از طریق فراخوانی‌های BLE GATT دریافت می‌کند. وقتی داده‌های جدید دریافت می‌شوند، بلافاصله در Health Connect نوشته می‌شوند.

import android.companion.CompanionDeviceService
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.records.StepsRecord
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch

class MyWearableService : CompanionDeviceService() {

   // A coroutine scope for handling suspend functions like writing to Health Connect
   private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
   private var healthConnectClient: HealthConnectClient? = null
   private var bluetoothGatt: BluetoothGatt? = null

   // This is called by the system when your wearable connects
   override fun onDeviceAppeared(address: String) {
       super.onDeviceAppeared(address)
       healthConnectClient = HealthConnectClient.getOrCreate(this)

       serviceScope.launch {
           // Check which permissions have been granted before subscribing to data from the wearable.
           // A service cannot request permissions, so your app must have already requested
           // and been granted them from an Activity.
           val granted = healthConnectClient?.permissionController?.getGrantedPermissions()

           // ... set up your GATT connection here ...

           // Once connected, subscribe to notifications for the data types you have
           // permission to write.
           if (granted?.contains(HealthPermission.getWritePermission(HeartRateRecord::class)) == true) {
               // subscribeToHeartRate(bluetoothGatt)
           }
       }
   }

   // The core of your low-latency pipeline is the BLE callback
   private val gattCallback = object : BluetoothGattCallback() {
       override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray) {
           super.onCharacteristicChanged(gatt, characteristic, value)

           // 1. Instantly receive the data
           val rawData = value

           // 2. Parse the data from the wearable
           val healthData = parseWearableData(rawData) // Your custom parsing logic

           // 3. Immediately process it. For simplicity, this example writes
           //    directly to Health Connect. A real-world app might write to its
           //    own datastore first and then sync with Health Connect.
           serviceScope.launch {
               writeToHealthConnect(healthData)
           }
       }
   }

   private suspend fun writeToHealthConnect(healthData: HealthData) {
       val records = prepareHealthConnectRecords(healthData) // Convert to Health Connect records
       try {
           healthConnectClient?.insertRecords(records)
       } catch (e: Exception) {
           // Handle exceptions
       }
   }

   // This is called by the system when your wearable disconnects
   override fun onDeviceDisappeared(address: String) {
       super.onDeviceDisappeared(address)
       // Clean up your GATT connection and other resources
       bluetoothGatt?.close()
   }
}

بهترین روش‌ها برای همگام‌سازی داده‌ها

عوامل زیر بر روند همگام‌سازی تأثیر می‌گذارند.

انقضای توکن

از آنجایی که یک توکن Changes استفاده نشده ظرف 30 روز منقضی می‌شود، شما باید از یک استراتژی همگام‌سازی استفاده کنید که از دست رفتن اطلاعات در چنین مواردی جلوگیری کند. استراتژی شما می‌تواند شامل رویکردهای زیر باشد:

  • در پایگاه داده برنامه خود، جدیدترین رکورد مصرف‌شده که دارای id Health Connect نیز هست را جستجو کنید.
  • از Health Connect رکوردهایی را درخواست کنید که با یک مهر زمانی خاص شروع می‌شوند و سپس آنها را در مخزن داده برنامه خود وارد یا به‌روزرسانی کنید.
  • برای رزرو توکن تغییرات (Changes token) برای دفعه‌ی بعدی که به آن نیاز دارید، درخواست دهید.

استراتژی‌های پیشنهادی مدیریت تغییرات

در صورتی که توکن‌های تغییرات برنامه شما نامعتبر یا منقضی شده باشند، بسته به کاربرد آن در منطق شما، استراتژی‌های مدیریتی زیر را توصیه می‌کنیم:

  • تمام داده‌ها را بخوانید و حذف کنید . این ایده‌آل‌ترین استراتژی است.
    • مهر زمانی آخرین باری که آنها داده ها را از Health Connect می خوانند، ذخیره کنید.
    • در زمان انقضای توکن، تمام داده‌ها را از آخرین برچسب زمانی یا برای ۳۰ روز گذشته دوباره بخوانید. سپس، آن را با استفاده از شناسه‌ها در برابر داده‌های خوانده شده قبلی dedupe کنید.
    • در حالت ایده‌آل، شناسه‌های کلاینت را پیاده‌سازی کنید زیرا برای به‌روزرسانی داده‌ها مورد نیاز هستند.
  • فقط داده‌های بعد از آخرین برچسب زمانی خوانده شده را بخوانید . این منجر به برخی اختلافات داده‌ای در حدود زمان انقضای توکن Changes می‌شود، اما دوره زمانی کوتاه‌تر است و می‌تواند از چند ساعت تا چند روز طول بکشد.
    • مهر زمانی آخرین باری که آنها داده ها را از Health Connect می خوانند، ذخیره کنید.
    • در زمان انقضای توکن، تمام داده‌ها از این برچسب زمانی به بعد خوانده می‌شوند.
  • داده‌های ۳۰ روز گذشته را حذف و سپس بخوانید . این روش با آنچه در اولین ادغام اتفاق می‌افتد، همسوتر است.
    • تمام داده‌های خوانده شده توسط برنامه از Health Connect را در 30 روز گذشته حذف کنید.
    • پس از حذف، تمام این داده‌ها را دوباره بخوانید.
  • خواندن داده‌های ۳۰ روز گذشته بدون حذف داده‌های تکراری . این استراتژی ایده‌آل نیست و منجر به نمایش داده‌های تکراری به کاربران می‌شود.
    • تمام داده‌های خوانده شده توسط برنامه از Health Connect را در 30 روز گذشته حذف کنید.
    • اجازه ورود ورودی‌های تکراری.

نوع داده، توکن‌ها را تغییر می‌دهد

اگر برنامه شما بیش از یک نوع داده را به طور مستقل مصرف می‌کند، برای هر نوع داده از توکن‌های تغییر جداگانه استفاده کنید. فقط در صورتی از لیستی از چندین نوع داده با API همگام‌سازی تغییرات استفاده کنید که این انواع داده یا با هم مصرف می‌شوند یا اصلاً مصرف نمی‌شوند.

پیش‌زمینه خوانده می‌شود

برنامه‌ها فقط می‌توانند داده‌های Health Connect را در حالی که در پیش‌زمینه هستند بخوانند. هنگام همگام‌سازی داده‌ها از Health Connect، دسترسی به Health Connect ممکن است در هر نقطه‌ای قطع شود. به عنوان مثال، برنامه شما باید هنگام خواندن حجم زیادی از داده‌ها از Health Connect، وقفه‌ها را در اواسط همگام‌سازی مدیریت کند و دفعه بعد که برنامه باز می‌شود، ادامه دهد.

پیشینه خوانده شده

شما می‌توانید درخواست کنید که برنامه شما در پس‌زمینه اجرا شود و داده‌ها را از Health Connect بخواند. اگر مجوز Background Read را درخواست کنید، کاربر شما می‌تواند به برنامه شما اجازه دهد تا در پس‌زمینه داده‌ها را بخواند.

زمان‌بندی‌های واردات

از آنجایی که برنامه شما نمی‌تواند از داده‌های جدید مطلع شود، داده‌های جدید را در دو مرحله بررسی کنید:

  • هر بار که برنامه شما در پیش‌زمینه فعال می‌شود. در این حالت، از رویدادهای چرخه عمر استفاده کنید.
  • به صورت دوره‌ای، در حالی که برنامه شما در پیش‌زمینه است. هنگامی که داده‌های جدید در دسترس قرار گرفت، به کاربران اطلاع دهید و به آنها اجازه دهید صفحه نمایش خود را به‌روزرسانی کنند تا تغییرات را منعکس کنند.