寫入醫療資料

本指南適用於 Health Connect 1.1.0-beta02 以上版本。

如要使用健康資料同步的「病歷」功能寫入醫療資料,請按照下列步驟操作:

  1. 確認功能支援情形
  2. 要求寫入權限
  3. 建立資料來源 (MedicalDataSource)
  4. 寫入醫療資源 (MedicalResource)

功能適用情況

如要判斷使用者的裝置是否支援 Health Connect 的「病歷」功能,請在用戶端檢查 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 管理中心和應用程式資訊清單中,為應用程式宣告這些權限:

<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 要求這些權限。系統接著會顯示 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)
  }
}

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

資料來源

健康資料同步 中的 MedicalDataSource 代表面向使用者的資料來源,例如醫療照護機構、醫院或 API。

儲存在「健康資料同步」中的病歷會整理成 MedicalDataSource。這樣一來,系統就能區分來自不同來源 (例如 API 或醫療照護系統) 的同一人病歷。

建立 MedicalDataSource 記錄時,請考量下列事項:

  • 如果所有記錄都來自相同來源,請建立一個 MedicalDataSource。
  • 如果記錄來自多個來源,只要符合下列條件,您就可以建立單一 MedicalDataSource:
    • 資料已核對。
    • 所有記錄都具有不重複的 FHIR 資源類型和 FHIR 資源 ID 組合。在 MedicalDataSource 中,只能有一筆 FHIR 資源類型的記錄,且可使用任何 FHIR 資源 ID。
  • 否則,為避免 ID 重複,請為每個資料來源建立 MedicalDataSource。

所有病歷都必須與 MedicalDataSource 建立關聯,因此必須先建立這項資源,才能寫入資源。

MedicalDataSource 的屬性:

  • 顯示名稱 (必填) - 資料來源的使用者顯示名稱,每個寫入應用程式皆有專屬 ID。
  • FHIR 基準 URI (必要) - 如果資料來自 FHIR 伺服器,則應為 FHIR 基準網址 (例如 https://example.com/fhir/)。多個資料來源可以與同一個 FHIR 基準網址建立關聯。

    如果資料是由沒有 FHIR 網址的應用程式產生,則應為應用程式定義的專屬且可理解的 URI (例如 myapp://..),指向資料來源。

    舉例來說,如果用戶端應用程式支援深層連結,則可將這個深層連結做為 FHIR 基本 URI。URI 長度上限為 2000 個字元。

  • 套件名稱 (自動填入):寫入資料的應用程式。

  • 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)

醫療資源

Health Connect 中的 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 字串。

以下是 JSON 的範例,使用 AllergyIntolerance 做為 FHIR 資源類型,對應至病歷中的醫療資源類型 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)
    )
)