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

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

این راهنما فرایند نوشتن یا به‌روزرسانی داده‌ها در 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 تماس بگیرید.

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

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 داشته باشید.

مثال زیر نحوه انجام دادن «درج/به‌روزرسانی» روی داده‌های واکشی‌شده از انبار داده برنامه را نشان می‌دهد:

 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 بنویسد. برای جلوگیری از تأثیر منفی بر عمر باتری و سایر جنبه‌های عملکرد، حداکثر فاصله بین نوشتن‌ها باید ۱۵ دقیقه باشد.

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

نوع داده

واحد

موردانتظار

مثال

قدم‌ها

تعداد قدم‌ها

هر ۱ دقیقه

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

۲۳:۱۶ - ۲۳:۱۷ - ۲۲ مرحله

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

سرعت قدم‌ها

قدم/ دقیقه

هر ۱ دقیقه

۲۳:۱۴ - ۲۳:۱۵ - ۵ spm

۲۳:۱۶ - ۲۳:۱۷ - ۲۲ نمونه در دقیقه

۲۳:۱۷ - ۲۳:۱۸ - ۸ دور در دقیقه

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

هل می‌دهد

هر ۱ دقیقه

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

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

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

کالری سوزانده‌شده درطول فعالیت

کالری

هر ۱۵ دقیقه

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

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

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

TotalCaloriesBurned

کالری

هر ۱۵ دقیقه

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

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

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

مسافت

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

هر ۱ دقیقه

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

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

۲۳:۱۷ - ۲۳:۱۸ - ۰٫۰۱۲ کیلومتر

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

پشت

هر ۱ دقیقه

۲۰:۳۶ - ۲۰:۳۷ - ۳٫۰۴۸ متر

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

۲۳:۲۳ - ۲۳:۲۴ - ۹٫۱۴۴ متر

طبقات پیموده‌شده

طبقات

هر ۱ دقیقه

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

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

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

HeartRate

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

‫۴ بار در دقیقه

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

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

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

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

HeartRateVariabilityRmssd

میلی‌ثانیه

هر ۱ دقیقه

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

RespiratoryRate

تنفس/دقیقه

هر ۱ دقیقه

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

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

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

اشباع اکسیژن

٪

هر ۱ ساعت

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

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

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

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

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

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

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

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

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

نوع داده

واحد

موردانتظار

بهترین

مثال

قدم‌ها

تعداد قدم‌ها

هر ۱ دقیقه

هر ۱ ثانیه

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

۲۳:۱۶ - ۲۳:۱۷ - ۲۲ مرحله

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

سرعت قدم‌ها

قدم/ دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

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

۲۳:۱۶ - ۲۳:۱۷ - ۳۷ کلمه در دقیقه

۲۳:۱۷ - ۲۳:۱۸ - ۴۰ کلمه در دقیقه

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

هل می‌دهد

هر ۱ دقیقه

هر ۱ ثانیه

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

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

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

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

دور بر دقیقه

هر ۱ دقیقه

هر ۱ ثانیه

‫۲۳:۱۴-۲۳:۱۵ - ۶۵ دور در دقیقه

‫۲۳:۱۶ - ۲۳:۱۷ - ۷۰ دور در دقیقه

۲۳:۱۷ - ۲۳:۱۸ - ۶۸ دور در دقیقه

قدرت

وات

هر ۱ دقیقه

هر ۱ ثانیه

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

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

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

سرعت

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

هر ۱ دقیقه

هر ۱ ثانیه

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

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

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

مسافت

کیلومتر/متر

هر ۱ دقیقه

هر ۱ ثانیه

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

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

۲۳:۱۷ - ۲۳:۱۸ - ۰٫۰۱۲ کیلومتر

کالری سوزانده‌شده درطول فعالیت

کالری

هر ۱ دقیقه

هر ۱ ثانیه

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

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

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

TotalCaloriesBurned

کالری

هر ۱ دقیقه

هر ۱ ثانیه

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

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

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

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

پشت

هر ۱ دقیقه

هر ۱ ثانیه

۲۰:۳۶ - ۲۰:۳۷ - ۳٫۰۴۸ متر

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

۲۳:۲۳ - ۲۳:۲۴ - ۹٫۱۴۴ متر

مسیرهای تمرین

عرض/طول/ارتفاع

هر ۳ تا ۵ ثانیه

هر ۱ ثانیه

HeartRate

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

‫۴ بار در دقیقه

هر ۱ ثانیه

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

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

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

نوع داده

واحد

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

مثال

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

مرحله

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

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

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

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

ضربان قلب درحال استراحت

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

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

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

اشباع اکسیژن

٪

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

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

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

این رویکرد از انواع و ساختارهای داده موجود استفاده می‌کند و سازگاری با پیاده‌سازی‌های فعلی 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 را در فایل مانیفست و در فعالیتتان اعلام کنید.