의료 데이터 쓰기

이 가이드는 Health Connect 버전 1.1.0-beta02와 호환됩니다.

헬스 커넥트의 의료 기록을 사용하여 의료 데이터를 작성하려면 다음 단계를 따르세요.

  1. 기능 사용 가능 여부 확인
  2. 쓰기 권한 요청
  3. 데이터 소스 만들기 (MedicalDataSource)
  4. 의료 리소스 작성 (MedicalResource)

기능 사용 가능 여부

사용자 기기가 헬스 커넥트의 의료 기록을 지원하는지 확인하려면 클라이언트에서 FEATURE_PERSONAL_HEALTH_RECORD의 사용 가능 여부를 확인하세요.

if (healthConnectClient
     .features
     .getFeatureStatus(
       HealthConnectFeatures.FEATURE_PERSONAL_HEALTH_RECORD
     ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {

  // Feature is available
} else {
  // Feature isn't available
}

자세한 내용은 기능 사용 가능 여부 확인하기를 참고하세요.

필수 권한

의료 데이터 쓰기는 다음 권한으로 보호됩니다.

  • android.permission.health.WRITE_MEDICAL_DATA

앱의 Play Console과 앱의 매니페스트에서 다음 권한을 선언합니다.

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

기기와 앱에서 사용하려는 모든 적절한 권한을 선언해야 합니다. 또한 사용하기 전에 각 권한이 사용자에게 부여되었는지 확인해야 합니다.

사용자에게 권한 요청

클라이언트 인스턴스를 만든 후 앱은 사용자에게 권한을 요청해야 합니다. 사용자는 언제든지 권한을 부여하거나 거부할 수 있어야 합니다.

이렇게 하려면 필요한 데이터 유형의 권한 집합을 만드세요. 집합에 있는 권한이 먼저 Android 매니페스트에 선언되어 있는지 확인합니다.

// Create a set of permissions for required data types
import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_WRITE_MEDICAL_DATA

val PERMISSIONS =
    setOf(
       PERMISSION_WRITE_MEDICAL_DATA
)

getGrantedPermissions를 사용하여 앱에 이미 필요한 권한이 부여되었는지 확인합니다. 그렇지 않은 경우 createRequestPermissionResultContract를 사용하여 이러한 권한을 요청합니다. 헬스 커넥트 권한 화면이 표시됩니다.

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

사용자는 언제든지 권한을 부여하거나 취소할 수 있으므로 앱은 부여된 권한을 주기적으로 확인하고 권한이 손실된 시나리오를 처리해야 합니다.

데이터 소스

헬스 커넥트의 MedicalDataSource은 의료 기관, 병원, API와 같은 사용자 대상 데이터 소스를 나타냅니다.

헬스 커넥트에 저장된 의료 기록은 MedicalDataSource로 정리됩니다. 이를 통해 API나 의료 시스템과 같은 다양한 소스에서 가져온 동일한 개인의 의료 기록을 분리할 수 있습니다.

모든 레코드가 동일한 소스에서 비롯되는 경우 쓰기 앱은 MedicalDataSource 하나만 만들면 됩니다. 레코드가 여러 소스에서 비롯된 경우에도 데이터가 조정되고 모든 레코드에 FHIR 리소스 유형과 FHIR 리소스 ID의 고유한 조합이 있으면 앱에서 단일 MedicalDataSource를 만들 수 있습니다. 그렇지 않으면 각 데이터 소스에 대해 MedicalDataSource를 만들어야 합니다.

모든 의료 기록은 MedicalDataSource와 연결되어야 하므로 리소스를 작성하기 전에 이를 만들어야 합니다.

MedicalDataSource의 속성:

  • 표시 이름 (필수) - 쓰기 앱별로 고유하게 식별되는 데이터 소스의 사용자 표시 이름입니다.
  • FHIR 기본 URI (필수) - FHIR 서버에서 가져온 데이터의 경우 FHIR 기본 URL (예: https://example.com/fhir/)이어야 합니다. 여러 데이터 소스를 동일한 FHIR 기본 URL과 연결할 수 있습니다.

    데이터가 FHIR URL이 없는 앱에 의해 생성된 경우 이는 데이터 소스를 가리키는 앱에서 정의한 고유하고 이해 가능한 URI(예: myapp://..)여야 합니다.

    예를 들어 클라이언트 앱이 딥 링크를 지원하는 경우 이 딥 링크를 FHIR 기본 URI로 사용할 수 있습니다. URI의 최대 길이는 2,000자입니다.

  • 패키지 이름 (자동으로 채워짐) - 데이터를 쓰는 앱입니다.

  • FHIR 버전 (필수) - FHIR 버전입니다. 지원되는 버전이어야 합니다.

MedicalDataSource 레코드 만들기

앱이 연결된 각 의료 기관 또는 법인의 레코드를 만듭니다.

// Create a `MedicalDataSource`
// Note that `displayName` must be unique across `MedicalDataSource`s
// Each `MedicalDataSource` is assigned an `id` by the system on creation
val medicalDataSource: MedicalDataSource =
    healthConnectClient.createMedicalDataSource(
        CreateMedicalDataSourceRequest(
            fhirBaseUri = Uri.parse("https://fhir.com/oauth/api/FHIR/R4/"),
            displayName = "Test Data Source",
            fhirVersion = FhirVersion(4, 0, 1)
        )
    )

MedicalDataSource 레코드 삭제

이전 예에서는 생성 시 시스템에서 id를 반환합니다. MedicalDataSource 레코드를 삭제해야 하는 경우 동일한 id을 참조하세요.

// Delete the `MedicalDataSource` that has the specified `id`
healthConnectClient.deleteMedicalDataSourceWithData(medicalDataSource.id)

의료 리소스

헬스 커넥트의 MedicalResource는 메타데이터와 함께 FHIR 리소스 (의료 기록 포함)를 나타냅니다.

MedicalResource의 속성:

  • DataSourceId (필수) - MedicalDataSource에 설명된 데이터 소스입니다.
  • FHIR 버전 (필수) - FHIR 버전입니다. 지원되는 버전이어야 합니다.
  • FHIR 리소스 (필수) JSON으로 인코딩된 FHIR 리소스 인스턴스입니다.
  • 의료 리소스 유형 (자동으로 채워짐) - 리소스의 사용자 대상 카테고리로, 사용자 대상 권한에 매핑됩니다.

JSON으로 FHIR 리소스 준비

의료 리소스를 헬스 커넥트에 쓰기 전에 JSON으로 FHIR 리소스 레코드를 준비합니다. 의료 리소스로 삽입할 수 있도록 각 JSON을 자체 변수에 저장합니다.

FHIR JSON 형식에 대한 도움이 필요한 경우 HL7 조직에서 제공하는 예시 데이터를 참고하세요.

MedicalResource 레코드 삽입 또는 업데이트

UpsertMedicalResourceRequest을 사용하여 MedicalDataSource의 새 MedicalResource 레코드를 삽입하거나 기존 레코드를 업데이트합니다.

// Insert `MedicalResource`s into the `MedicalDataSource`
val medicalResources: List<MedicalResource> =
    healthConnectClient.upsertMedicalResources(
        listOf(
            UpsertMedicalResourceRequest(
                medicalDataSource.id,
                medicalDataSource.fhirVersion,
                medicationJsonToInsert // a valid FHIR json string
            )
        )
    )

// Update `MedicalResource`s in the `MedicalDataSource`
val updatedMedicalResources: List<MedicalResource> =
    healthConnectClient.upsertMedicalResources(
        listOf(
            UpsertMedicalResourceRequest(
                medicalDataSource.id,
                medicalDataSource.fhirVersion,
                // a valid FHIR json string
                // if this resource has the same type and ID as in `medicationJsonToInsert`,
                // this `upsertMedicalResources()` call will update the previously inserted
                // `MedicalResource`
                updatedMedicationJsonToInsert
            )
        )
    )

FHIR 리소스 예

이전 예시에서 변수 medicationJsonToInsert은 유효한 FHIR JSON 문자열을 나타냈습니다.

다음은 FHIR 리소스 유형으로 AllergyIntolerance를 사용하는 JSON의 예입니다. 이는 의료 기록에서 FHIR_RESOURCE_TYPE_ALLERGY_INTOLERANCE의 의료 리소스 유형에 매핑됩니다.

{
  "resourceType": "AllergyIntolerance",
  "id": "allergyintolerance-1",
  "criticality": "high",
  "code": {
    "coding": [
      {
        "system": "http://snomed.info/sct",
        "code": "91936005",
        "display": "Penicillin allergy"
      }
    ],
    "text": "Penicillin allergy"
  },
  "recordedDate": "2020-10-09T14:58:00+00:00",
   "asserter": {
    "reference": "Patient/patient-1"
  },
  "lastOccurrence": "2020-10-09",
  "patient": {
    "reference": "Patient/patient-1",
    "display": "B., Alex"
  }
  ...
}

MedicalResource 레코드 삭제

MedicalResource 레코드는 ID로 삭제할 수 있습니다.

// Delete `MedicalResource`s matching the specified `dataSourceId`, `type` and `fhirResourceId`
healthConnectClient.deleteMedicalResources(
    medicalResources.map { medicalResource: MedicalResource ->
        MedicalResourceId(
            dataSourceId = medicalDataSource.id,
            fhirResourceType = medicalResource.id.fhirResourceType,
            fhirResourceId = medicalResource.id.fhirResourceId
        )
    }
)

또는 medicalResourceType에 의해 삭제될 수 있습니다.

// Delete all `MedicalResource`s that are in any pair of provided `dataSourceIds` and
// `medicalResourceTypes`
healthConnectClient.deleteMedicalResources(
    DeleteMedicalResourcesRequest(
        dataSourceIds = setOf(medicalDataSource.id),
        medicalResourceTypes = setOf(MEDICAL_RESOURCE_TYPE_MEDICATIONS)
    )
)