Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Health Connect를 FHIR로
Flutter로 Fitbit, Garmin, Oura, Withings 및 Wear OS의 Android Health Connect 데이터를 읽고 FHIR R4 레코드에 쓰기: 권한, 기록, Play 스토어 검토.
Health Connect는 Android의 온디바이스 건강 저장소입니다. Samsung Health, Fitbit, Garmin Connect, Oura, Withings 및 Wear OS 앱이 여기에 데이터를 쓰고, 사용자의 권한으로 앱이 데이터를 읽습니다. 이 데이터를 FHIR 레코드로 저장하려면, 휴대폰에서 일일 총계 및 평균을 읽어 백엔드로 전송하고, 각 측정값을 LOINC 코드 및 UCUM 단위가 있는 Observation으로 작성합니다. 이 페이지에서는 Android에서 요구하는 권한, 동일한 코드로 Android의 Health Connect와 iOS의 Apple Health를 읽는 Flutter 예제(flutter analyze로 확인됨), 그리고 Google Play 게시 규칙에 대해 다룹니다.
Health Connect에 도달하는 항목
Health Connect는 Android 14 이상에 내장되어 있으며 이전 버전에서는 앱으로 사용할 수 있습니다. HeartRateRecord, RestingHeartRateRecord, HeartRateVariabilityRmssdRecord, OxygenSaturationRecord, RespiratoryRateRecord, StepsRecord, DistanceRecord, ActiveCaloriesBurnedRecord, SleepSessionRecord, WeightRecord, BloodPressureRecord, BloodGlucoseRecord, BodyTemperatureRecord 및 ExerciseSessionRecord과 같은 기록을 보유합니다.
각 공급업체 문서에 따르면 누가 거기에 기록하는가:
| 출처 | 예상되는 내용 |
|---|---|
| Fitbit 및 Pixel Watch | 사용자가 설정하면 Fitbit 앱이 Health Connect와 동기화됩니다 (Google 도움말) |
| Garmin | Garmin Connect는 Android 14 이상에서 Health Connect를 지원합니다: 심박수 및 칼로리와 같은 활동 및 웰빙 데이터 (Android Developers, 2025년 8월) |
| Oura | 심박수, HRV, 수면 단계, 걸음 수, 거리, 칼로리 및 운동 (Oura) |
| Withings | Health Mate는 Health Connect를 통해 활동, 체중, 수면 및 기타 데이터를 교환합니다 (Android Developers 블로그) |
| Samsung Health, Galaxy Watch | Samsung Health 자체 속도에 따른 일부 데이터 — Samsung Health to FHIR 참조 |
각 공급업체 앱은 Health Connect에 쓰기 권한이 있어야 하며, 이는 사용자가 해당 앱 또는 Health Connect 설정에서 부여합니다. 출처가 누락된 경우 가장 먼저 확인해야 할 사항입니다.
권한 Android 요구 사항
- 레코드 유형 및 방향별로 하나의 권한이 필요합니다. 예를 들어, 매니페스트에 선언되고 런타임에 요청되는
android.permission.health.READ_HEART_RATE및android.permission.health.READ_STEPS입니다. - 기록:
android.permission.health.READ_HEALTH_DATA_HISTORY없이 앱은 권한이 부여되기 전 마지막 30일만 읽을 수 있습니다. - 백그라운드: 앱이 포그라운드에 있지 않을 때 읽으려면
android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND이 필요합니다. - 개인정보처리방침을 설명하는 권한 근거 화면(
ACTION_SHOW_PERMISSIONS_RATIONALE을 처리하는 액티비티, Android 14의 액티비티 별칭 포함). 이 화면이 없으면 권한 대화상자가 열리지 않습니다. - Flutter에서는
MainActivity가FlutterActivity가 아닌FlutterFragmentActivity을 확장해야 합니다. 그렇지 않으면 권한 요청이 실패합니다.
Flutter에서 일일 값 읽기
health 패키지는 Android의 Health Connect와 iOS의 Apple Health를 단일 API 뒤에서 읽습니다. 예제는 Anpheros Daily가 함께 제공하는 버전 13.2.1을 사용합니다.
import 'dart:math' as math;
import 'package:health/health.dart';
/// One day of data from Health Connect (Android) or Apple Health (iOS), ready for your backend.
class DailyValue {
DailyValue(this.metric, this.day, this.value, {this.min, this.max});
final String metric; // 'heart_rate', 'steps'
final String day; // '2026-10-01', the user's local day
final double value;
final double? min, max;
Map<String, Object?> toJson() => {'metric': metric, 'day': day, 'value': value, 'min': min, 'max': max};
}
final health = Health();
Future<List<DailyValue>> collectLastDays({int days = 30}) async {
await health.configure();
if (!await health.isHealthConnectAvailable()) {
await health.installHealthConnect(); // opens the Play Store on Android; always available on iOS
return [];
}
const types = [HealthDataType.HEART_RATE, HealthDataType.STEPS];
final granted = await health.requestAuthorization(types, permissions: [HealthDataAccess.READ, HealthDataAccess.READ]);
if (!granted) return [];
final now = DateTime.now();
final out = <DailyValue>[];
for (var i = days - 1; i >= 0; i--) {
final start = DateTime(now.year, now.month, now.day - i); // local midnight, safe across DST changes
final end = DateTime(start.year, start.month, start.day + 1);
final day = start.toIso8601String().substring(0, 10);
final steps = await health.getTotalStepsInInterval(start, end);
if (steps != null) out.add(DailyValue('steps', day, steps.toDouble()));
final samples = await health.getHealthDataFromTypes(types: [HealthDataType.HEART_RATE], startTime: start, endTime: end);
final bpm = [for (final p in samples) if (p.value is NumericHealthValue) (p.value as NumericHealthValue).numericValue.toDouble()];
if (bpm.isNotEmpty) {
out.add(DailyValue('heart_rate', day, bpm.reduce((a, b) => a + b) / bpm.length,
min: bpm.reduce(math.min), max: bpm.reduce(math.max)));
}
}
return out; // POST these to your backend, which writes them to the FHIR record
}
getTotalStepsInInterval은 Health Connect에 집계된 총계를 요청합니다. 이는 이미 중복되는 소스(전화기와 시계가 같은 걸음 수를 세는 경우)를 사용자가 Health Connect에서 설정한 데이터 소스 우선순위에 따라 해결합니다. 원시 걸음 수 기록을 직접 합산하면 이중 계산됩니다.
Anpheros Daily에서 이를 출시한 후의 참고 사항:
- 앱이 포그라운드로 전환될 때 동기화하며, 반복 동기화를 방지하는 짧은 가드가 있습니다. 다른 앱은 자체 일정에 따라 Health Connect에 쓰므로, 사용자가 공급업체 앱에서 보는 데이터는 몇 분 또는 몇 시간 후에 도착할 수 있습니다.
- 심박수는 단일 값이 아닌 시리즈입니다. 각 샘플에 대해 하나의 값이 아니라, 모든 판독값을 업로드하는 대신 휴대폰에서 요약합니다(일별 또는 차트의 경우 4시간 단위).
- 여기서 HRV는 RMSSD입니다. Apple Health에 사용되는 SDNN 코드 아래에 저장하지 마십시오.
Flutter 값에서 FHIR Observation으로
값을 백엔드로 전송하고, 사람, 측정 항목, 날짜별로 하나의 Observation을 안정적인 식별자와 함께 작성하며, 동일한 날짜가 다시 전송될 때 이를 업데이트합니다. 전체 매핑 테이블(Health Connect 레코드 → LOINC → UCUM), 검증된 FHIR 예시, 그리고 플랫폼에 대한 TypeScript upsert 실행은 FHIR의 웨어러블 데이터에서 확인할 수 있습니다.
Google Play에 게시하기
Health Connect를 읽는 앱은 Play Console에서 Health Connect 권한 선언을 완료하고, 모든 데이터 유형에 대한 근거를 제시하며, 이에 부합하는 개인정보처리방침을 갖추어야 합니다. 앱에서 명시적으로 사용하지 않는 데이터 유형에 대한 요청은 거부됩니다. 검토를 위해 각 유형을 사용하는 화면 옆에 나열하여 계획하십시오.
Wear OS
Wear OS 시계에서 앱은 Health Services를 통해 실시간 센서 데이터(예: 운동 중 심박수)를 읽을 수 있습니다. 시계 자체 건강 앱이 기록한 데이터는 공급업체의 휴대폰 앱을 통해 휴대폰의 Health Connect로 전달됩니다. 의료 기록의 경우, 휴대폰에서 Health Connect를 읽는 것으로 충분하며, 시계 앱은 실시간 기능에 사용됩니다.
Anpheros의 역할
Anpheros 플랫폼은 개인의 FHIR R4 레코드를 저장합니다. 각 웨어러블 값은 Observation으로 표시되며, 동의, 출처, 접근 로그 뒤에 저장됩니다. Anpheros는 Health Connect를 직접 읽지 않으며, Android 앱이 이를 수행합니다. Anpheros 자체 앱인 Anpheros Daily는 Android에서 Health Connect를 읽고(Plus 및 Max 플랜) 일일 요약을 레코드에 기록합니다.
자주 묻는 질문
Health Connect에 클라우드 API가 있나요?
아니요. Health Connect는 휴대폰에 데이터를 저장하며, 사용자의 허가를 받은 해당 휴대폰의 앱만 데이터를 읽을 수 있습니다. 데이터를 서버로 가져오려면 앱에서 데이터를 읽어 전송해야 합니다.
Health Connect REST API 또는 웹 API가 있나요?
아니요. Health Connect는 REST 또는 웹 엔드포인트가 없는 온디바이스 Android API입니다. 서버는 휴대폰의 앱이 데이터를 읽어 전송할 때만 데이터를 수신합니다. 예를 들어, FHIR Observations를 Anpheros로 전송하는 경우입니다.
Python 또는 React Native에서 Health Connect API를 사용할 수 있나요?
Python에서는 사용할 수 없습니다. Python은 서버가 아닌 휴대폰에서 실행되기 때문입니다. React Native 또는 Flutter에서는 가능합니다. 앱 내에서 Android API를 호출하는 커뮤니티 또는 공식 플러그인을 통해 사용할 수 있습니다.
제 앱이 Health Connect 데이터를 30일만 읽을 수 있는 이유는 무엇인가요?
READ_HEALTH_DATA_HISTORY 권한이 없으면 Health Connect는 최초 권한 부여 이전 30일로 읽기를 제한합니다. 더 오래된 데이터가 필요한 경우 기록 권한을 요청하세요.
Garmin은 Health Connect와 동기화되나요?
예. Google은 2025년 8월에 Garmin Connect가 Android 14 이상에서 심박수 및 칼로리와 같은 활동 및 웰니스 데이터에 대해 Health Connect를 지원한다고 발표했습니다. Body Battery와 같은 Garmin 자체 점수는 공유되지 않습니다.
Fitbit Web API 없이 Fitbit 데이터를 읽을 수 있나요?
Android에서는 가능합니다. 사용자가 Fitbit 앱에서 Health Connect를 활성화하면, Fitbit 데이터는 사용자가 승인한 앱에서 Health Connect를 통해 사용할 수 있습니다.
Health Connect 걸음 수가 제 공급업체 앱과 다른 이유는 무엇인가요?
공급업체 앱이 최신 데이터를 아직 내보내지 않았거나, 일부 유형만 내보내거나, Health Connect가 동일 기간에 대해 다른 소스를 선호할 수 있습니다. Health Connect 설정에서 데이터 소스와 우선순위를 확인하세요.
관련 자료
- Fitbit Web API 종료 (2026년 10월)
- FHIR 형식의 웨어러블 데이터: 매핑 테이블 및 백엔드 코드
- Samsung Health를 FHIR로 변환
- Apple Health (HealthKit)를 FHIR로 변환
- Flutter로 헬스케어 앱 구축하기
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card