写入医疗数据

本指南与健康数据共享版本 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 请求这些权限。系统随即会显示“健康数据共享”权限界面。

// 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,前提是这些数据已协调一致,并且所有记录都具有 FHIR 资源类型和 FHIR 资源 ID 的唯一组合。 否则,应为每个数据源创建一个 MedicalDataSource

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

MedicalDataSource 的属性:

  • 显示名称(必需)- 面向用户的显示名称,每个写入应用都必须具有唯一的显示名称。
  • 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)

医疗资源

健康数据共享中的 MedicalResource 表示 FHIR 资源(包含医疗记录)以及元数据。

MedicalResource 的属性:

  • DataSourceId(必需)- 数据源,如 MedicalDataSource 中所述。
  • FHIR 版本(必需)- FHIR 版本。必须是受支持的版本
  • FHIR 资源(必需)JSON 编码的 FHIR 资源实例。
  • 医疗资源类型(自动填充)- 资源的面向用户的类别,与面向用户的权限相对应。

以 JSON 格式准备 FHIR 资源

在将医疗资源写入“健康数据共享”之前,请先以 JSON 格式准备好 FHIR 资源记录。将每个 JSON 存储在各自的变量中,以便作为医疗资源插入。

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

插入或更新 MedicalResource 记录

使用 UpsertMedicalResourceRequestMedicalDataSource 插入新的或更新现有的 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)
    )
)