อ่านข้อมูลดิบ

ตัวอย่างต่อไปนี้แสดงวิธีอ่านข้อมูลดิบซึ่งเป็นส่วนหนึ่งของเวิร์กโฟลว์ทั่วไป

อ่านข้อมูล

Health Connect อนุญาตให้แอปอ่านข้อมูลจาก Datastore เมื่อแอปอยู่ในเบื้องหน้าและเบื้องหลัง

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

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

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

หากต้องการอ่านบันทึก ให้สร้าง ReadRecordsRequest แล้วระบุ เมื่อเรียกใช้ readRecords

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

val response = healthConnectClient.readRecords(
    ReadRecordsRequest(
        HeartRateRecord::class,
        timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
    )
)
response.records.forEach { record ->
    /* Process records */
}

นอกจากนี้ คุณยังอ่านข้อมูลในลักษณะที่รวมได้โดยใช้ aggregate

suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long {
    val response = healthConnectClient.aggregate(
        AggregateRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
    return response[StepsRecord.COUNT_TOTAL] ?: 0L
}

อ่านจำนวนก้าวในอุปกรณ์เคลื่อนที่

Health Connect จะนับจำนวนก้าวในอุปกรณ์ด้วย Android 14 (ระดับ API 34) และ SDK Extension เวอร์ชัน 20 ขึ้นไป หากแอปใดได้รับสิทธิ์ READ_STEPS แล้ว Health Connect จะเริ่มบันทึกจำนวนก้าวจากอุปกรณ์ที่ใช้ Android และผู้ใช้จะเห็นข้อมูลจำนวนก้าวที่เพิ่มลงในรายการจำนวนก้าว ของ Health Connect โดยอัตโนมัติ

หากต้องการตรวจสอบว่าการนับจำนวนก้าวในอุปกรณ์พร้อมใช้งานหรือไม่ ให้ตรวจสอบว่าอุปกรณ์ใช้ Android 14 (ระดับ API 34) และมี SDK Extension เวอร์ชัน 20 ขึ้นไป

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

หากแอปอ่านจำนวนก้าวที่รวมโดยใช้ aggregate และไม่ได้กรองตาม DataOrigin ระบบจะรวมจำนวนก้าวในอุปกรณ์ ไว้ในยอดรวมโดยอัตโนมัติ และคุณไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ สำหรับ การอัปเดตในเดือนมิถุนายน 2026

การเปลี่ยนแปลงการระบุแหล่งที่มาสำหรับจำนวนก้าวในอุปกรณ์

ตั้งแต่การอัปเดตในเดือนมิถุนายน 2026 เป็นต้นไป ระบบจะระบุจำนวนก้าวที่ Health Connect ติดตามโดยกำเนิดเป็นชื่อแพ็กเกจสังเคราะห์ (SPN) เช่น com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e

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

SPN จะเฉพาะเจาะจงกับอุปกรณ์และกำหนดขอบเขตตามแอปพลิเคชันเพื่อปกป้องความเป็นส่วนตัวของผู้ใช้

  • เสถียร: SPN สำหรับอุปกรณ์ปัจจุบันจะเสถียรสำหรับแอปพลิเคชันของคุณ
  • กำหนดขอบเขตตามแอปพลิเคชัน: แอปพลิเคชันต่างๆ ในอุปกรณ์เดียวกันจะเห็น SPN ที่แตกต่างกันสำหรับข้อมูลจำนวนก้าวในอุปกรณ์

ค้นหาจำนวนก้าวในอุปกรณ์

เนื่องจาก SPN มีการกำหนดขอบเขตและเฉพาะเจาะจงกับอุปกรณ์ คุณจึงต้องไม่ ฮาร์ดโค้ดค่า SPN แต่ให้ใช้ getCurrentDeviceDataSource() API เพื่อดึงข้อมูล SPN สำหรับอุปกรณ์ปัจจุบัน

แม้ว่าการนับจำนวนก้าวในอุปกรณ์จะต้องใช้ SDK Extension เวอร์ชัน 20 ขึ้นไป แต่ getCurrentDeviceDataSource() API ก็พร้อมใช้งานใน Android 14 (ระดับ API 34) ที่มี SDK Extension เวอร์ชัน 11 ขึ้นไป

getCurrentDeviceDataSource() API ยังไม่พร้อมใช้งานในไลบรารี Health Connect Jetpack ตัวอย่างต่อไปนี้ใช้ Android Framework API แทน

import android.content.Context
import android.health.connect.HealthConnectManager

val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
val deviceDataSource = healthConnectManager?.getCurrentDeviceDataSource()
val currentDeviceSpn = deviceDataSource?.deviceDataOrigin?.packageName

หากแอปต้องอ่านจำนวนก้าวในอุปกรณ์ หรือหากแอปแสดงข้อมูลจำนวนก้าวที่แบ่งตามแอปพลิเคชันหรืออุปกรณ์ต้นทาง คุณต้องค้นหาบันทึกที่ DataOrigin เป็น android หรือ ตรงกับ SPN ของอุปกรณ์ หากแอปแสดงการระบุแหล่งที่มาสำหรับข้อมูลจำนวนก้าว ให้ใช้ metadata.device เพื่อระบุอุปกรณ์ต้นทางสำหรับบันทึกแต่ละรายการ สำหรับจำนวนก้าวในอุปกรณ์ที่ระบุโดย SPN ในข้อมูลที่รวม คุณสามารถใช้ข้อมูลเมตาของอุปกรณ์ เช่น model หรือ manufacturer จาก DeviceDataSource เพื่อการระบุแหล่งที่มา หรือใช้ป้ายกำกับทั่วไป เช่น "โทรศัพท์ของคุณ" สำหรับจำนวนก้าวในอุปกรณ์

ตัวอย่างต่อไปนี้แสดงวิธีอ่านข้อมูลจำนวนก้าวที่รวมในอุปกรณ์โดยกรองทั้ง android และ SPN ของอุปกรณ์ปัจจุบัน

import android.content.Context
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant

suspend fun readDeviceStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    context: Context,
    startTime: Instant,
    endTime: Instant
) {
    // 1. Check if SDK Extension 11+ is available for getCurrentDeviceDataSource()
    val isDataSourceApiAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.U &&
            SdkExtensions.getExtensionVersion(Build.VERSION_CODES.U) >= 11

    try {
        val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)

        // 2. Safely fetch the package name only if API is available and data exists
        val currentDeviceSpn = if (isDataSourceApiAvailable) {
            healthConnectManager?.getCurrentDeviceDataSource()?.deviceDataOrigin?.packageName
        } else {
            null
        }

        val dataOriginFilters = mutableSetOf(DataOrigin("android"))

        // 3. Explicit null-safety check using .let
        currentDeviceSpn?.let {
            dataOriginFilters.add(DataOrigin(it))
        }

        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = dataOriginFilters
            )
        )

        val stepCount = response[StepsRecord.COUNT_TOTAL]

    } catch (e: Exception) {
        // Now this catch block only handles actual runtime exceptions, 
        // rather than Errors from missing methods.
    }
}

การนับจำนวนก้าวในอุปกรณ์

  • การใช้เซ็นเซอร์: Health Connect ใช้เซ็นเซอร์ TYPE_STEP_COUNTER จาก SensorManager เซ็นเซอร์นี้ได้รับการเพิ่มประสิทธิภาพให้ใช้พลังงานต่ำ จึงเหมาะสำหรับการติดตามจำนวนก้าวในเบื้องหลังอย่างต่อเนื่อง
  • ความละเอียดของข้อมูล: ระบบจะจัดกลุ่มและเขียนข้อมูลจำนวนก้าวลงในฐานข้อมูล Health Connect ไม่เกิน 1 ครั้งต่อนาทีโดยปกติ เพื่อประหยัดแบตเตอรี่
  • การระบุแหล่งที่มา: ระบบจะระบุจำนวนก้าวที่บันทึกโดยฟีเจอร์นี้ก่อนเดือนมิถุนายน 2026 เป็น ชื่อแพ็กเกจ android ใน DataOrigin หลังจากวันที่นี้ ระบบจะระบุจำนวนก้าวเป็น SPN ที่เฉพาะเจาะจงกับอุปกรณ์ ดู การเปลี่ยนแปลงการระบุแหล่งที่มาสำหรับจำนวนก้าวในอุปกรณ์
  • การเปิดใช้งาน: กลไกการนับจำนวนก้าวในอุปกรณ์จะทำงานก็ต่อเมื่อแอปพลิเคชันอย่างน้อย 1 รายการในอุปกรณ์ได้รับสิทธิ์ READ_STEPS ภายใน Health Connect

ตัวอย่างการอ่านในเบื้องหลัง

หากต้องการอ่านข้อมูลในเบื้องหลัง ให้ประกาศสิทธิ์ต่อไปนี้ในไฟล์ Manifest

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

ตัวอย่างต่อไปนี้แสดงวิธีอ่านข้อมูลจำนวนก้าวในเบื้องหลังของผู้ใช้ภายในช่วงเวลาหนึ่งๆ โดยใช้ WorkManager

class ScheduleWorker(appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        val healthConnectClient = HealthConnectClient.getOrCreate(applicationContext)
        // Perform background read logic here
        return Result.success()
    }
}
@OptIn(ExperimentalFeatureAvailabilityApi::class)
fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) {
    if (healthConnectClient
            .features
            .getFeatureStatus(
                HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
            ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
    ) {

        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
}

พารามิเตอร์ ReadRecordsRequest มีค่า pageSize เริ่มต้นเป็น 1,000 หากจำนวนบันทึกใน readResponse รายการเดียวเกิน pageSize ของคำขอ คุณต้องวนซ้ำในทุกหน้าของคำตอบเพื่อดึงข้อมูลบันทึกทั้งหมดโดยใช้ pageToken อย่างไรก็ตาม โปรดระมัดระวังเพื่อหลีกเลี่ยงปัญหาการจำกัดอัตรา

ตัวอย่างการอ่าน pageToken

เราขอแนะนำให้ใช้ pageToken สำหรับการอ่านบันทึกเพื่อดึงข้อมูลทั้งหมดที่พร้อมใช้งานจากระยะเวลาที่ขอ

ตัวอย่างต่อไปนี้แสดงวิธีอ่านบันทึกทั้งหมดจนกว่าโทเค็นหน้าทั้งหมดจะหมด

val type = HeartRateRecord::class
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(7))

try {
    var pageToken: String? = null
    do {
        val readResponse =
            healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = type,
                    timeRangeFilter = TimeRangeFilter.between(
                        startTime,
                        endTime
                    ),
                    pageToken = pageToken
                )
            )
        val records = readResponse.records
        // Do something with records
        pageToken = readResponse.pageToken
    } while (pageToken != null)
} catch (quotaError: IllegalStateException) {
    // Backoff
}
ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติแนะนำเมื่ออ่านชุดข้อมูลขนาดใหญ่ได้ที่ วางแผนเพื่อหลีกเลี่ยงการจำกัดอัตราคำขอ

อ่านข้อมูลที่เขียนไว้ก่อนหน้านี้

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

โดยมีข้อจำกัดในการอ่านบางประการดังนี้

  • สำหรับ Android 14 ขึ้นไป

    • ไม่มีข้อจำกัดด้านข้อมูลย้อนหลังในการอ่านข้อมูลของตัวเอง
    • ข้อจำกัด 30 วันในการอ่านข้อมูลอื่นๆ
  • สำหรับ Android 13 และต่ำกว่า

    • ข้อจำกัด 30 วันในการอ่านข้อมูลใดๆ

คุณสามารถนำข้อจำกัดออกได้โดยขอสิทธิ์อ่าน

หากต้องการอ่านข้อมูลย้อนหลัง คุณต้องระบุชื่อแพ็กเกจเป็นออบเจ็กต์ DataOrigin ในพารามิเตอร์dataOriginFilter ของ ReadRecordsRequest

ตัวอย่างต่อไปนี้แสดงวิธีระบุชื่อแพ็กเกจเมื่ออ่านบันทึกอัตราการเต้นของหัวใจ

try {
    val response =  healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = HeartRateRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            dataOriginFilter = setOf(DataOrigin("com.my.package.name"))
        )
    )
    for (record in response.records) {
        // Process each record
    }
} catch (e: Exception) {
    // Run error handling here
}

อ่านข้อมูลที่มีอายุมากกว่า 30 วัน

โดยค่าเริ่มต้น แอปพลิเคชันทั้งหมดจะอ่านข้อมูลจาก Health Connect ได้นานสูงสุด 30 วันก่อนวันที่ได้รับสิทธิ์ครั้งแรก

หากต้องการขยายสิทธิ์อ่านให้เกินข้อจำกัด เริ่มต้น ให้ขอ PERMISSION_READ_HEALTH_DATA_HISTORY ไม่เช่นนั้น การพยายามอ่านบันทึกที่มีอายุมากกว่า 30 วันจะทำให้เกิดข้อผิดพลาด

ประวัติสิทธิ์ของแอปที่ถูกลบ

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

เช่น สมมติว่าผู้ใช้ลบแอปของคุณในวันที่ 10 พฤษภาคม 2023 จากนั้นติดตั้งแอปอีกครั้งในวันที่ 15 พฤษภาคม 2023 และให้สิทธิ์อ่าน วันที่เร็วที่สุดที่แอปของคุณจะอ่านข้อมูลได้โดยค่าเริ่มต้นคือ15 เมษายน 2023

จัดการข้อยกเว้น

Health Connect จะแสดงข้อยกเว้นมาตรฐานสำหรับการดำเนินการ CRUD เมื่อพบปัญหา แอปของคุณควรตรวจจับและจัดการข้อยกเว้นแต่ละรายการเหล่านี้ตามความเหมาะสม

แต่ละเมธอดใน HealthConnectClient จะแสดงข้อยกเว้นที่อาจเกิดขึ้น โดยทั่วไปแล้ว แอปของคุณควรจัดการข้อยกเว้นต่อไปนี้

ตารางที่ 1: ข้อยกเว้นของ Health Connect และแนวทางปฏิบัติแนะนำ
ข้อยกเว้น คำอธิบาย แนวทางปฏิบัติแนะนำ
IllegalStateException เกิดสถานการณ์ใดสถานการณ์หนึ่งต่อไปนี้

  • บริการ Health Connect ไม่พร้อมใช้งาน
  • คำขอไม่ใช่โครงสร้างที่ถูกต้อง เช่น คำขอรวมในบัคเก็ตเป็นระยะซึ่งใช้ออบเจ็กต์ Instant สำหรับ timeRangeFilter

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

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

RemoteException เกิดข้อผิดพลาดภายในหรือในการสื่อสารกับบริการพื้นฐานที่ SDK เชื่อมต่ออยู่

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

  • ทำการซิงค์เป็นประจำระหว่าง Datastore ของแอปกับ Health Connect
  • ใช้กลยุทธ์การลองใหม่และการรอแบบทวีคูณเพื่อจัดการปัญหาคำขอ

SecurityException เกิดปัญหาเมื่อคำขอต้องใช้สิทธิ์ที่ไม่ได้ให้ไว้ วิธีหลีกเลี่ยงปัญหานี้คือตรวจสอบว่าคุณได้ ประกาศการใช้ประเภทข้อมูล Health Connect สำหรับแอปที่เผยแพร่แล้ว นอกจากนี้ คุณต้องประกาศสิทธิ์ Health Connect ในไฟล์ Manifest และ ในกิจกรรมของคุณ