คู่มือนี้ใช้ได้กับ Health Connect เวอร์ชัน 1.1.0-alpha12 ขึ้นไป
คู่มือนี้ครอบคลุมกระบวนการเขียนหรืออัปเดตข้อมูลใน Health Connect
จัดการค่าที่เป็น 0
ข้อมูลบางประเภท เช่น จำนวนก้าว ระยะทาง หรือแคลอรี อาจมีค่าเป็น 0
เขียนค่าเป็น 0 เฉพาะเมื่อแสดงถึงการไม่มีกิจกรรมอย่างแท้จริงขณะที่ผู้ใช้สวมใส่อุปกรณ์ อย่าเขียนค่าเป็น 0 หากไม่ได้สวมอุปกรณ์ ข้อมูลขาดหายไป หรือแบตเตอรี่หมด ในกรณีเช่นนี้ ให้ละเว้นระเบียนเพื่อหลีกเลี่ยงข้อมูลที่ทำให้เข้าใจผิด
ตั้งค่าโครงสร้างข้อมูล
ก่อนที่จะเขียนข้อมูล เราต้องตั้งค่าระเบียนก่อน สำหรับข้อมูลมากกว่า 50 ประเภท แต่ละประเภทจะมีโครงสร้างของตัวเอง ดูรายละเอียดเพิ่มเติมเกี่ยวกับประเภทข้อมูลที่ใช้ได้ในข้อมูลอ้างอิง 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) ))
ขอสิทธิ์จากผู้ใช้
หลังจากสร้างอินสแตนซ์ไคลเอ็นต์แล้ว แอปของคุณจะต้องขอสิทธิ์จากผู้ใช้ ผู้ใช้ต้องได้รับอนุญาตให้ให้สิทธิ์หรือปฏิเสธสิทธิ์ได้ทุกเมื่อ โดยสร้างชุดสิทธิ์สำหรับประเภทข้อมูลที่จำเป็น ตรวจสอบว่าได้ประกาศสิทธิ์ในชุดสิทธิ์ในไฟล์ Manifest ของ 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))
อัปเดตข้อมูล
หากต้องการเปลี่ยนแปลงระเบียนอย่างน้อย 1 รายการ โดยเฉพาะเมื่อคุณต้องการซิงค์ Datastore ของแอปกับข้อมูลจาก Health Connect คุณสามารถอัปเดตข้อมูลได้ การอัปเดตข้อมูลที่มีอยู่ทำได้ 2 วิธี ซึ่งขึ้นอยู่กับตัวระบุที่ใช้ค้นหาระเบียน
ข้อมูลเมตา
คุณควรตรวจสอบคลาส Metadata ก่อน เนื่องจากจำเป็นต้องใช้เมื่ออัปเดตข้อมูล เมื่อสร้าง Record แต่ละรายการใน Health Connect จะมีช่อง metadata พร็อพเพอร์ตี้ต่อไปนี้เกี่ยวข้องกับการซิงค์ข้อมูล
| พร็อพเพอร์ตี้ | คำอธิบาย |
|---|---|
id
|
Record ทุกรายการใน Health Connect มีค่า id ที่ไม่ซ้ำกันHealth Connect จะป้อนข้อมูลนี้โดยอัตโนมัติ เมื่อแทรกบันทึกใหม่ |
lastModifiedTime
|
Record ทุกรายการยังติดตามเวลาที่มีการแก้ไขระเบียนครั้งล่าสุดด้วยHealth Connect จะป้อนข้อมูลนี้โดยอัตโนมัติ |
clientRecordId
|
Record แต่ละรายการสามารถมีรหัสที่ไม่ซ้ำกันซึ่งเชื่อมโยงอยู่เพื่อใช้เป็นข้อมูลอ้างอิงใน Datastore ของแอป
แอปของคุณจะระบุค่านี้ |
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 } }
Upsert ผ่านรหัสระเบียนลูกค้า
หากคุณใช้ค่ารหัสระเบียนไคลเอ็นต์และเวอร์ชันระเบียนไคลเอ็นต์ที่ไม่บังคับ เราขอแนะนำให้ใช้ insertRecords แทน updateRecords
ฟังก์ชัน 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
นอกจากนี้ คุณควรใช้ตรรกะที่จัดการข้อยกเว้นการเขียน เช่น ข้อมูลอยู่นอกขอบเขต หรือข้อผิดพลาดของระบบภายใน คุณสามารถใช้กลยุทธ์ Backoff และลองใหม่ในกลไกการกำหนดเวลางานได้ หากเขียนลงใน Health Connect ไม่สำเร็จในท้ายที่สุด ให้ตรวจสอบว่าแอปของคุณสามารถข้ามจุดส่งออกนั้นไปได้ อย่าลืมบันทึกและรายงานข้อผิดพลาดเพื่อช่วยในการวินิจฉัย
เมื่อติดตามข้อมูล คุณสามารถทำตามคำแนะนำ 2-3 ข้อต่อไปนี้ได้ ทั้งนี้ขึ้นอยู่กับวิธีที่แอปเขียนข้อมูล
การจัดการเขตเวลา
เมื่อเขียนบันทึกตามเวลา ให้หลีกเลี่ยงการตั้งค่าออฟเซ็ตเป็น 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 ให้ใช้ความละเอียดที่เหมาะสม การใช้ความละเอียดที่เหมาะสมจะช่วยลดภาระในการจัดเก็บข้อมูล ขณะเดียวกันก็ยังคงรักษาข้อมูลที่สอดคล้องและถูกต้องไว้ได้ ความละเอียดของข้อมูลประกอบด้วย 2 สิ่งต่อไปนี้
- ความถี่ในการเขียน: ความถี่ที่แอปพลิเคชันเขียนข้อมูลใหม่ลงใน Health Connect
- เขียนข้อมูลให้บ่อยที่สุดเมื่อมีข้อมูลใหม่ โดยคำนึงถึงประสิทธิภาพของอุปกรณ์ด้วย
- เพื่อหลีกเลี่ยงผลกระทบเชิงลบต่ออายุการใช้งานแบตเตอรี่และประสิทธิภาพด้านอื่นๆ ช่วงเวลาสูงสุดระหว่างการเขียนควรเป็น 15 นาที
- ความละเอียดของข้อมูลที่เขียน: ความถี่ในการสุ่มตัวอย่างข้อมูล
- เช่น เขียนตัวอย่างอัตราการเต้นของหัวใจทุกๆ 5 วินาที
- ข้อมูลแต่ละประเภทไม่จำเป็นต้องใช้อัตราการสุ่มตัวอย่างเดียวกัน การอัปเดตข้อมูลจำนวนก้าวทุกวินาทีมีประโยชน์น้อยมากเมื่อเทียบกับความถี่ที่น้อยกว่า เช่น ทุก 60 วินาที
- อัตราการสุ่มตัวอย่างที่สูงขึ้นอาจช่วยให้ผู้ใช้เห็นข้อมูลสุขภาพและการออกกำลังกายที่ละเอียดและเจาะลึกยิ่งขึ้น ความถี่ของอัตราการสุ่มตัวอย่างควรสร้างสมดุลระหว่างรายละเอียดและประสิทธิภาพ
หลักเกณฑ์เพิ่มเติม
โปรดทำตามหลักเกณฑ์ต่อไปนี้เมื่อเขียนข้อมูล
- ในการซิงค์แต่ละครั้ง ให้เขียนเฉพาะข้อมูลใหม่และข้อมูลที่อัปเดตซึ่งมีการแก้ไขนับตั้งแต่การซิงค์ครั้งล่าสุด
- แบ่งคำขอเป็นกลุ่มๆ โดยมีระเบียนไม่เกิน 1,000 รายการต่อคำขอเขียน 1 รายการ
- จำกัดให้งานทำงานเฉพาะเมื่ออุปกรณ์ไม่มีการใช้งานและแบตเตอรี่ไม่เหลือน้อย
- สำหรับงานที่ทำงานอยู่เบื้องหลัง ให้ใช้ WorkManager เพื่อกำหนดเวลางานที่ทำเป็นระยะๆ โดยมีระยะเวลาสูงสุด 15 นาที
โค้ดต่อไปนี้ใช้ WorkManager เพื่อกำหนดเวลางานที่ทำงานอยู่เบื้องหลังเป็นระยะๆ โดยมีระยะเวลาสูงสุด 15 นาที และช่วงเวลาที่ยืดหยุ่น 5 นาที การกำหนดค่านี้ตั้งค่าโดยใช้คลาส PeriodicWorkRequest.Builder
val constraints = Constraints.Builder()
.requiresBatteryNotLow()
.requiresDeviceIdle(true)
.build()
val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>(
15,
TimeUnit.MINUTES,
5,
TimeUnit.MINUTES
)
.setConstraints(constraints)
.build()
การติดตามกิจกรรม
ซึ่งรวมถึงแอปที่ทำการติดตามตามเหตุการณ์ เช่น การออกกำลังกายและการนอนหลับ หรือการป้อนข้อมูลด้วยตนเองของผู้ใช้ เช่น โภชนาการ ระบบจะสร้างบันทึกเหล่านี้เมื่อแอปทำงานอยู่เบื้องหน้า หรือในกรณีที่เกิดขึ้นไม่บ่อยนักซึ่งมีการใช้งานแอป 2-3 ครั้งใน 1 วัน
ตรวจสอบว่าแอปของคุณไม่ได้ทำให้ Health Connect ทำงานตลอดระยะเวลาของเหตุการณ์
การเขียนข้อมูลลงใน Health Connect ต้องทำด้วยวิธีใดวิธีหนึ่งใน 2 วิธีต่อไปนี้
- ซิงค์ข้อมูลกับ Health Connect หลังจากกิจกรรมเสร็จสิ้น เช่น ซิงค์ข้อมูลเมื่อผู้ใช้สิ้นสุดเซสชันการออกกำลังกายที่ติดตาม
- กำหนดเวลางานแบบครั้งเดียวโดยใช้
WorkManagerเพื่อซิงค์ข้อมูลในภายหลัง
แนวทางปฏิบัติแนะนำสำหรับรายละเอียดและความถี่ในการเขียน
เมื่อเขียนข้อมูลลงใน Health Connect ให้ใช้ความละเอียดที่เหมาะสม การใช้ความละเอียดที่เหมาะสมจะช่วยลดภาระในการจัดเก็บข้อมูล ขณะเดียวกันก็ยังคงรักษาข้อมูลที่สอดคล้องและถูกต้องไว้ได้ ความละเอียดของข้อมูลประกอบด้วย 2 สิ่งต่อไปนี้
ความถี่ในการเขียน: ความถี่ที่แอปพลิเคชันพุชข้อมูลใหม่ไปยัง Health Connect เขียนข้อมูลให้บ่อยที่สุดเมื่อมีข้อมูลใหม่ โดยคำนึงถึงประสิทธิภาพของอุปกรณ์ด้วย เพื่อหลีกเลี่ยงผลกระทบเชิงลบต่ออายุการใช้งานแบตเตอรี่และประสิทธิภาพด้านอื่นๆ ช่วงเวลาสูงสุดระหว่างการเขียนควรเป็น 15 นาที
ความละเอียดของข้อมูลที่เขียน: ความถี่ในการสุ่มตัวอย่างข้อมูลที่พุชเข้ามา เช่น เขียนตัวอย่างอัตราการเต้นของหัวใจทุกๆ 5 วินาที ข้อมูลแต่ละประเภทไม่จำเป็นต้องมีอัตราการสุ่มตัวอย่างเท่ากัน การอัปเดตข้อมูลจำนวนก้าวทุกวินาทีมีประโยชน์น้อยมากเมื่อเทียบกับความถี่ที่น้อยกว่า เช่น ทุก 60 วินาที อย่างไรก็ตาม อัตราการสุ่มตัวอย่างที่สูงขึ้นอาจช่วยให้ผู้ใช้เห็นข้อมูลสุขภาพและการออกกำลังกายที่ละเอียดและเจาะลึกยิ่งขึ้น ความถี่ของอัตราการสุ่มตัวอย่างควรสร้างสมดุลระหว่างรายละเอียดและประสิทธิภาพ
จัดโครงสร้างระเบียนสำหรับข้อมูลซีรีส์
สำหรับประเภทข้อมูลที่ใช้ชุดตัวอย่าง เช่น HeartRateRecord คุณต้องจัดโครงสร้างระเบียนให้ถูกต้อง คุณควรสร้างระเบียนขนาดเล็กหลายรายการ โดยแต่ละรายการแสดงถึงช่วงเวลาที่เฉพาะเจาะจง แทนที่จะสร้างระเบียนเดียวที่ยาวตลอดทั้งวันซึ่งมีการอัปเดตอย่างต่อเนื่อง
ตัวอย่างเช่น สำหรับข้อมูลอัตราการเต้นของหัวใจ คุณควรสร้าง HeartRateRecord ใหม่สำหรับแต่ละนาที แต่ละระเบียนจะมีเวลาเริ่มต้นและเวลาสิ้นสุดที่ครอบคลุมนาทีนั้น และจะมีตัวอย่างอัตราการเต้นของหัวใจทั้งหมดที่บันทึกไว้ในนาทีนั้น
ในระหว่างการซิงค์กับ Health Connect เป็นประจำ (เช่น ทุก 15 นาที) แอปควรเขียนบันทึกแบบ 1 นาทีทั้งหมดที่สร้างขึ้นตั้งแต่การซิงค์ครั้งก่อนหน้า ซึ่งจะช่วยให้บันทึกมีขนาดที่จัดการได้ และปรับปรุงประสิทธิภาพการค้นหาและการประมวลผลข้อมูล
ตัวอย่างต่อไปนี้แสดงวิธีสร้าง HeartRateRecord สำหรับ 1 นาทีซึ่งมีตัวอย่างหลายรายการ
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 บ่อยที่สุดเท่าที่จะเป็นไปได้เมื่อมีข้อมูลใหม่ เพื่อหลีกเลี่ยงผลกระทบเชิงลบต่ออายุการใช้งานแบตเตอรี่และประสิทธิภาพด้านอื่นๆ ช่วงเวลาสูงสุดระหว่างการเขียนควรเป็น 15 นาที
ประเภทข้อมูล |
หน่วย |
คาดไว้ |
ตัวอย่าง |
ขั้นตอน |
ขั้นตอน |
ทุกๆ 1 นาที |
23:14 - 23:15 - 5 ก้าว 23:16 - 23:17 - 22 ก้าว 23:17 - 23:18 - 8 ก้าว |
StepsCadence |
ก้าว/นาที |
ทุกๆ 1 นาที |
23:14 - 23:15 - 5 spm 23:16 - 23:17 - 22 spm 23:17 - 23:18 - 8 spm |
การทำวีลแชร์พุช |
การผลัก |
ทุกๆ 1 นาที |
23:14 - 23:15 - 5 ครั้ง 23:16 - 23:17 - วิดพื้น 22 ครั้ง 23:17 - 23:18 - 8 ครั้ง |
ActiveCaloriesBurned |
แคลอรี่ |
ทุก 15 นาที |
23:15 - 23:30 - 2 แคลอรี 23:30 - 23:45 - 25 แคลอรี่ 23:45 - 00:00 - 5 แคลอรี่ |
TotalCaloriesBurned |
แคลอรี่ |
ทุก 15 นาที |
23:15 - 23:30 - 16 แคลอรี 23:30 - 23:45 - 16 แคลอรี่ 23:45 - 00:00 - 16 แคลอรี |
ระยะทาง |
กม./นาที |
ทุกๆ 1 นาที |
23:14-23:15 - 0.008 กม. 23:16 - 23:16 - 0.021 กม. 23:17 - 23:18 - 0.012 กม. |
ElevationGained |
ม. |
ทุกๆ 1 นาที |
20:36 - 20:37 - 3.048 ม. 20:39 - 20:40 - 3.048 ม. 23:23 - 23:24 - 9.144 ม. |
FloorsClimbed |
ชั้น |
ทุกๆ 1 นาที |
23:14 - 23:15 - 5 ชั้น 23:16 - 23:16 - 22 ชั้น 23:17 - 23:18 - 8 ชั้น |
HeartRate |
bpm |
4 ครั้งต่อนาที |
06:11:15 น. - 55 bpm 6:11:30 น. - 56 bpm 06:11:45 น. - 56 bpm 06:12:00 น. - 55 bpm |
HeartRateVariabilityRmssd |
มิลลิวินาที |
ทุกๆ 1 นาที |
6:11 น. - 23 มิลลิวินาที |
RespiratoryRate |
ครั้ง/นาที |
ทุกๆ 1 นาที |
23:14 - 23:15 - 60 ครั้ง/นาที 23:16 - 23:16 - 62 ครั้ง/นาที 23:17 - 23:18 - 64 ครั้ง/นาที |
OxygenSaturation |
% |
ทุกๆ 1 ชั่วโมง |
6:11 - 95.208% |
ควรเขียนข้อมูลลงใน Health Connect เมื่อสิ้นสุดเซสชันการออกกำลังกายหรือการนอนหลับ สำหรับการติดตามกิจกรรม เช่น การออกกำลังกายและการนอนหลับ หรือการป้อนข้อมูลด้วยตนเองของผู้ใช้ เช่น โภชนาการ ระบบจะสร้างบันทึกเหล่านี้เมื่อแอปทำงานอยู่เบื้องหน้า หรือในกรณีที่เกิดขึ้นไม่บ่อยนักซึ่งมีการใช้งานแอป 2-3 ครั้งต่อวัน
ตรวจสอบว่าแอปของคุณไม่ได้ทำให้ Health Connect ทำงานตลอดระยะเวลาของเหตุการณ์
การเขียนข้อมูลลงใน Health Connect ต้องทำด้วยวิธีใดวิธีหนึ่งใน 2 วิธีต่อไปนี้
- ซิงค์ข้อมูลกับ Health Connect หลังจากกิจกรรมเสร็จสิ้น เช่น ซิงค์ข้อมูลเมื่อผู้ใช้สิ้นสุดเซสชันการออกกำลังกายที่ติดตาม
- กำหนดเวลางานแบบครั้งเดียวโดยใช้ WorkManager เพื่อซิงค์ข้อมูลในภายหลัง
เซสชันการออกกำลังกายและการนอนหลับ
อย่างน้อยที่สุด แอปพลิเคชันของคุณควรเป็นไปตามคำแนะนำในคอลัมน์ที่คาดหวังในตารางที่ 2 หากเป็นไปได้ ให้ทำตามคำแนะนำในคอลัมน์ดีที่สุด
ตารางต่อไปนี้แสดงวิธีเขียนข้อมูลระหว่างการออกกำลังกาย
ประเภทข้อมูล |
หน่วย |
คาดว่าจะได้รับ |
ขอแสดงความนับถือ |
ตัวอย่าง |
ขั้นตอน |
ขั้นตอน |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 5 ก้าว 23:16 - 23:17 - 22 ก้าว 23:17 - 23:18 - 8 ก้าว |
StepsCadence |
ก้าว/นาที |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 35 spm 23:16 - 23:17 - 37 spm 23:17 - 23:18 - 40 spm |
การทำวีลแชร์พุช |
การผลัก |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 5 pushes 23:16 - 23:17 - วิดพื้น 22 ครั้ง 23:17 - 23:18 - 8 ครั้ง |
CyclingPedalingCadence |
rpm |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 65 rpm 23:16 - 23:17 - 70 rpm 23:17 - 23:18 - 68 rpm |
กำลังไฟ |
วัตต์ |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 250 วัตต์ 23:16 - 23:17 - 255 วัตต์ 23:17 - 23:18 - 245 วัตต์ |
ความเร็ว |
กม./นาที |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 0.3 กม./นาที 23:16 - 23:17 - 0.4 กม./นาที 23:17 - 23:18 -0.4 กม./นาที |
ระยะทาง |
กม./ม. |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 0.008 กม. 23:16 - 23:16 - 0.021 กม. 23:17 - 23:18 - 0.012 กม. |
ActiveCaloriesBurned |
แคลอรี่ |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 20 แคลอรี่ 23:16 - 23:17 - 20 แคลอรี่ 23:17 - 23:18 - 25 แคลอรี่ |
TotalCaloriesBurned |
แคลอรี่ |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
23:14-23:15 - 36 แคลอรี่ 23:16 - 23:17 - 36 แคลอรี่ 23:17 - 23:18 - 41 แคลอรี |
ElevationGained |
ม. |
ทุกๆ 1 นาที |
ทุก 1 วินาที |
20:36 - 20:37 - 3.048 ม. 20:39 - 20:40 - 3.048 ม. 23:23 - 23:24 - 9.144 ม. |
ExerciseRoutes |
lat/lng/alt |
ทุก 3-5 วินาที |
ทุก 1 วินาที |
|
HeartRate |
bpm |
4 ครั้งต่อนาที |
ทุก 1 วินาที |
23:14-23:15 - 150 bpm |
ตารางที่ 3 แสดงวิธีเขียนข้อมูลระหว่างหรือหลังเซสชันการนอนหลับ
ประเภทข้อมูล |
หน่วย |
ตัวอย่างที่คาดไว้ |
ตัวอย่าง |
การแบ่งระยะการนอนหลับ |
เก็บพักไว้ |
ระยะเวลาที่ละเอียดต่อระยะการนอนหลับ |
23:46 - 23:50 - ตื่น 23:50 - 23:56 น. - หลับตื้น 23:56 - 00:16 - หลับลึก |
RestingHeartRate |
bpm |
ค่ารายวันเดียว (คาดว่าจะได้รับเป็นสิ่งแรกในตอนเช้า) |
06:11 น. - 60 bpm |
OxygenSaturation |
% |
ค่ารายวันเดียว (คาดว่าจะได้รับในช่วงเช้า) |
6:11 - 95.208% |
มหกรรมกีฬา
แนวทางนี้ใช้ประเภทและโครงสร้างข้อมูลที่มีอยู่ และจะตรวจสอบความเข้ากันได้กับการใช้งาน 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 จะแสดงรายการข้อยกเว้นที่อาจเกิดขึ้น
โดยทั่วไปแล้ว แอปควรจัดการข้อยกเว้นต่อไปนี้
| ข้อยกเว้น | คำอธิบาย | แนวทางปฏิบัติแนะนำที่แนะนำ |
|---|---|---|
IllegalStateException
| เกิดสถานการณ์ใดสถานการณ์หนึ่งต่อไปนี้
| จัดการปัญหาที่อาจเกิดขึ้นกับอินพุตก่อนที่จะส่งคำขอ เราขอแนะนำให้กำหนดค่าให้กับตัวแปรหรือใช้เป็นพารามิเตอร์ภายในฟังก์ชันที่กำหนดเองแทนการใช้โดยตรงในคำขอ เพื่อให้คุณใช้กลยุทธ์การจัดการข้อผิดพลาดได้ |
IOException
| พบปัญหาเมื่ออ่านและเขียนข้อมูลจากดิสก์ | วิธีหลีกเลี่ยงปัญหานี้มีดังนี้
|
RemoteException
| เกิดข้อผิดพลาดภายในหรือในการสื่อสารกับบริการพื้นฐานที่ SDK เชื่อมต่ออยู่ ตัวอย่างเช่น แอปของคุณพยายามลบระเบียนที่มี uid ที่ระบุ อย่างไรก็ตาม ระบบจะส่งข้อยกเว้นหลังจากที่แอปพบเมื่อตรวจสอบในบริการที่เกี่ยวข้องว่าไม่มีระเบียนดังกล่าว
| วิธีหลีกเลี่ยงปัญหานี้มีดังนี้
|
SecurityException
| ปัญหาจะเกิดขึ้นเมื่อคำขอต้องใช้สิทธิ์ที่ไม่ได้รับอนุญาต | เพื่อหลีกเลี่ยงปัญหานี้ โปรดตรวจสอบว่าคุณได้ประกาศการใช้ประเภทข้อมูลของ Health Connect สำหรับแอปที่เผยแพร่แล้ว นอกจากนี้ คุณต้องประกาศสิทธิ์ของ Health Connect ในไฟล์ Manifest และในกิจกรรมของคุณด้วย |