نوشتن داده‌ها

این راهنما با Health Connect نسخه 1.1.0-alpha12 یا بالاتر سازگار است.

این راهنما فرایند نوشتن یا به‌روزرسانی داده‌ها در Health Connect را پوشش می‌دهد.

مدیریت مقادیر صفر

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

راه‌اندازی ساختار داده‌ها

قبل‌از نوشتن داده‌ها، ابتدا باید سوابق را تنظیم کنیم. برای بیش‌از ۵۰ نوع داده، هرکدام ساختار مربوط به خود را دارند. برای جزئیات بیشتر درباره انواع داده‌های دردسترس، به مرجع Jetpack مراجعه کنید.

سوابق پایه

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

مثال زیر نحوه تنظیم داده‌های تعداد قدم‌ها را نشان می‌دهد:

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

سوابق با واحدهای اندازه‌گیری

Health Connect می‌تواند مقادیر را همراه با واحدهای اندازه‌گیری آن‌ها ذخیره کند تا دقت را ارائه دهد. یک نمونه نوع داده تغذیه است که بسیار گسترده و جامع است. این فایل شامل طیف گسترده‌ای از فیلدهای اختیاری مواد مغذی است که از کربوهیدرات کل تا ویتامین‌ها را دربر می‌گیرد. هر نقطه داده نشان‌دهنده مواد مغذی‌ای است که احتمالاً به‌عنوان بخشی از وعده غذایی یا ماده غذایی مصرف شده است.

در این نوع داده، همه مواد مغذی در واحد جرم نشان داده می‌شوند، درحالی‌که energy در واحد انرژی نشان داده می‌شود.

مثال زیر نشان می‌دهد که چگونه داده‌های تغذیه را برای کاربری که موز خورده است تنظیم کنید:

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(1))

val banana = NutritionRecord(
    name = "banana",
    energy = 105.0.kilocalories,
    dietaryFiber = 3.1.grams,
    potassium = 0.422.grams,
    totalCarbohydrate = 27.0.grams,
    totalFat = 0.4.grams,
    saturatedFat = 0.1.grams,
    sodium = 0.001.grams,
    sugar = 14.0.grams,
    vitaminB6 = 0.0005.grams,
    vitaminC = 0.0103.grams,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = ZoneOffset.UTC,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_PHONE)
    )
)

رکوردها با داده‌های سری

Health Connect می‌تواند فهرستی از داده‌های سری را ذخیره کند. یک نمونه نوع داده ضربان قلب است که مجموعه‌ای از نمونه‌های ضربان قلب شناسایی‌شده بین خوانش‌ها را ضبط می‌کند.

در این نوع داده، پارامتر samples با فهرستی از نمونه‌های ضربان قلب نشان داده می‌شود. هر نمونه حاوی یک مقدار beatsPerMinute و یک مقدار time است.

مثال زیر نحوه تنظیم داده‌های سری ضربان قلب را نشان می‌دهد:

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    },
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

درخواست اجازه‌ها از کاربر

پس‌از ایجاد نمونه مشتری، برنامه‌تان باید از کاربر درخواست اجازه کند. کاربران باید بتوانند در هرزمانی اجازه‌ها را اعطا یا رد کنند. برای انجام این کار، مجموعه‌ای از اجازه‌ها را برای انواع داده‌های موردنیاز ایجاد کنید. مطمئن شوید که اجازه‌های موجود در مجموعه ابتدا در مانیفست Android شما اعلام شده باشد.

val permissions =
    setOf(
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        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.") }
    }
}
ازآنجایی‌که کاربران می‌توانند در هر زمانی اجازه‌ها را اعطا یا لغو کنند، برنامه شما باید قبل‌از استفاده از اجازه‌ها، هر بار آن‌ها را بررسی کند و سناریوهایی را که در آن‌ها اجازه ازدست رفته است مدیریت کند.

نوشتن داده‌ها

یکی از گردش‌های کاری رایج در Health Connect نوشتن داده است. برای افزودن سوابق، از insertRecords استفاده کنید.

مثال زیر نحوه نوشتن داده‌ها را با درج تعداد قدم‌ها نشان می‌دهد:

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

به‌روزرسانی داده‌ها

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

فراداده

ارزش دارد که ابتدا کلاس Metadata را بررسی کنید زیرا این کار هنگام به‌روزرسانی داده‌ها ضروری است. هنگام ایجاد، هر Record در Health Connect دارای یک فیلد metadata است. ویژگی‌های زیر به همگام‌سازی مربوط هستند:

مشخصات شرح
id هر Record در Health Connect دارای مقدار id یکتایی است.
Health Connect به‌طور خودکار این را هنگام درج سابقه جدید پر می‌کند.
lastModifiedTime هر Record آخرین باری را که سابقه اصلاح شده است نیز ردیابی می‌کند.
Health Connect این مورد را به‌طور خودکار پر می‌کند.
clientRecordId هر Record می‌تواند شناسه یکتایی داشته باشد که با آن مرتبط است تا به‌عنوان مرجع در پایگاه داده برنامه شما عمل کند.
برنامه‌تان این مقدار را ارائه می‌دهد.
clientRecordVersion وقتی سابقه‌ای clientRecordId دارد، می‌توان از clientRecordVersion استفاده کرد تا داده‌ها با نسخه موجود در پایگاه داده برنامه شما همگام‌سازی‌شده باقی بمانند.
برنامه‌تان این مقدار را ارائه می‌دهد.

به‌روزرسانی پس‌از خواندن براساس محدوده زمانی

برای به‌روزرسانی داده‌ها، ابتدا سوابق موردنیاز را آماده کنید. درصورت لزوم، تغییرات لازم را در سوابق اعمال کنید. سپس، برای اعمال تغییرات با updateRecords تماس بگیرید.

مثال زیر نحوه به‌روزرسانی داده‌ها را نشان می‌دهد. برای این منظور، مقادیر انحراف منطقه هر سابقه به «زمان استاندارد اقیانوس آرام» (PST) تنظیم شده است.

suspend fun updateSteps(
    healthConnectClient: HealthConnectClient,
    prevRecordStartTime: Instant,
    prevRecordEndTime: Instant
) {
    try {
        val request = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(
                    prevRecordStartTime,
                    prevRecordEndTime
                )
            )
        )

        val newStepsRecords = arrayListOf<StepsRecord>()
        for (record in request.records) {
            // Adjusted both offset values to reflect changes
            val sr = StepsRecord(
                count = record.count,
                startTime = record.startTime,
                startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
                endTime = record.endTime,
                endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
                metadata = record.metadata
            )
            newStepsRecords.add(sr)
        }

        healthConnectClient.updateRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

درج و به‌روزرسانی ازطریق شناسه سابقه کارخواه

اگر از مقادیر اختیاری «شناسه سابقه مشتری» و «نسخه سابقه مشتری» استفاده می‌کنید، توصیه می‌کنیم به‌جای updateRecords از insertRecords استفاده کنید.

تابع insertRecords می‌تواند داده‌ها را به‌روزرسانی یا درج کند. اگر داده‌ها براساس مجموعه ارائه‌شده از «شناسه‌های سابقه مشتری» در Health Connect وجود داشته باشد، بازنویسی می‌شود. درغیراین‌صورت، به‌عنوان داده جدید نوشته می‌شود. این سناریو هر زمان که لازم باشد داده‌ها را از مخزن داده برنامه‌تان با Health Connect همگام‌سازی کنید مفید است.

مثال زیر نشان می‌دهد که چگونه می‌توان یک عملیات upsert را روی داده‌های استخراج‌شده از فضای ذخیره‌سازی داده برنامه انجام داد:

 fun pullStepsFromDatastore(startTime: Instant, endTime: Instant) : ArrayList<StepsRecord> {
    val appStepsRecords = arrayListOf<StepsRecord>()
    // Pull data from app datastore
    // ...
    // Make changes to data if necessary
    // ...
    // Store data in appStepsRecords
    // ...
    var sr = StepsRecord(
        metadata = Metadata.activelyRecorded(
            clientRecordId = "Your client record ID",
            clientRecordVersion = 0L,
            device = Device(type = Device.TYPE_WATCH)
        ),
        startTime = startTime,
        startZoneOffset = startTime.atZone(ZoneId.of("PST")).offset,
        endTime = endTime,
        endZoneOffset = endTime.atZone(ZoneId.of("PST")).offset,
        count = 120
    )
    appStepsRecords.add(sr)
    // ...
    return appStepsRecords
}

suspend fun upsertSteps(
    healthConnectClient: HealthConnectClient,
    newStepsRecords: ArrayList<StepsRecord>
) {
    try {
        healthConnectClient.insertRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

پس‌از آن، می‌توانید این توابع را در رشته اصلی‌تان فراخوانی کنید.

upsertSteps(healthConnectClient, pullStepsFromDatastore(
    startTime = startTime,
    endTime = endTime
))

بررسی مقدار در «نسخه سابقه کارخواه»

اگر فرایند درج/ به‌روزرسانی داده‌ها شامل «نسخه سابقه کارخواه» باشد، Health Connect بررسی‌های مقایسه‌ای را در مقادیر clientRecordVersion انجام می‌دهد. اگر نسخه داده‌های درج‌شده بالاتر از نسخه داده‌های موجود باشد، به‌روزرسانی/درج انجام می‌شود. درغیراین‌صورت، فرایند تغییر را نادیده می‌گیرد و مقدار بدون تغییر باقی می‌ماند.

برای گنجاندن نسخه‌بندی در داده‌هایتان، باید Metadata.clientRecordVersion را با مقدار Long براساس منطق نسخه‌بندی‌تان ارائه دهید.

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))

val stepsRecord = StepsRecord(
    count = 100L,
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.activelyRecorded(
        clientRecordId = "Your supplied record ID",
        clientRecordVersion = 0L, // Your supplied record version
        device = Device(type = Device.TYPE_WATCH)
    )
)

هرگاه تغییری ایجاد شود، «درج‌به‌روزرسانی» به‌طور خودکار version را افزایش نمی‌دهد، و از هرگونه نمونه غیرمنتظره بازنویسی داده‌ها جلوگیری می‌کند. با این کار، باید مقدار بالاتری را به‌صورت دستی برای آن ارائه دهید.

راهنمای عمومی

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

هنگام نوشتن داده‌هایی که از منبع دیگری وارد یا مشتق شده‌اند، انتظار می‌رود که منشأ و فراداده دستگاه منبع آن را به‌درستی ارجاع دهید. برای انجام این کار، باید فراداده‌های زیر را برای هر سابقه نوشتاری ارائه دهید:

  • recordingMethod: برای داده‌های ضبط‌شده به‌صورت خودکار یا دستی، انتظار داریم روش ضبط به‌روز شود تا نوع فعالیت ضبط‌شده را منعکس کند:
    • RECORDING_METHOD_AUTOMATICALLY_RECORDED: اگر داده‌ها به‌طور خودکار ثبت شده باشد، برای مثال، مچ‌بند تناسب اندام به‌طور خودکار تشخیص داده باشد که کاربر به دویدن رفته است.
    • ‫RECORDING_METHOD_ACTIVELY_RECORDED: اگر کاربر فعالیت جدیدی را شروع کرده باشد، مثلاً دوچرخه‌سواری در دستگاه پوشیدنی‌اش.
    • RECORDING_METHOD_MANUAL_ENTRY: اگر کاربر داده‌ها را به‌طور دستی وارد کرده باشد.
  • device.type: باید نوع دستگاه را از یکی از انواع Device پشتیبانی‌شده مشخص کنید.
  • device.manufacturer: سازنده دستگاه، برای مثال، «Fitbit».
  • device.model: مدل دستگاه، برای مثال، «Charge 3».
  • device.udi: (اختیاری) بخش «شناسه دستگاه» (DI) «شناسه یکتای دستگاه» (UDI) پزشکی. برای جزئیات مربوط به اجازه‌های لازم و رهنمودهای حریم خصوصی، به راهنمای فراداده مراجعه کنید.

تنظیم صحیح فراداده برای شفافیت داده‌ها بسیار مهم است و به کاربران کمک می‌کند تا متوجه شوند اطلاعات سلامتی‌شان از کجا می‌آید. برای جزئیات کامل، به راهنمای فراداده Health Connect مراجعه کنید.

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

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

هنگام ردیابی داده‌ها، چند پیشنهاد وجود دارد که می‌توانید بسته به روشی که برنامه‌تان داده‌ها را می‌نویسد، آن‌ها را دنبال کنید.

مدیریت منطقه زمانی

هنگام نوشتن سوابق مبتنی بر زمان، از تنظیم کردن انحراف‌ها روی zoneOffset.UTC به‌طور پیش‌فرض خودداری کنید زیرا این کار می‌تواند منجر به مُهرهای زمان نادرست شود وقتی کاربران در مناطق دیگر هستند. درعوض، انحراف را براساس مکان واقعی دستگاه محاسبه کنید. می‌توانید منطقه زمانی دستگاه را بااستفاده از ZoneId.systemDefault() بازیابی کنید.

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(1))
val stepsRecords = mutableListOf<StepsRecord>()
var sampleTime = startTime
val minutesBetweenSamples = 15L
while (sampleTime < endTime) {
    // Get the default ZoneId then convert it to an offset
    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(sampleTime)
    stepsRecords += StepsRecord(
        startTime = sampleTime.minus(Duration.ofMinutes(minutesBetweenSamples)),
        startZoneOffset = zoneOffset,
        endTime = sampleTime,
        endZoneOffset = zoneOffset,
        count = Random.nextLong(1, 100),
        metadata = Metadata.activelyRecorded(device = Device(type = Device.TYPE_WATCH)),
    )
    sampleTime = sampleTime.plus(Duration.ofMinutes(minutesBetweenSamples))
}
healthConnectClient.insertRecords(
    stepsRecords
)

برای جزئیات بیشتر، اسناد مربوط به ZoneId را ببینید.

نوشتن فراوانی و دانه‌بندی

هنگام نوشتن داده‌ها در Health Connect، از وضوح مناسب استفاده کنید. استفاده از وضوح مناسب به کاهش بار فضای ذخیره‌سازی کمک می‌کند و درعین‌حال داده‌های منسجم و دقیق را حفظ می‌کند. وضوح داده‌ها شامل دو چیز است:

  • بسامد نوشتن: تعداد دفعاتی که برنامه شما داده‌های جدید را در Health Connect می‌نویسد.
    • وقتی داده‌های جدید دردسترس است، داده‌ها را تا حد امکان به‌طور مکرر بنویسید، درعین‌حال به عملکرد دستگاه توجه داشته باشید.
    • برای جلوگیری از تأثیر منفی بر عمر باتری و سایر جنبه‌های عملکرد، حداکثر فاصله بین نوشتن‌ها باید ۱۵ دقیقه باشد.
  • سطح جزئیات داده‌های نوشته‌شده: چند وقت یک‌بار از داده‌ها نمونه‌برداری شده است.
    • برای مثال، نمونه‌های ضربان قلب را هر ۵ ثانیه یک‌بار بنویسید.
    • همه انواع داده‌ها به نرخ نمونه‌برداری یکسانی نیاز ندارند. به‌روزرسانی داده‌های تعداد قدم‌ها در هر ثانیه، در مقایسه با آهنگ کمتر تکرار مانند هر ۶۰ ثانیه، مزیت چندانی ندارد.
    • نرخ‌های نمونه‌برداری بالاتر ممکن است به کاربران امکان دهد تا نگاهی دقیق‌تر و جزئی‌تر به داده‌های سلامتی و تناسب اندام خود داشته باشند. بسامدهای نرخ نمونه‌برداری باید بین جزئیات و عملکرد تعادل برقرار کنند.

رهنمودهای اضافی

هنگام نوشتن داده‌ها، این دستورالعمل‌ها را دنبال کنید:

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

کد زیر از WorkManager برای زمان‌بندی کارهای پس‌زمینه‌ای دوره‌ای استفاده می‌کند، با حداکثر دوره زمانی ۱۵ دقیقه و فاصله زمانی انعطاف‌پذیر ۵ دقیقه. این پیکربندی بااستفاده از کلاس PeriodicWorkRequest.Builder تنظیم می‌شود.

val constraints = Constraints.Builder()
    .requiresBatteryNotLow()
    .requiresDeviceIdle(true)
    .build()

val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>(
        15,
        TimeUnit.MINUTES,
        5,
        TimeUnit.MINUTES
    )
    .setConstraints(constraints)
    .build()

ردگیری فعال

این شامل برنامه‌هایی می‌شود که ردگیری مبتنی بر رویداد انجام می‌دهند، مثل ورزش و خواب، یا ورودی دستی کاربر، مثل تغذیه. این سوابق زمانی ایجاد می‌شوند که برنامه در پیش‌نما باشد، یا در موارد نادری که چند بار در روز استفاده شود.

بررسی کنید که برنامه‌تان Health Connect را در کل مدت رویداد درحال اجرا نگه ندارد.

داده‌ها باید به یکی از دو روش زیر در Health Connect نوشته شوند:

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

روال‌های مطلوب برای جزئیات و دفعات نوشتن

هنگام نوشتن داده‌ها در Health Connect، از وضوح مناسب استفاده کنید. استفاده از وضوح مناسب به کاهش بار فضای ذخیره‌سازی کمک می‌کند و درعین‌حال داده‌های منسجم و دقیق را حفظ می‌کند. وضوح داده‌ها شامل ۲ چیز است:

  1. بسامد نوشتن: تعداد دفعاتی که برنامه شما داده‌های جدید را به Health Connect ارسال می‌کند. وقتی داده‌های جدید دردسترس است، داده‌ها را تا حد امکان به‌طور مکرر بنویسید، درحالی‌که به عملکرد دستگاه توجه دارید. برای جلوگیری از تأثیر منفی بر عمر باتری و سایر جنبه‌های عملکرد، حداکثر فاصله بین نوشتن‌ها باید ۱۵ دقیقه باشد.

  2. سطح جزئیات داده‌های نوشته‌شده: داده‌هایی که وارد شده‌اند چند وقت یک‌بار نمونه‌برداری شده‌اند. برای مثال، نمونه‌های ضربان قلب را هر ۵ ثانیه بنویسید. همه انواع داده‌ها به نرخ نمونه‌برداری یکسانی نیاز ندارند. به‌روزرسانی داده‌های تعداد قدم‌ها در هر ثانیه، در مقایسه با آهنگ کمتر مانند هر ۶۰ ثانیه، مزیت چندانی ندارد. بااین‌حال، نرخ‌های نمونه‌برداری بالاتر ممکن است به کاربران امکان دهد نگاهی دقیق‌تر و جزئی‌تر به داده‌های سلامتی و تناسب اندام خود داشته باشند. بسامدهای نرخ نمونه‌برداری باید بین جزئیات و عملکرد تعادل برقرار کنند.

ساختار سوابق برای داده‌های مجموعه

برای انواع داده‌ای که از مجموعه‌ای از نمونه‌ها استفاده می‌کنند، مثل HeartRateRecord، مهم است که سوابق خود را به‌درستی ساختاربندی کنید. به‌جای ایجاد یک سابقه یک‌روزه که به‌طور مداوم به‌روز می‌شود، باید چندین سابقه کوچک‌تر ایجاد کنید که هرکدام نشان‌دهنده یک بازه زمانی خاص باشد.

برای مثال، برای داده‌های ضربان قلب، باید برای هر دقیقه یک HeartRateRecord جدید ایجاد کنید. هر رکورد دارای زمان شروع و زمان پایان است که آن دقیقه را پوشش می‌دهد و شامل همه نمونه‌های ضربان قلب ثبت‌شده در آن دقیقه است.

درطول همگام‌سازی‌های منظم با Health Connect (برای مثال، هر ۱۵ دقیقه)، برنامه شما باید همه سوابق یک‌دقیقه‌ای را که از زمان همگام‌سازی قبلی ایجاد شده‌اند بنویسد. این کار باعث می‌شود سوابق در اندازه قابل‌مدیریت باقی بمانند و عملکرد جستجو و پردازش داده‌ها بهبود یابد.

مثال زیر نحوه ایجاد HeartRateRecord برای یک دقیقه را نشان می‌دهد که حاوی چند نمونه است:

val startTime = Instant.now().truncatedTo(ChronoUnit.MINUTES)
val endTime = startTime.plus(Duration.ofMinutes(1))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // Create a new record every minute, containing a list of samples.
    samples = listOf(
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(15),
            beatsPerMinute = 80,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(30),
            beatsPerMinute = 82,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(45),
            beatsPerMinute = 85,
        )
    ),
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

نوشتن داده‌های پایش‌شده درطول روز

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

جدول ۱: راهنمای نوشتن داده

نوع داده

واحد

مورد انتظار

مثال

قدم‌ها

تعداد قدم‌ها

هر ۱ دقیقه

‫۲۳:۱۴ - ۲۳:۱۵ - ۵ مرحله

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۲ قدم

‫۲۳:۱۷ - ۲۳:۱۸ - ۸ مرحله

سرعت قدم‌ها

قدم/ دقیقه

هر ۱ دقیقه

‫۲۳:۱۴ - ۲۳:۱۵ - ۵ ضربه در دقیقه

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۲ ضربه در دقیقه

23:17 - 23:18 - 8 spm

دفعات هل دادن صندلی چرخدار

دفعات هل دادن

هر ۱ دقیقه

‫۲۳:۱۴ - ۲۳:۱۵ - ۵ فشار

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۲ فشار

۲۳:۱۷ - ۲۳:۱۸ - ۸ فشار

ActiveCaloriesBurned

کالری

هر ۱۵ دقیقه

‫۲۳:۱۵ - ۲۳:۳۰ - ۲ کالری

۲۳:۳۰ - ۲۳:۴۵ - ۲۵ کالری

‫۲۳:۴۵ - ۰۰:۰۰ - ۵ کالری

TotalCaloriesBurned

کالری

هر ۱۵ دقیقه

‫۲۳:۱۵ - ۲۳:۳۰ - ۱۶ کالری

‫۲۳:۳۰ - ۲۳:۴۵ - ۱۶ کالری

‫۲۳:۴۵ - ۰۰:۰۰ - ۱۶ کالری

مسافت

کیلومتر/دقیقه

هر ۱ دقیقه

‫۲۳:۱۴-۲۳:۱۵ - ۰٫۰۰۸ کیلومتر

‫۲۳:۱۶ - ۲۳:۱۶ - ۰٫۰۲۱ کیلومتر

23:17 - 23:18 - 0.012 km

ارتفاع صعودکرده

پشت

هر ۱ دقیقه

20:36 - 20:37 - 3.048m

‫۲۰:۳۹ - ۲۰:۴۰ - ۳.۰۴۸ متر

23:23 - 23:24 - 9.144m

FloorsClimbed

طبقات

هر ۱ دقیقه

‫۲۳:۱۴ - ۲۳:۱۵ - ۵ طبقه

‫۲۳:۱۶ - ۲۳:۱۶ - ۲۲ طبقه

‫۲۳:۱۷ - ۲۳:۱۸ - ۸ طبقه

HeartRate

ضربان در دقیقه

۴ بار در دقیقه

‫۶:۱۱:۱۵ ق.ظ. - ۵۵ ضربه در دقیقه

‫۶:۱۱:۳۰ ق.ظ. - ۵۶ ضربه در دقیقه

‫۶:۱۱:۴۵ ق.ظ. - ۵۶ ضربه در دقیقه

‫۶:۱۲:۰۰ ق.ظ. - ۵۵ ضربه در دقیقه

HeartRateVariabilityRmssd

میلی‌ثانیه

هر ۱ دقیقه

‫۶:۱۱ ق.ظ. - ۲۳ میلی‌ثانیه

RespiratoryRate

نفس/دقیقه

هر ۱ دقیقه

‫۲۳:۱۴ - ۲۳:۱۵ - ۶۰ تنفس در دقیقه

‫۲۳:۱۶ - ۲۳:۱۶ - ۶۲ تنفس در دقیقه

‫۲۳:۱۷ - ۲۳:۱۸ - ۶۴ تنفس در دقیقه

OxygenSaturation

٪

هر ۱ ساعت

‫۶:۱۱ - ۹۵.۲۰۸٪

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

بررسی کنید که برنامه‌تان Health Connect را در کل مدت رویداد درحال اجرا نگه ندارد.

داده‌ها باید به یکی از دو روش زیر در Health Connect نوشته شوند:

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

جلسه‌های تمرین و خواب

حداقل، برنامه شما باید از راهنمایی‌های ستون موردانتظار در جدول ۲ پیروی کند. درصورت امکان، راهنمایی‌های ستون بهترین را دنبال کنید.

جدول زیر نحوه نوشتن داده‌ها را درطول تمرین نشان می‌دهد:

جدول ۲: راهنمایی برای نوشتن داده‌ها درطول جلسه تمرین

نوع داده

واحد

مورد انتظار

بهترین

مثال

قدم‌ها

تعداد قدم‌ها

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۵ قدم

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۲ قدم

‫۲۳:۱۷ - ۲۳:۱۸ - ۸ مرحله

سرعت قدم‌ها

قدم/ دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۳۵ کلمه در دقیقه

‫۲۳:۱۶ - ۲۳:۱۷ - ۳۷ ضربه در دقیقه

‫۲۳:۱۷ - ۲۳:۱۸ - ۴۰ ضربه در دقیقه

دفعات هل دادن صندلی چرخدار

دفعات هل دادن

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۵ فشار

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۲ فشار

۲۳:۱۷ - ۲۳:۱۸ - ۸ فشار

سرعت رکاب‌زنی دوچرخه‌سواری

تنفس در دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۶۵ تنفس در دقیقه

‫۲۳:۱۶ - ۲۳:۱۷ - ۷۰ تنفس در دقیقه

‫۲۳:۱۷ - ۲۳:۱۸ - ۶۸ تنفس در دقیقه

قدرت

وات

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۲۵۰ وات

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۵۵ وات

۲۳:۱۷ - ۲۳:۱۸ - ۲۴۵ وات

سرعت

کیلومتر/دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۰٫۳ کیلومتر/دقیقه

‫۲۳:۱۶ - ۲۳:۱۷ - ۰٫۴ کیلومتر/دقیقه

‫۲۳:۱۷ - ۲۳:۱۸ -۰.۴ کیلومتر/دقیقه

مسافت

کیلومتر/دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۰٫۰۰۸ کیلومتر

‫۲۳:۱۶ - ۲۳:۱۶ - ۰٫۰۲۱ کیلومتر

23:17 - 23:18 - 0.012 km

ActiveCaloriesBurned

کالری

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۲۰ کالری

‫۲۳:۱۶ - ۲۳:۱۷ - ۲۰ کالری

‫۲۳:۱۷ - ۲۳:۱۸ - ۲۵ کالری

TotalCaloriesBurned

کالری

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۳۶ کالری

‫۲۳:۱۶ - ۲۳:۱۷ - ۳۶ کالری

‫۲۳:۱۷ - ۲۳:۱۸ - ۴۱ کالری

ارتفاع صعودکرده

پشت

هر ۱ دقیقه

هر ۱ ثانیه

20:36 - 20:37 - 3.048m

‫۲۰:۳۹ - ۲۰:۴۰ - ۳.۰۴۸ متر

23:23 - 23:24 - 9.144m

ExerciseRoutes

عرض جغرافیایی/طول جغرافیایی/ارتفاع

هر ۳ تا ۵ ثانیه

هر ۱ ثانیه

HeartRate

ضربان در دقیقه

۴ بار در دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۱۵۰ ضربه در دقیقه

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

جدول ۳: راهنمایی برای نوشتن داده‌ها درطول یا بعداز جلسه خواب

نوع داده

واحد

نمونه‌های موردانتظار

مثال

مراحل خواب

صحنه

دوره زمانی دقیق برای هر مرحله خواب

‫۲۳:۴۶ - ۲۳:۵۰ - بیدار

۲۳:۵۰ - ۲۳:۵۶ - خواب سبک

۲۳:۵۶ - ۰۰:۱۶ - خواب عمیق

RestingHeartRate

ضربان در دقیقه

مقدار روزانه تکی (انتظار می‌رود اول صبح باشد)

‫۶:۱۱ ق.ظ. - ۶۰ ضربه در دقیقه

OxygenSaturation

٪

مقدار روزانه تکی (انتظار می‌رود اول صبح باشد)

‫۶:۱۱ - ۹۵.۲۰۸٪

رویدادهای چندورزشی

این رویکرد از انواع و ساختارهای داده موجود استفاده می‌کند و سازگاری با پیاده‌سازی‌های فعلی Health Connect و خوانندگان داده را تأیید می‌کند. این رویکردی رایج است که پلاتفرم‌های تناسب اندام اتخاذ می‌کنند.

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

مثال زیر نحوه نوشتن داده‌ها را برای ورزش سه‌گانه نشان می‌دهد:

val swimStartTime = Instant.parse("2024-08-22T08:00:00Z")
val swimEndTime = Instant.parse("2024-08-22T08:30:00Z")
val bikeStartTime = Instant.parse("2024-08-22T08:40:00Z")
val bikeEndTime = Instant.parse("2024-08-22T09:40:00Z")
val runStartTime = Instant.parse("2024-08-22T09:50:00Z")
val runEndTime = Instant.parse("2024-08-22T10:20:00Z")

val swimSession = ExerciseSessionRecord(
    startTime = swimStartTime,
    endTime = swimEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val bikeSession = ExerciseSessionRecord(
    startTime = bikeStartTime,
    endTime = bikeEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val runSession = ExerciseSessionRecord(
    startTime = runStartTime,
    endTime = runEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

healthConnectClient.insertRecords(listOf(swimSession, bikeSession, runSession))

رسیدگی به موارد استثنا

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

هر روش در HealthConnectClient استثناهایی را که ممکن است رخ دهد فهرست می‌کند. به‌طورکلی، برنامه شما باید استثناهای زیر را مدیریت کند:

جدول ۱: استثناهای Health Connect و روال‌های مطلوب توصیه‌شده
استثنا شرح روال مطلوب توصیه‌شده
IllegalStateException یکی از سناریوهای زیر رخ داده است:

  • سرویس Health Connect دردسترس نیست.
  • درخواست ساختار معتبری ندارد. برای مثال، درخواست انبوهشی در دسته‌های دوره‌ای که در آن از شیء Instant برای timeRangeFilter استفاده می‌شود.

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

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

RemoteException خطاهایی در سرویس اساسی که کیت توسعه نرم‌افزار به آن متصل می‌شود یا در برقراری ارتباط با آن رخ داده است.

برای مثال، برنامه‌تان در تلاش است رکوردی را با uid داده‌شده حذف کند. بااین‌حال، این استثنا پس‌از اینکه برنامه در سرویس زیربنایی بررسی می‌کند که سابقه وجود ندارد، ایجاد می‌شود.
برای جلوگیری از این مشکل، چند پیشنهاد در اینجا ارائه شده است:

  • همگام‌سازی‌های منظم بین مخزن داده برنامه‌تان و Health Connect انجام دهید.
  • برای رسیدگی به مشکلات درخواست، از استراتژی‌های تلاش مجدد و عقب‌نشینی استفاده کنید.

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