本指南將介紹在 Health Connect 中寫入或更新資料的程序。
設定資料結構
在寫入資料之前,我們需要先設定記錄。資料類型有超過 50 種,每種都有各自的結構。如要進一步瞭解可用的資料類型,請參閱 Jetpack 參考資料。
基本記錄
Health Connect 中的「步數」資料類型會擷取使用者在兩次讀取作業間的步數。步數是各大健康與健身平台上的常見測量指標。
以下範例說明如何設定步數資料:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))
val stepsRecord = StepsRecord(
count = 120,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
)
)
含有測量單位的記錄
Health Connect 可以儲存值及其測量單位,因此能提供準確資料。舉例來說,「營養」資料類型相當龐大且全面,包含各種選用的營養素欄位,從碳水化合物總量到維生素應有盡有。每個資料點都代表可能作為膳食或食品的一部分攝入的營養素。
在這個資料類型中,所有營養素均以 Mass
為單位,而 energy
則以 Energy
為單位。
以下範例說明如何針對吃了香蕉的使用者設定營養資料:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(1))
val banana = NutritionRecord(
name = "banana",
energy = 105.0.kilocalories,
dietaryFiber = 3.1.grams,
potassium = 0.422.grams,
totalCarbohydrate = 27.0.grams,
totalFat = 0.4.grams,
saturatedFat = 0.1.grams,
sodium = 0.001.grams,
sugar = 14.0.grams,
vitaminB6 = 0.0005.grams,
vitaminC = 0.0103.grams,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.manualEntry(
device = Device(type = Device.TYPE_PHONE)
)
)
含有系列資料的記錄
Health Connect 可儲存一系列資料的清單。舉例來說,「心率」資料類型會擷取系統在讀取作業間偵測到的一系列心跳資料樣本。
在這個資料類型中,samples
參數會以心率樣本清單表示。每個樣本都包含 beatsPerMinute
值和 time
值。
以下範例說明如何設定心率系列資料:
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))
val heartRateRecord = HeartRateRecord(
startTime = startTime,
startZoneOffset = ZoneOffset.UTC,
endTime = endTime,
endZoneOffset = ZoneOffset.UTC,
// records 10 arbitrary data, to replace with actual data
samples = List(10) { index ->
HeartRateRecord.Sample(
time = startTime + Duration.ofSeconds(index.toLong()),
beatsPerMinute = 100 + index.toLong(),
)
},
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
))
寫入資料
Health Connect 中常見的一項工作流程就是寫入資料。如要新增記錄,請使用 insertRecords
。
以下範例說明如何透過插入步數來寫入資料:
suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))
try {
val stepsRecord = StepsRecord(
count = 120,
startTime = startTime,
endTime = endTime,
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.autoRecorded(
device = Device(type = Device.TYPE_WATCH)
)
)
healthConnectClient.insertRecords(listOf(stepsRecord))
} catch (e: Exception) {
// Run error handling here
}
}
更新資料
如果您需要變更一或多筆記錄,特別是在需要將應用程式資料儲存庫與 Health Connect 的資料同步時,您就可以更新資料。更新現有資料的方法有兩種,至於要採取哪一種,則視用於尋找記錄的 ID 而定。
中繼資料
建議您先檢查 Metadata
類別,因為這是更新資料前的必要操作。Health Connect 中的每個 Record
在建立時都包含 metadata
欄位。下列屬性與同步處理相關:
屬性 | 說明 |
---|---|
id
|
Health Connect 中的每筆 Record 都有專屬的 id 值。在插入新記錄時 ,Health Connect 會自動填入這項資料。 |
lastModifiedTime
|
每筆 Record 也會追蹤上次修改記錄的時間。Health Connect 會自動填入這項資料。 |
clientRecordId
|
每筆 Record 都具有與之關聯的專屬 ID,可做為應用程式資料儲存庫中的參考資料。您的應用程式會提供這個值。 |
clientRecordVersion
|
如果記錄包含 clientRecordId ,就能使用 clientRecordVersion 讓資料與應用程式資料儲存庫中的版本保持同步。您的應用程式會提供這個值。 |
透過記錄 ID 更新
如要更新資料,請先備妥所需的記錄,接著對記錄進行任何必要更動,然後呼叫 updateRecords
即可變更。
以下範例說明如何更新資料。為此,每筆記錄的時區偏移值均已調整成 PST。
suspend fun updateSteps(
healthConnectClient: HealthConnectClient,
prevRecordStartTime: Instant,
prevRecordEndTime: Instant
) {
try {
val request = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(
prevRecordStartTime, prevRecordEndTime
)
)
)
val newStepsRecords = arrayListOf<StepsRecord>()
for (record in request.records) {
// Adjusted both offset values to reflect changes
val sr = StepsRecord(
count = record.count,
startTime = record.startTime,
startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
endTime = record.endTime,
endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
metadata = record.metadata
)
newStepsRecords.add(sr)
}
healthConnectClient.updateRecords(newStepsRecords)
} catch (e: Exception) {
// Run error handling here
}
}
透過用戶端記錄 ID 更新/插入
如果您使用選用的用戶端記錄 ID 和用戶端記錄版本值,我們會建議您使用 insertRecords
,而非 updateRecords
。
insertRecords
函式可更新/插入資料。如果 Health Connect 中的資料以指定的一組用戶端記錄 ID 為依據,系統會覆寫這類資料。但如果不是的話,則會以新資料的形式寫入。當您需要將應用程式資料儲存庫中的資料同步到 Health Connect 時,這就非常實用。
以下範例說明如何對從應用程式資料儲存庫提取的資料執行更新/插入作業:
suspend fun pullStepsFromDatastore() : ArrayList<StepsRecord> {
val appStepsRecords = arrayListOf<StepsRecord>()
// Pull data from app datastore
// ...
// Make changes to data if necessary
// ...
// Store data in appStepsRecords
// ...
var sr = StepsRecord(
metadata = Metadata.autoRecorded(
clientRecordId = "Your client record ID",
device = Device(type = Device.TYPE_WATCH)
),
// Assign more parameters for this record
)
appStepsRecords.add(sr)
// ...
return appStepsRecords
}
suspend fun upsertSteps(
healthConnectClient: HealthConnectClient,
newStepsRecords: ArrayList<StepsRecord>
) {
try {
healthConnectClient.insertRecords(newStepsRecords)
} catch (e: Exception) {
// Run error handling here
}
}
之後,您可以在主執行緒中呼叫這些函式。
upsertSteps(healthConnectClient, pullStepsFromDatastore())
檢查用戶端記錄版本中的值
如果您在更新/插入資料的程序中也會處理到用戶端記錄版本,Health Connect 會對 clientRecordVersion
值執行比較檢查。假如插入資料的版本高於現有資料版本,系統就會執行更新/插入作業。但如果不是的話,該程序會忽略變更,而值也會保持不變。
如要在資料中加入版本編號,您需要依據版本編號邏輯為 Metadata.clientRecordVersion
提供 Long
值。
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))
val stepsRecord = StepsRecord(
count = 100L,
startTime = startTime,
startZoneOffset = ZoneOffset.UTC,
endTime = endTime,
endZoneOffset = ZoneOffset.UTC,
metadata = Metadata.manualEntry(
clientRecordId = "Your supplied record ID",
clientRecordVersion = 0L, // Your supplied record version
device = Device(type = Device.TYPE_WATCH)
)
)
為防止意外覆寫資料的情況,每當變更發生時,更新/插入作業不會自動依累加原則設定 version
。因此,您必須手動為該項目輸入較高的值。
寫入資料的最佳做法
應用程式只能將「擁有來源」的資料寫入 Health Connect。
如果應用程式資料是從另一個應用程式匯入,則應由該應用程式負責將其擁有的資料寫入 Health Connect。
此外,建議您針對資料寫入例外狀況導入處理邏輯,例如資料在邊界外或發生內部系統錯誤時。您可以對工作排程機制套用輪詢和重試策略。如果最終無法順利寫入 Health Connect,請確保應用程式能夠移出該匯出點。請務必記錄並回報錯誤,以利診斷作業。
追蹤資料時,您可以根據應用程式寫入資料的方式採用以下幾項建議。
被動追蹤
這包括提供被動健身或健康追蹤功能的應用程式,例如在背景持續記錄步數或心率。
應用程式需採用以下做法,定期將資料寫入 Health Connect:
- 每次同步時,請僅寫入新資料及上次同步後修改的更新資料。
- 在每個寫入要求中,區塊要求最多為 1000 條記錄。
- 使用
WorkManager
安排週期性背景工作,時間長度至少為 15 分鐘。 請限制只在裝置處於閒置狀態且電量充足時執行工作。
val constraints = Constraints.Builder() .requiresBatteryNotLow() .requiresDeviceIdle(true) .build() val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>( 15, TimeUnit.MINUTES, 5, TimeUnit.MINUTES ) .setConstraints(constraints) .build()
主動追蹤
這類應用程式功能包括執行以運動和睡眠等事件為基礎的追蹤功能,或讓使用者手動輸入營養攝取等資訊。如果應用程式是在前景運作,或事件發生頻率相當低 (如一天幾次),就會建立這類記錄。
請確保在整個事件期間,應用程式不會要求 Health Connect 保持在執行狀態。
資料必須透過以下其中一種方式寫入 Health Connect:
- 在事件完成後,將資料同步處理至 Health Connect。例如在使用者結束追蹤的運動時段後同步處理資料。
- 使用
WorkManager
排定一次性工作,稍後再同步處理資料。
寫入精細程度和頻率的最佳做法
將資料寫入 Health Connect 時,請使用適當的解析度。使用適當的解析度有助於減少儲存空間負載,同時維持一致且準確的資料。資料解決方案包含 2 個部分:
- 寫入頻率:應用程式將任何新資料推送至 Health Connect 的頻率。例如,每隔 15 分鐘寫入新資料。
- 寫入資料的精細程度:推送的資料被取樣的頻率。例如,每隔 5 秒寫入心率樣本。並非所有資料類型都需要相同的取樣率。如要更新步數資料,每秒取樣一次的效果不會優於採用較低的取樣頻率,例如每 60 秒一次。不過,取樣率較高可讓使用者更詳細瞭解自己的健康與健身資料。您應在精細程度和效能之間取得平衡,採用適當的取樣頻率。
寫入全天監控的資料
如果是持續收集的資料 (例如步數),應用程式應至少每天每 15 分鐘寫入一次 Health Connect。
資料類型 |
單位 |
預期 |
示例 |
步數 |
步數 |
每分鐘 |
23:14 - 23:15 - 5 個步驟 23:16 - 23:17 - 22 步 23:17 - 23:18 - 8 個步驟 |
StepsCadence |
步/分鐘 |
每分鐘 |
23:14 - 23:15 - 5 spm 23:16 - 23:17 - 22 spm 23:17 - 23:18 - 8 spm |
推動輪椅次數 |
推送 |
每分鐘 |
23:14 - 23:15 - 5 次推送 23:16 - 23:17 - 22 次推送 23:17 - 23:18 - 8 次推送 |
ActiveCaloriesBurned |
卡路里 |
每 15 分鐘檢查一次 |
23:15 - 23:30 - 2 卡路里 23:30 - 23:45 - 25 卡路里 23:45 - 00:00 - 5 卡路里 |
TotalCaloriesBurned |
卡路里 |
每 15 分鐘檢查一次 |
23:15 - 23:30 - 16 卡路里 23:30 - 23:45 - 16 卡路里 23:45 - 00:00 - 16 卡路里 |
距離 |
公里/分鐘 |
每分鐘 |
23:14-23:15 - 0.008 公里 23:16 - 23:16 - 0.021 公里 23:17 - 23:18 - 0.012 公里 |
ElevationGained |
分鐘 |
每分鐘 |
20:36 - 20:37 - 3.048m 20:39 - 20:40 - 3.048m 23:23 - 23:24 - 9.144m |
FloorsClimbed |
層樓 |
每分鐘 |
23:14 - 23:15 - 5 層樓 23:16 - 23:16 - 22 層樓 23:17 - 23:18 - 8 層樓 |
HeartRate |
bpm |
每分鐘 |
上午 6 點 11 分 - 55 bpm |
HeartRateVariabilityRmssd |
ms |
每分鐘 |
上午 6 點 11 分 - 23 毫秒 |
RespiratoryRate |
呼吸次數/分鐘 |
每分鐘 |
23:14 - 23:15 - 60 次/分鐘 23:16 - 23:16 - 62 次/分鐘 23:17 - 23:18 - 64 次/分鐘 |
OxygenSaturation |
% |
每小時 |
6:11 - 95.208% |
寫入時段
資料應在健身或睡眠時段結束時寫入 Health Connect。
最佳做法是,任何睡眠或運動時段都應使用錄製裝置和適當的中繼資料 (包括 RecordingMethod
) 來寫入。
您的應用程式至少應遵循下方「預期」欄中的指引。盡可能遵循「最佳」指南。
運動期間追蹤的資料
資料類型 |
單位 |
預期 |
祝一切順心! |
示例 |
步數 |
步數 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 5 個步驟 23:16 - 23:17 - 22 步 23:17 - 23:18 - 8 個步驟 |
StepsCadence |
步/分鐘 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 35 spm 23:16 - 23:17 - 37 spm 23:17 - 23:18 - 40 spm |
推動輪椅次數 |
推送 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 5 次推送 23:16 - 23:17 - 22 次推送 23:17 - 23:18 - 8 次推送 |
CyclingPedalingCadence |
rpm:每分鐘呼吸次數 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 65 rpm 23:16 - 23:17 - 70 rpm 23:17 - 23:18 - 68 rpm |
電源 |
瓦特 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 250 瓦 23:16 - 23:17 - 255 瓦 23:17 - 23:18 - 245 瓦 |
速度 |
公里/分鐘 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 0.3 公里/分鐘 23:16 - 23:17 - 0.4 公里/分鐘 23:17 - 23:18 -0.4 公里/分鐘 |
距離 |
公里/公尺 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 0.008 公里 23:16 - 23:16 - 0.021 公里 23:17 - 23:18 - 0.012 公里 |
ActiveCaloriesBurned |
卡路里 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 20 卡路里 23:16 - 23:17 - 20 卡路里 23:17 - 23:18 - 25 卡路里 |
TotalCaloriesBurned |
卡路里 |
每分鐘 |
每 1 秒 |
23:14-23:15 - 36 卡路里 23:16 - 23:17 - 36 卡路里 23:17 - 23:18 - 41 卡路里 |
ElevationGained |
分鐘 |
每分鐘 |
每 1 秒 |
20:36 - 20:37 - 3.048m 20:39 - 20:40 - 3.048m 23:23 - 23:24 - 9.144m |
ExerciseRoutes |
lat/lng/alt |
每 3 到 5 秒 |
每 1 秒 |
|
HeartRate |
bpm |
每分鐘 |
每 1 秒 |
23:14-23:15 - 150 bpm 23:16 - 23:17 -152 bpm 23:17 - 23:18 - 155 bpm |
睡眠期間追蹤的資料
資料類型 |
單位 |
預期的樣本 |
示例 |
睡眠分期 |
階段 |
各睡眠階段的精細時間長度 |
23:46 - 23:50 - 清醒 23:50 - 23:56 - 淺層睡眠 23:56 - 00:16 - 熟睡 |
RestingHeartRate |
bpm |
單一每日值 (預計在早上第一時間) |
上午 6 點 11 分 - 60 bpm |
OxygenSaturation |
% |
單一每日值 (預計在早上第一時間) |
6:11 - 95.208% |