แผนการฝึก

คู่มือนี้ใช้ได้กับ 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

ประกาศสิทธิ์เหล่านี้ใน Play Console สําหรับแอปของคุณ รวมถึงในไฟล์ Manifest ของแอป

<application>
  <uses-permission
android:name="android.permission.health.READ_PLANNED_EXERCISE" />
  <uses-permission
android:name="android.permission.health.WRITE_PLANNED_EXERCISE" />
...
</application>

คุณมีหน้าที่รับผิดชอบในการประกาศสิทธิ์ที่เหมาะสมทั้งหมดที่ตั้งใจจะใช้ในอุปกรณ์และแอป นอกจากนี้ คุณควรตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์แต่ละรายการแล้วก่อนใช้งาน

แผนการฝึกอบรมจะลิงก์กับเซสชันการออกกำลังกาย ดังนั้น ผู้ใช้จึงต้องให้สิทธิ์ใช้เรคคอร์ดแต่ละประเภทที่เกี่ยวข้องกับแผนการฝึกอบรมเพื่อใช้ประโยชน์จากฟีเจอร์นี้ของ Health Connect อย่างเต็มที่

ตัวอย่างเช่น หากแผนการฝึกวัดอัตราการเต้นของหัวใจของผู้ใช้ระหว่างการวิ่งหลายครั้ง นักพัฒนาแอปอาจต้องประกาศสิทธิ์ต่อไปนี้และผู้ใช้ต้องให้สิทธิ์เพื่อเขียนเซสชันการออกกําลังกายและอ่านผลลัพธ์เพื่อประเมินในภายหลัง

  • android.permission.health.READ_EXERCISE
  • android.permission.health.READ_EXERCISE_ROUTE
  • 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_ROUTE WRITE_EXERCISE_ROUTE
READ_HEART_RATE WRITE_HEART_RATE

ข้อมูลที่รวมอยู่ในระเบียนเซสชันการออกกำลังกายที่วางแผนไว้

  • ชื่อเซสชัน
  • รายการกลุ่มการออกกำลังกายตามแผนที่วางไว้
  • เวลาเริ่มต้นและสิ้นสุดของเซสชัน
  • ประเภทการออกกำลังกาย
  • หมายเหตุสำหรับกิจกรรม
  • ข้อมูลเมตา
  • รหัสเซสชันการออกกำลังกายที่เสร็จสมบูรณ์ — ระบบจะเขียนข้อมูลนี้โดยอัตโนมัติหลังจากเซสชันการออกกำลังกายที่เกี่ยวข้องกับเซสชันการออกกำลังกายที่วางแผนไว้นี้เสร็จสมบูรณ์

ข้อมูลที่รวมอยู่ในระเบียนบล็อกการออกกำลังกายที่วางแผนไว้

บล็อกการออกกำลังกายที่ตั้งเวลาไว้จะมีรายการขั้นตอนการออกกำลังกายเพื่อรองรับการทำซ้ำของกลุ่มขั้นตอนต่างๆ (เช่น ทำท่าดึงข้อศอกขึ้น เบิร์กพี และเกร็งหน้าท้องตามลำดับ 5 ครั้งติดต่อกัน)

ข้อมูลที่รวมอยู่ในระเบียนขั้นตอนการออกกำลังกายที่วางแผนไว้

การรวมที่รองรับ

ประเภทข้อมูลนี้ไม่รองรับการรวม

ตัวอย่างการใช้งาน

สมมติว่าผู้ใช้วางแผนที่จะวิ่งเป็นเวลา 90 นาทีในอีก 2 วันข้างหน้า การวิ่งนี้จะวิ่งรอบทะเลสาบ 3 รอบโดยมีอัตราการเต้นของหัวใจเป้าหมายระหว่าง 90 ถึง 110 ครั้งต่อนาที

  1. เซสชันการออกกำลังกายที่วางแผนไว้ซึ่งผู้ใช้กำหนดข้อมูลต่อไปนี้ในแอปแผนการฝึกอบรม
    1. เวลาที่เริ่มต้นและสิ้นสุดการเรียกใช้ตามแผนที่วางไว้
    2. ประเภทการออกกำลังกาย (การวิ่ง)
    3. จำนวนรอบ (จำนวนครั้ง)
    4. เป้าหมายประสิทธิภาพสำหรับอัตราการเต้นของหัวใจ (ระหว่าง 90 ถึง 110 bpm)
  2. แอปแผนการฝึกอบรมจะจัดกลุ่มข้อมูลนี้ออกเป็นกลุ่มและขั้นตอนการออกกำลังกาย และเขียนลงใน Health Connect เป็นPlannedExerciseSessionRecord
  3. ผู้ใช้ทําเซสชันที่วางแผนไว้ (ทํางานอยู่)
  4. ระบบจะบันทึกข้อมูลการออกกำลังกายที่เกี่ยวข้องกับเซสชันด้วยวิธีใดวิธีหนึ่งต่อไปนี้
    1. อุปกรณ์ที่สวมใส่ได้ระหว่างเซสชัน เช่น อัตราการเต้นของหัวใจ ระบบจะเขียนข้อมูลนี้ลงใน Health Connect เป็นประเภทระเบียนสำหรับกิจกรรม ในกรณีนี้คือ HeartRateRecord
    2. ผู้ใช้ดำเนินการเองหลังจากเซสชัน เช่น ระบุการเริ่มต้นและสิ้นสุดของการเรียกใช้จริง ระบบจะเขียนข้อมูลนี้ลงใน Health Connect เป็น ExerciseSessionRecord
  5. หลังจากนั้น แอปแผนการฝึกอบรมจะอ่านข้อมูลจาก Health Connect เพื่อประเมินประสิทธิภาพจริงเทียบกับเป้าหมายที่ผู้ใช้กำหนดไว้ในเซสชันการออกกำลังกายที่ตั้งไว้

วางแผนการออกกำลังกายและตั้งเป้าหมาย

ผู้ใช้อาจวางแผนการออกกำลังกายในอนาคตและตั้งเป้าหมาย เขียนข้อมูลนี้ลงใน Health Connect เป็นเซสชันการออกกําลังกายที่วางแผนไว้

ในตัวอย่างที่อธิบายไว้ในตัวอย่างการใช้งาน ผู้ใช้วางแผนที่จะวิ่งเป็นเวลา 90 นาทีในอีก 2 วันข้างหน้า การวิ่งนี้จะวิ่งรอบทะเลสาบ 3 รอบโดยมีอัตราการเต้นของหัวใจเป้าหมายระหว่าง 90 ถึง 110 ครั้งต่อนาที

คุณอาจพบข้อมูลโค้ดสั้นๆ เช่นนี้ในตัวแฮนเดิลแบบฟอร์มสําหรับแอปที่บันทึกเซสชันการออกกําลังกายที่วางแผนไว้ไปยัง Health Connect หรือจะดูที่จุดส่งผ่านข้อมูลสำหรับการผสานรวมก็ได้ เช่น บริการที่เสนอการฝึกอบรม

// Ensure 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 = ExerciseSessionRecord.EXERCISE_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
)
val insertedPlannedExerciseSessions =
    healthConnectClient.insertRecords(listOf(plannedExerciseSessionRecord)).recordIdsList
val insertedPlannedExerciseSessionId = insertedPlannedExerciseSessions.first()

บันทึกข้อมูลการออกกําลังกายและกิจกรรม

2 วันต่อมา ผู้ใช้บันทึกเซสชันการออกกําลังกายจริง เขียนข้อมูลนี้ลงใน Health Connect เป็นเซสชันการออกกำลังกาย

ในตัวอย่างนี้ ระยะเวลาเซสชันของผู้ใช้ตรงกับระยะเวลาที่วางแผนไว้ทุกประการ

คุณอาจพบข้อมูลโค้ดต่อไปนี้ในตัวแฮนเดิลแบบฟอร์มสําหรับแอปที่บันทึกเซสชันการออกกําลังกายไปยัง Health Connect นอกจากนี้ยังอาจพบในตัวแฮนเดิลการส่งออกและนําเข้าข้อมูลสําหรับอุปกรณ์ที่สวมใส่ได้ซึ่งสามารถตรวจจับและบันทึกเซสชันการออกกําลังกาย

insertedPlannedExerciseSessionId ที่นี่ใช้ซ้ำจากตัวอย่างก่อนหน้า ในแอปจริง รหัสจะกำหนดโดยผู้ใช้ที่เลือกเซสชันการออกกำลังกายที่วางแผนไว้จากรายการเซสชันที่มีอยู่

// Ensure 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,
)
val insertedExerciseSessions =
    healthConnectClient.insertRecords(listOf(exerciseSessionRecord))

อุปกรณ์ที่สวมใส่ได้ยังบันทึกอัตราการเต้นของหัวใจตลอดการวิ่งด้วย ข้อมูลโค้ดต่อไปนี้อาจใช้สร้างระเบียนภายในช่วงเป้าหมายได้

ในแอปจริง ชิ้นส่วนหลักของข้อมูลโค้ดนี้อาจอยู่ในตัวแฮนเดิลสำหรับข้อความจากอุปกรณ์ที่สวมใส่ได้ ซึ่งจะเขียนการวัดลงใน Health Connect เมื่อรวบรวมข้อมูล

// Ensure 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,
)
val insertedHeartRateRecords = healthConnectClient.insertRecords(listOf(heartRateRecord))

ประเมินเป้าหมายด้านประสิทธิภาพ

ในวันถัดจากการออกกำลังกายของผู้ใช้ คุณสามารถเรียกข้อมูลการออกกำลังกายที่บันทึกไว้ ตรวจสอบเป้าหมายการออกกำลังกายที่วางแผนไว้ และประเมินประเภทข้อมูลอื่นๆ เพื่อพิจารณาว่าบรรลุเป้าหมายที่ตั้งไว้หรือไม่

ข้อมูลโค้ดสั้นๆ เช่นนี้อาจพบในงานที่ทำงานเป็นระยะๆ เพื่อประเมินเป้าหมายประสิทธิภาพ หรือเมื่อโหลดรายการแบบฝึกหัดและแสดงการแจ้งเตือนเกี่ยวกับเป้าหมายประสิทธิภาพในแอป

// Ensure 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
                            }
                        }
                    }
                }
            }
        }
    }
}