写入医疗数据

本指南适用于 Health Connect 版本 1.1.0-beta02

如需在 Health Connect 中使用个人健康记录 (PHR) 写入医疗数据,请按以下步骤操作:

  1. 查看功能的可用性
  2. 请求写入权限
  3. 创建数据源 (MedicalDataSource)
  4. 撰写医疗资源 (MedicalResource)

功能的适用范围

如需确定用户的设备是否支持 Health Connect 中的个人健康记录 (PHR),请检查客户端上 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)
  }
}

由于用户可以随时授予或撤消权限,因此您的应用需要定期检查已授予的权限,并应对权限丢失的情况。

数据源

Health Connect 中的 MedicalDataSource 代表面向用户的数据源,例如医疗保健组织、医院或 API。

存储在 Health Connect 中的医疗记录会整理到 MedicalDataSource 中。这样,系统就可以将来自不同来源(例如 API 或医疗系统)的同一个人的医疗记录分开。

如果所有记录都来自同一来源,写入应用只需创建一个 MedicalDataSource。如果记录来自多个来源,只要这些数据已协调一致且所有记录的 FHIR 资源类型和 FHIR 资源 ID 组合都是唯一的,应用仍可以创建单个 MedicalDataSource。否则,应为每个数据源创建 MedicalDataSource

所有医疗记录都必须与 MedicalDataSource 相关联,因此必须先创建 MedicalDataSource,然后才能写入资源。

MedicalDataSource 的属性:

  • 显示名称(必需)- 面向用户的数据源显示名称,每个写入应用都有唯一标识。
  • FHIR 基准 URI(必需)- 对于来自 FHIR 服务器的数据,此字段应为 FHIR 基准网址(例如 https://example.com/fhir/)。多个数据源可以与同一 FHIR 基准网址相关联。

    如果数据由不含 FHIR 网址的应用生成,则此字段应为应用定义的唯一且易于理解的 URI(例如 myapp://..),该 URI 应指向数据的来源。

    例如,如果客户端应用支持深层链接,则此深层链接可用作 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 资源

在将医疗资源写入 Health Connect 之前,请使用 JSON 格式准备 FHIR 资源记录。将每个 JSON 存储在自己的变量中,以便作为医疗资源插入。

如果您需要有关 FHIR JSON 格式的帮助,请参阅 HL7 组织提供的示例数据

插入或更新 MedicalResource 记录

使用 UpsertMedicalResourceRequestMedicalDataSource 插入新的 MedicalResource 记录或更新现有 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 资源类型,该类型会映射到 PHR 中的 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 记录

系统可能会按 ID 删除 MedicalResource 记录:

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