คู่มือนี้ใช้ได้กับ Health Connect เวอร์ชัน 1.1.0-alpha11
Health Connect มีประเภทข้อมูลการออกกำลังกายที่วางแผนไว้เพื่อให้แอปฝึกซ้อม เขียนแผนการฝึกซ้อม และช่วยให้แอปออกกำลังกายอ่านแผนการฝึกซ้อมได้ ระบบจะอ่านการออกกำลังกายที่บันทึกไว้ (การออกกำลังกาย) เพื่อวิเคราะห์ประสิทธิภาพที่ปรับเปลี่ยนในแบบของคุณ เพื่อช่วยให้ผู้ใช้บรรลุเป้าหมายการฝึกซ้อม
ความพร้อมใช้งานของฟีเจอร์
หากต้องการดูว่าอุปกรณ์ของผู้ใช้รองรับแผนการฝึกใน Health Connect หรือไม่ ให้ตรวจสอบความพร้อมใช้งานของFEATURE_PLANNED_EXERCISE
ในไคลเอ็นต์ ดังนี้
if (healthConnectClient
.features
.getFeatureStatus(
HealthConnectFeatures.FEATURE_PLANNED_EXERCISE
) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {
// Feature is available
} else {
// Feature isn't available
}
ดูข้อมูลเพิ่มเติมได้ที่ตรวจสอบความพร้อมใช้งานของฟีเจอร์
สิทธิ์ที่จำเป็น
การเข้าถึงการออกกำลังกายที่วางแผนไว้จะได้รับการปกป้องโดยสิทธิ์ต่อไปนี้
android.permission.health.READ_PLANNED_EXERCISE
android.permission.health.WRITE_PLANNED_EXERCISE
หากต้องการเพิ่มความสามารถในการออกกำลังกายที่วางแผนไว้ลงในแอป ให้เริ่มต้นด้วยการขอสิทธิ์เขียนสำหรับประเภทข้อมูล PlannedExerciseSession
นี่คือสิทธิ์ที่คุณต้องประกาศเพื่อให้เขียน การออกกำลังกายที่วางแผนไว้ได้
<application>
<uses-permission
android:name="android.permission.health.WRITE_PLANNED_EXERCISE" />
...
</application>
หากต้องการอ่านการออกกำลังกายที่วางแผนไว้ คุณต้องขอสิทธิ์ต่อไปนี้
<application>
<uses-permission
android:name="android.permission.health.READ_PLANNED_EXERCISE" />
...
</application>
ขอสิทธิ์จากผู้ใช้
หลังจากสร้างอินสแตนซ์ไคลเอ็นต์แล้ว แอปของคุณต้องขอสิทธิ์จากผู้ใช้ ผู้ใช้ต้องได้รับอนุญาตให้ให้หรือปฏิเสธสิทธิ์ได้ทุกเมื่อ
โดยให้สร้างชุดสิทธิ์สำหรับประเภทข้อมูลที่จำเป็น ตรวจสอบว่าได้ประกาศสิทธิ์ในชุดไว้ใน Android manifest ก่อน
// Create a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getWritePermission(ExerciseSessionRecord::class)
)
ใช้ getGrantedPermissions
เพื่อดูว่าแอปของคุณได้รับสิทธิ์ที่จำเป็นแล้วหรือไม่ หากไม่มี ให้ใช้ createRequestPermissionResultContract
เพื่อขอสิทธิ์เหล่านั้น ซึ่งจะแสดงหน้าจอสิทธิ์ของ Health Connect
// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()
val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
if (granted.containsAll(PERMISSIONS)) {
// Permissions successfully granted
} else {
// Lack of required permissions
}
}
suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
val granted = healthConnectClient.permissionController.getGrantedPermissions()
if (granted.containsAll(PERMISSIONS)) {
// Permissions already granted; proceed with inserting or reading data
} else {
requestPermissions.launch(PERMISSIONS)
}
}
เนื่องจากผู้ใช้สามารถให้หรือเพิกถอนสิทธิ์ได้ทุกเมื่อ แอปของคุณจึงต้อง ตรวจสอบสิทธิ์ที่ได้รับเป็นระยะๆ และจัดการสถานการณ์ที่ สิทธิ์สูญหาย
สิทธิ์ที่เกี่ยวข้อง
แผนการฝึกจะลิงก์กับเซสชันการออกกำลังกาย ดังนั้น ผู้ใช้ต้องให้สิทธิ์ในการใช้บันทึกแต่ละประเภทที่เกี่ยวข้องกับแผนการฝึกเพื่อใช้ฟีเจอร์นี้ของ Health Connect ได้อย่างเต็มที่
ตัวอย่างเช่น หากแผนการฝึกวัดอัตราการเต้นของหัวใจของผู้ใช้ระหว่างการวิ่งหลายครั้ง นักพัฒนาแอปอาจต้องประกาศสิทธิ์ต่อไปนี้และผู้ใช้ต้องให้สิทธิ์เพื่อเขียนเซสชันการออกกำลังกายและอ่าน ผลลัพธ์เพื่อการประเมินในภายหลัง
android.permission.health.READ_EXERCISE
android.permission.health.READ_EXERCISE_ROUTES
android.permission.health.READ_HEART_RATE
android.permission.health.WRITE_EXERCISE
android.permission.health.WRITE_EXERCISE_ROUTE
android.permission.health.WRITE_HEART_RATE
อย่างไรก็ตาม บ่อยครั้งที่แอปที่สร้างแผนการฝึกและประเมินประสิทธิภาพ เทียบกับแผนไม่ใช่แอปเดียวกับที่ใช้แผนการฝึกและเขียน ข้อมูลการออกกำลังกายจริง สิทธิ์การอ่านและการเขียน บางอย่างอาจไม่จำเป็น ทั้งนี้ขึ้นอยู่กับประเภทแอป ตัวอย่างเช่น คุณอาจต้องมีสิทธิ์ต่อไปนี้ สำหรับแอปแต่ละประเภท
แอปแผนการฝึก | แอปออกกำลังกาย |
---|---|
WRITE_PLANNED_EXERCISE |
READ_PLANNED_EXERCISE |
READ_EXERCISE |
WRITE_EXERCISE |
READ_EXERCISE_ROUTES |
WRITE_EXERCISE_ROUTE |
READ_HEART_RATE |
WRITE_HEART_RATE |
ข้อมูลที่รวมอยู่ในบันทึกเซสชันการออกกำลังกายที่วางแผนไว้
- ชื่อเซสชัน
- รายการช่วงเวลาออกกำลังกายที่วางแผนไว้
- เวลาเริ่มต้นและสิ้นสุดของเซสชัน
- ประเภทการออกกำลังกาย
- หมายเหตุสำหรับกิจกรรม
- ข้อมูลเมตา
- รหัสเซสชันการออกกำลังกายที่เสร็จสมบูรณ์ - ระบบจะเขียนรหัสนี้โดยอัตโนมัติหลังจากเซสชันการออกกำลังกายที่เกี่ยวข้องกับเซสชันการออกกำลังกายที่วางแผนไว้เสร็จสมบูรณ์
ข้อมูลที่รวมอยู่ในบันทึกช่วงเวลาออกกำลังกายที่วางแผนไว้
บล็อกการออกกำลังกายที่วางแผนไว้จะมีรายการขั้นตอนการออกกำลังกายเพื่อรองรับ การทำซ้ำขั้นตอนกลุ่มต่างๆ (เช่น ทำท่าดัมเบลยกแขน เบอร์พี และครันช์ 5 ครั้งติดต่อกัน)
- คำอธิบายของบล็อก
- รายการขั้นตอนการออกกำลังกายที่วางแผนไว้
- จำนวนการทำซ้ำ
ข้อมูลที่รวมอยู่ในบันทึกขั้นตอนการออกกำลังกายที่วางแผนไว้
- คำอธิบายขั้นตอน
- หมวดหมู่การออกกำลังกาย
- ประเภทการออกกำลังกาย
- รายการเป้าหมายด้านประสิทธิภาพ
- เป้าหมายการดูจนจบ
การรวมที่รองรับ
ไม่มีการรวบรวมที่รองรับสำหรับข้อมูลประเภทนี้
ตัวอย่างการใช้งาน
สมมติว่าผู้ใช้วางแผนที่จะวิ่ง 90 นาทีในอีก 2 วันข้างหน้า การวิ่งนี้จะประกอบด้วย วิ่งรอบทะเลสาบ 3 รอบโดยมีอัตราการเต้นของหัวใจเป้าหมายระหว่าง 90 ถึง 110 ครั้งต่อนาที
- เซสชันการออกกำลังกายที่วางแผนไว้ซึ่งมีองค์ประกอบต่อไปนี้จะได้รับการกำหนดโดยผู้ใช้ใน
แอปแผนการฝึก
- การเริ่มต้นและสิ้นสุดการเรียกใช้ที่วางแผนไว้
- ประเภทการออกกำลังกาย (วิ่ง)
- จำนวนรอบ (การทำซ้ำ)
- เป้าหมายประสิทธิภาพสำหรับอัตราการเต้นของหัวใจ (ระหว่าง 90 ถึง 110 bpm)
- ข้อมูลนี้จะจัดกลุ่มเป็นบล็อกการออกกำลังกายและขั้นตอนต่างๆ แล้วเขียนลงใน Health Connect โดยแอปแผนการฝึกเป็น
PlannedExerciseSessionRecord
- ผู้ใช้ทำเซสชันที่วางแผนไว้ (วิ่ง)
- ระบบจะบันทึกข้อมูลการออกกำลังกายที่เกี่ยวข้องกับเซสชันในลักษณะใดลักษณะหนึ่งต่อไปนี้
- โดยอุปกรณ์ที่สวมใส่ได้ระหว่างเซสชัน เช่น อัตราการเต้นของหัวใจ
ระบบจะเขียนข้อมูลนี้ลงใน Health Connect เป็นประเภทบันทึกสำหรับ
กิจกรรม ในกรณีนี้คือ
HeartRateRecord
- ผู้ใช้ดำเนินการด้วยตนเองหลังจากเซสชัน เช่น การระบุจุดเริ่มต้นและจุดสิ้นสุดของการวิ่งจริง ระบบจะเขียนข้อมูลนี้ลงใน Health
Connect เป็น
ExerciseSessionRecord
- โดยอุปกรณ์ที่สวมใส่ได้ระหว่างเซสชัน เช่น อัตราการเต้นของหัวใจ
ระบบจะเขียนข้อมูลนี้ลงใน Health Connect เป็นประเภทบันทึกสำหรับ
กิจกรรม ในกรณีนี้คือ
- ในภายหลัง แอปแผนการฝึกจะอ่านข้อมูลจาก Health Connect เพื่อ ประเมินประสิทธิภาพจริงเทียบกับเป้าหมายที่ผู้ใช้ตั้งไว้ใน เซสชันการออกกำลังกายที่วางแผนไว้
วางแผนการออกกำลังกายและตั้งเป้าหมาย
ผู้ใช้อาจวางแผนการออกกำลังกายในอนาคตและตั้งเป้าหมาย เขียนข้อมูลนี้ไปยัง Health Connect เป็นเซสชันการออกกำลังกายที่วางแผนไว้
ในตัวอย่างที่อธิบายไว้ในตัวอย่างการใช้งาน ผู้ใช้วางแผนการวิ่ง 90 นาทีในอีก 2 วันข้างหน้า การวิ่งนี้จะประกอบด้วยการวิ่งรอบทะเลสาบ 3 รอบ โดยมีอัตราการเต้นของหัวใจเป้าหมายระหว่าง 90 ถึง 110 ครั้งต่อนาที
คุณอาจพบข้อมูลโค้ดลักษณะนี้ในตัวแฮนเดิลอร์แบบฟอร์มสำหรับแอปที่บันทึก เซสชันการออกกำลังกายที่วางแผนไว้ไปยัง Health Connect นอกจากนี้ ยังอาจพบใน จุดรับข้อมูลสำหรับการผสานรวม เช่น กับบริการที่เสนอการฝึกอบรม
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class))) {
// The user hasn't granted the app permission to write planned exercise session data.
return
}
val plannedDuration = Duration.ofMinutes(90)
val plannedStartDate = LocalDate.now().plusDays(2)
val plannedExerciseSessionRecord = PlannedExerciseSessionRecord(
startDate = plannedStartDate,
duration = plannedDuration,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
blocks = listOf(
PlannedExerciseBlock(
repetitions = 1, steps = listOf(
PlannedExerciseStep(
exerciseType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING,
exercisePhase = PlannedExerciseStep.EXERCISE_PHASE_ACTIVE,
completionGoal = ExerciseCompletionGoal.RepetitionsGoal(repetitions = 3),
performanceTargets = listOf(
ExercisePerformanceTarget.HeartRateTarget(
minHeartRate = 90.0, maxHeartRate = 110.0
)
)
),
), description = "Three laps around the lake"
)
),
title = "Run at lake",
notes = null,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedPlannedExerciseSessions =
healthConnectClient.insertRecords(listOf(plannedExerciseSessionRecord)).recordIdsList
val insertedPlannedExerciseSessionId = insertedPlannedExerciseSessions.first()
บันทึกข้อมูลการออกกำลังกายและกิจกรรม
2 วันต่อมา ผู้ใช้บันทึกเซสชันการออกกำลังกายจริง เขียนข้อมูลนี้ลงใน Health Connect เป็นเซสชันการออกกำลังกาย
ในตัวอย่างนี้ ระยะเวลาเซสชันของผู้ใช้ตรงกับระยะเวลาที่วางแผนไว้ ทุกประการ
คุณอาจเห็นข้อมูลโค้ดต่อไปนี้ในตัวแฮนเดิลแบบฟอร์มสำหรับแอปที่บันทึก เซสชันการออกกำลังกายไปยัง Health Connect นอกจากนี้ ยังอาจพบในตัวแฮนเดิลการนำเข้าและส่งออกข้อมูลสำหรับอุปกรณ์สวมใส่ที่ตรวจจับและบันทึกเซสชันการออกกำลังกายได้
insertedPlannedExerciseSessionId
ที่นี่จะนำมาจากตัวอย่างก่อนหน้า ในแอปจริง ระบบจะกำหนดรหัสโดยผู้ใช้เลือกเซสชันการออกกำลังกายที่วางแผนไว้จากรายการเซสชันที่มีอยู่
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(ExerciseSessionRecord::class))) {
// The user doesn't granted the app permission to write exercise session data.
return
}
val sessionDuration = Duration.ofMinutes(90)
val sessionEndTime = Instant.now()
val sessionStartTime = sessionEndTime.minus(sessionDuration)
val exerciseSessionRecord = ExerciseSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
segments = listOf(
ExerciseSegment(
startTime = sessionStartTime,
endTime = sessionEndTime,
repetitions = 3,
segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING
)
),
title = "Run at lake",
plannedExerciseSessionId = insertedPlannedExerciseSessionId,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedExerciseSessions =
healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
นอกจากนี้ อุปกรณ์ที่สวมใส่ได้ยังบันทึกอัตราการเต้นของหัวใจตลอดการวิ่งด้วย คุณใช้ข้อมูลโค้ดต่อไปนี้ เพื่อสร้างระเบียนภายในช่วงเป้าหมายได้
ในแอปจริง ส่วนหลักของข้อมูลโค้ดนี้อาจอยู่ในแฮนเดิล สำหรับข้อความจากอุปกรณ์ที่สวมใส่ได้ ซึ่งจะเขียนการวัดไปยัง Health Connect เมื่อรวบรวม
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(HeartRateRecord::class))) {
// The user doesn't granted the app permission to write heart rate record data.
return
}
val samples = mutableListOf<HeartRateRecord.Sample>()
var currentTime = sessionStartTime
while (currentTime.isBefore(sessionEndTime)) {
val bpm = Random.nextInt(21) + 90
val heartRateRecord = HeartRateRecord.Sample(
time = currentTime,
beatsPerMinute = bpm.toLong(),
)
samples.add(heartRateRecord)
currentTime = currentTime.plusSeconds(180)
}
val heartRateRecord = HeartRateRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
samples = samples,
metadata = Metadata.autoRecorded(
device = Device(type = Device.Companion.TYPE_WATCH)
)
)
val insertedHeartRateRecords = healthConnectClient.insertRecords(listOf(heartRateRecord))
ประเมินเป้าหมายด้านประสิทธิภาพ
ในวันถัดจากวันที่ผู้ใช้ออกกำลังกาย คุณสามารถดึงข้อมูลการออกกำลังกายที่บันทึกไว้ ตรวจสอบ เป้าหมายการออกกำลังกายที่วางแผนไว้ และประเมินข้อมูลประเภทอื่นๆ เพื่อ ดูว่าบรรลุเป้าหมายที่ตั้งไว้หรือไม่
โดยปกติแล้ว คุณจะพบข้อมูลโค้ดเช่นนี้ในงานที่ทำเป็นระยะๆ เพื่อประเมิน เป้าหมายประสิทธิภาพ หรือเมื่อโหลดรายการแบบฝึกหัดและแสดง การแจ้งเตือนเกี่ยวกับเป้าหมายประสิทธิภาพในแอป
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.containsAll(
listOf(
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class)
)
)
) {
// The user doesn't granted the app permission to read exercise session record data.
return
}
val searchDuration = Duration.ofDays(1)
val searchEndTime = Instant.now()
val searchStartTime = searchEndTime.minus(searchDuration)
val response = healthConnectClient.readRecords(
ReadRecordsRequest<ExerciseSessionRecord>(
timeRangeFilter = TimeRangeFilter.between(searchStartTime, searchEndTime)
)
)
for (exerciseRecord in response.records) {
val plannedExerciseRecordId = exerciseRecord.plannedExerciseSessionId
val plannedExerciseRecord =
if (plannedExerciseRecordId == null) null else healthConnectClient.readRecord(
PlannedExerciseSessionRecord::class, plannedExerciseRecordId
).record
if (plannedExerciseRecord != null) {
val aggregateRequest = AggregateRequest(
metrics = setOf(HeartRateRecord.BPM_AVG),
timeRangeFilter = TimeRangeFilter.between(
exerciseRecord.startTime, exerciseRecord.endTime
),
)
val aggregationResult = healthConnectClient.aggregate(aggregateRequest)
val maxBpm = aggregationResult[HeartRateRecord.BPM_MAX]
val minBpm = aggregationResult[HeartRateRecord.BPM_MIN]
if (maxBpm != null && minBpm != null) {
plannedExerciseRecord.blocks.forEach { block ->
block.steps.forEach { step ->
step.performanceTargets.forEach { target ->
when (target) {
is ExercisePerformanceTarget.HeartRateTarget -> {
val minTarget = target.minHeartRate
val maxTarget = target.maxHeartRate
if(
minBpm >= minTarget && maxBpm <= maxTarget
) {
// Success!
}
}
// Handle more target types
}
}
}
}
}
}
}
}
เซสชันการออกกำลังกาย
เซสชันการออกกำลังกายอาจประกอบด้วยกิจกรรมต่างๆ ตั้งแต่การวิ่งไปจนถึงแบดมินตัน
เขียนข้อมูลเซสชันการออกกำลังกาย
วิธีสร้างคำขอแทรกที่มีเซสชันมีดังนี้
suspend fun writeExerciseSession(healthConnectClient: HealthConnectClient) {
healthConnectClient.insertRecords(
listOf(
ExerciseSessionRecord(
startTime = START_TIME,
startZoneOffset = START_ZONE_OFFSET,
endTime = END_TIME,
endZoneOffset = END_ZONE_OFFSET,
exerciseType = ExerciseSessionRecord.ExerciseType.RUNNING,
title = "My Run"
),
// ... other records
)
)
}
อ่านเซสชันการออกกำลังกาย
ตัวอย่างวิธีอ่านเซสชันการออกกำลังกายมีดังนี้
suspend fun readExerciseSessions(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response =
healthConnectClient.readRecords(
ReadRecordsRequest(
ExerciseSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (exerciseRecord in response.records) {
// Process each exercise record
// Optionally pull in with other data sources of the same time range.
val distanceRecord =
healthConnectClient
.readRecords(
ReadRecordsRequest(
DistanceRecord::class,
timeRangeFilter =
TimeRangeFilter.between(
exerciseRecord.startTime,
exerciseRecord.endTime
)
)
)
.records
}
}
เขียนข้อมูลประเภทย่อย
เซสชันยังประกอบด้วยข้อมูลประเภทย่อยที่ไม่บังคับ ซึ่งจะช่วยเพิ่มข้อมูลเพิ่มเติมให้กับเซสชันได้ด้วย
เช่น เซสชันการออกกำลังกายอาจรวมคลาส ExerciseSegment
, ExerciseLap
และ ExerciseRoute
ดังนี้
val segments = listOf(
ExerciseSegment(
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
segmentType = ActivitySegmentType.BENCH_PRESS,
repetitions = 373
)
)
val laps = listOf(
ExerciseLap(
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
length = 0.meters
)
)
ExerciseSessionRecord(
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_CALISTHENICS,
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
segments = segments,
laps = laps,
route = route
)