透過「健康資料同步」開發健康資料體驗

本指南適用於健康資料同步 1.1.0 以上版本。

如果您想建構管理使用者生命徵象的應用程式,可以使用 Health Connect 執行下列操作:

  • 從其他應用程式讀取生命徵象資料,例如血壓、心率和體溫
  • 寫入應用程式或連結裝置記錄的生命徵象資料
  • 監控趨勢,並根據生命徵象資料提供健康洞察

本指南說明如何使用生命徵象資料類型,包括權限、讀取和寫入工作流程,以及最佳做法。

總覽:建構全方位的生命徵象追蹤工具

您可以按照下列核心步驟,使用健康資料同步打造全方位的生理指標追蹤體驗:

  • 要求生命徵象資料類型的適當權限。
  • 使用 BloodPressureRecord、HeartRateRecord 等記錄寫入生命徵象資料。
  • 讀取生命徵象資料,以便顯示、分析或同步。
  • 使用批次處理,有效率地寫入及讀取資料。

這個工作流程可與其他健康資料同步應用程式互通,並驗證使用者控管的資料存取權。

事前準備

導入生命徵象功能前:

核心概念

健康資料同步中的生理指標資料會以各種記錄類型表示,每種類型都對應到特定的生理測量值。與健身課程不同,生命徵象通常會記錄為時間點或間隔資料。

生命徵象資料類型

生命徵象資料會以個別記錄類型表示。常見的類型包括:

如需完整的資料類型清單,請參閱「健康資料同步資料類型」。

開發作業注意事項

生命徵象資料可能屬於機密資料,應用程式可能需要寫入資料,以回應感應器或使用者輸入內容的測量結果,或從後端同步資料。權限對於處理生命徵象資料至關重要。

權限

應用程式必須先要求相關的健康資料同步權限,才能讀取或寫入生命徵象資料。生命徵象的常見權限包括血壓、心率、體溫、血糖、血氧濃度和呼吸速率。此時你應該可以執行下列操作:

以下範例說明如何要求血壓、心率和體溫權限:

建立用戶端執行個體後,應用程式必須要求使用者授予權限。使用者必須能隨時授予或拒絕權限。 如要這麼做,請為所需資料類型建立一組權限。請務必先在 Android 資訊清單中聲明該組權限。

val permissions =
    setOf(
        HealthPermission.getReadPermission(BloodPressureRecord::class),
        HealthPermission.getWritePermission(BloodPressureRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        HealthPermission.getReadPermission(BodyTemperatureRecord::class),
        HealthPermission.getWritePermission(BodyTemperatureRecord::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.") }
    }
}
使用者隨時可以授予或撤銷權限,因此應用程式每次使用權限前都必須檢查權限,並處理權限遺失的情況。

如要要求權限,請呼叫 checkPermissionsAndRun 函式:

if (!granted.containsAll(permissions)) {
    // Check if required permissions are not granted, and return
    return emptySet()
}
// Permissions already granted; proceed with inserting or reading data

如果只需要要求單一資料類型的權限 (例如血壓),請在權限集中只加入該資料類型:

血壓資料的存取權受下列權限保護:

  • android.permission.health.READ_BLOOD_PRESSURE
  • android.permission.health.WRITE_BLOOD_PRESSURE

如要為應用程式新增血壓功能,請先要求 BloodPressureRecord 資料類型的權限。

您需要宣告以下權限,才能寫入血壓:

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

如要讀取血壓資料,您必須要求下列權限:

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

寫入生命徵象資料

本節說明如何將生理指標資料寫入健康資料同步。生命徵象資料通常會寫入個別記錄。如果您要一次寫入多筆記錄 (例如從感應器或後端同步),請使用批次處理。

編寫 BloodPressureRecord 的範例:

suspend fun writeBloodPressureRecord(healthConnectClient: HealthConnectClient) {
    val record = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    healthConnectClient.insertRecords(listOf(record))
}

批次寫入

如果應用程式需要寫入多個資料點,例如從連結裝置或後端服務同步資料,請批次寫入,以提高效率並減少電池消耗。健康資料同步 在單一寫入要求中最多可處理 1,000 筆記錄。

以下程式碼說明如何一次批次寫入多筆記錄:

suspend fun writeBatchRecords(healthConnectClient: HealthConnectClient) {
    val bloodPressureRecord = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    val heartRateRecord = HeartRateRecord(
        startTime = Instant.now().minusSeconds(60),
        startZoneOffset = ZoneOffset.UTC,
        endTime = Instant.now(),
        endZoneOffset = ZoneOffset.UTC,
        samples = listOf(HeartRateRecord.Sample(time = Instant.now().minusSeconds(30), beatsPerMinute = 80))
    )
    healthConnectClient.insertRecords(listOf(bloodPressureRecord, heartRateRecord))
}

讀取生命徵象資料

應用程式可以讀取生命徵象資料,顯示測量結果、分析趨勢,或與外部伺服器同步資料。如要讀取生理指標,請使用 ReadRecordsRequest 搭配特定記錄類型,並依日期範圍篩選。

讀取 BloodPressureRecord 資料的範例:

suspend fun readBloodPressureRecords(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response = healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = BloodPressureRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )

    for (record in response.records) {
        // Process each blood pressure record
        val systolic = record.systolic
        val diastolic = record.diastolic
    }
}

如需將生理指標資料與後端伺服器同步處理,或讓應用程式的資料儲存庫與健康資料同步保持最新狀態,請使用 ChangeLogs。這樣一來,您就能擷取特定時間點後插入、更新或刪除的記錄清單,比手動追蹤變更或重複讀取所有資料更有效率。詳情請參閱「使用『健康資料同步』同步資料」。

最佳做法

請遵循下列指南,提升資料可靠性和使用者體驗:

  • 批次寫入要求:為減少輸入/輸出負擔並延長電池續航力,請將資料點分組為單一 insertRecords 呼叫,每批最多 1,000 筆記錄,而非個別寫入每個資料點。
  • 在即時追蹤期間頻繁寫入:如要頻繁更新感應器 (例如連續血糖監測儀或心率監測器) 的資料,請以最多 15 分鐘的間隔批次寫入資料,在即時更新和電池效率之間取得平衡。
  • 使用 WorkManager 進行背景同步:使用 WorkManager 延遲寫入,例如從配對裝置或後端服務同步資料。建議每 15 分鐘進行一次批次寫入。
  • 避免寫入重複資料:使用用戶端 ID:建立記錄時,請設定 metadata.clientRecordId。健康資料同步會使用這個 ID 識別不重複的記錄。如果嘗試寫入具有現有 clientRecordId 的記錄,健康資料同步會忽略重複記錄或更新現有記錄,而不是建立新記錄。設定 metadata.clientRecordId 是最有效的方法,可避免在同步重試或重新安裝應用程式時重複。
    val record = StepsRecord(
        count = 100,
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.UTC,
        endZoneOffset = ZoneOffset.UTC,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "daily_steps_2023_10_27_user_123"
        )
    )
  • 檢查現有資料:同步資料前,請先查詢健康資料同步在同步日期範圍內的記錄,確認應用程式資料是否已存在,避免重複或覆寫較新的資料。
  • 清楚說明要求權限的原因:請使用 Permission.createIntent 流程,說明應用程式為何需要存取健康資料,例如:「監控血壓趨勢並提供洞察資訊」。
  • 確保時間戳記與測量時間一致:確認記錄時間戳記準確反映測量時間。如果是 HeartRateRecord 等間隔資料,請確認 startTime 和 endTime 正確無誤。

測試

為驗證資料正確性並提供優質的使用者體驗,請遵循下列測試策略,並參閱官方的「測試主要用途」說明文件。

驗證工具

  • 健康資料同步 Toolbox:使用這款隨附應用程式,手動檢查記錄、刪除測試資料,以及模擬資料庫變更。這是確認記錄是否正確儲存的最佳方式。
  • 使用 FakeHealthConnectClient 進行單元測試:使用測試程式庫,驗證應用程式如何處理邊緣案例,例如撤銷權限或 API 例外狀況,而不需要實體裝置。

品質檢查清單

典型架構

導入 Vitals 時,通常會包含以下項目:

元件 管理
Vitals 控制器 感應器/輸入讀取
批次處理邏輯
存放區層 (包裝 健康資料同步 作業): 插入生命徵象記錄
讀取生命徵象記錄
UI 層 (顯示): 即時讀數
歷來資料
圖表和趨勢

疑難排解

問題 可能原因 解析度
缺少資料類型 (例如血壓) 缺少寫入權限或時間篩選器不正確。 請確認您已要求特定資料類型的權限,且使用者已授予該權限。確認 ReadRecordsRequest 使用的 TimeRangeFilter 涵蓋評估時間。請參閱「權限」。
出現重複記錄 缺少 clientRecordId。 在每筆記錄的 Metadata 中指派專屬的 clientRecordId。這樣一來,如果同步重試期間重複寫入相同資料,健康資料同步就能執行去重複作業。請參閱「最佳做法」。
無法寫入記錄 單位不正確或值超出有效範圍。 健康資料同步會驗證記錄值。舉例來說,血壓值必須在生理上合理的範圍內。請參閱資料類型說明文件,瞭解有效範圍和單位。

常見的偵錯步驟

檢查權限狀態。 嘗試執行讀取或寫入作業前,請務必呼叫 getPermissionStatus()。使用者隨時可以在系統設定中撤銷權限。