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

如果您想建構可管理使用者生命徵象的應用程式,可以透過健康資料同步執行下列操作:

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

本指南將說明如何使用健康資料類型,涵蓋權限、讀取和寫入工作流程,以及最佳做法。

總覽:建立完整的健康指標追蹤器

如要使用「健康資料同步」建構完整的健康指標追蹤體驗,請按照下列核心步驟操作:

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

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

事前準備

實作生命徵象功能前,請先完成下列事項:

核心概念

「健康資料同步」中的健康資料會以各種記錄類型表示,每種記錄類型都對應特定的生理測量值。與運動訓練不同,健康指標通常會以時間點或間隔為基礎記錄資料。

健康資料類型

健康資料是以個別記錄類型表示。常見類型包括:

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

開發作業注意事項

健康資料可能屬於私密資訊,應用程式可能需要根據感應器測量結果或使用者輸入內容寫入資料,或是從後端同步處理資料。權限是處理生命徵象資料的關鍵。

權限

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

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

建立用戶端執行個體後,應用程式必須要求使用者授予權限。使用者必須能隨時授予或拒絕權限。

如要這麼做,請為所需資料類型建立一組權限。請務必先在 Android 資訊清單中聲明該組權限。

// Create a set of permissions for required data types
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 權限畫面。

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

由於使用者可以隨時授予或撤銷權限,應用程式每次使用權限前都必須先檢查,並處理權限遭撤銷的情況。

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

if (!granted.containsAll(PERMISSIONS)) {
    requestPermissions.launch(PERMISSIONS)
    // Check if required permissions are not granted, and return
  }
// 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))
}

批次寫入

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

下列程式碼顯示如何一次批次寫入多筆記錄:

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 呼叫,最多可包含 1000 筆記錄,而非個別寫入每個點。
    • 即時追蹤:如要頻繁更新感應器資料 (例如連續血糖監測器或心率監測器),請以最多 15 分鐘的間隔分批寫入資料,以平衡即時更新和電池效率。
    • 背景同步:使用 WorkManager 延後寫入,例如從隨附裝置或後端服務同步處理資料。批次寫入作業的時間間隔應為 15 分鐘。
  • 避免寫入重複資料:使用用戶端 ID 建立記錄時,請設定 metadata.clientRecordId。「健康資料同步」會使用這項資訊來識別不重複的記錄。如果您嘗試寫入已存在的 clientRecordId 記錄,系統會忽略重複的記錄或更新現有記錄,而不是建立新記錄。設定 metadata.clientRecordId 是最有效的方法,可避免在重試同步或重新安裝應用程式時發生重複問題。

    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,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "bp_20240101_user123"
        )
    )
  • 檢查現有資料:同步處理資料前,請查詢「健康資料同步」中同步時間範圍內的記錄,確認應用程式資料是否已存在,以免重複或覆寫較新的資料。

  • 清楚說明權限要求理由:使用 Permission.createIntent 流程說明應用程式為何需要存取健康資料,例如「監控血壓趨勢並提供深入分析」。

  • 時間戳記與測量結果一致:確認記錄時間戳記準確反映測量時間。如果是間隔資料 (例如 HeartRateRecord),請確認 startTimeendTime 正確無誤。

測試

如要驗證資料正確性並確保使用者享有優質體驗,請依循下列測試策略,並參閱官方的測試熱門用途說明文件。

驗證工具

品質檢查清單

一般架構

導入 Android Vitals 通常包括:

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

疑難排解

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

常見的偵錯步驟

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