1. Antes de comenzar
Qué compilarás
En este codelab, compilarás una app para Android con la biblioteca de FHIR Engine. Tu app usará la biblioteca de FHIR Engine para descargar recursos de FHIR desde un servidor de FHIR y subir cualquier cambio local al servidor.
Qué aprenderás
- Cómo crear un servidor local de HAPI FHIR con Docker
- Cómo integrar la biblioteca de FHIR Engine en tu aplicación para Android
- Cómo usar la API de Sync para configurar un trabajo único o periódico para descargar y subir recursos de FHIR
- Cómo usar la API de Search
- Cómo usar las APIs de Data Access para crear, leer, actualizar y borrar recursos de FHIR de forma local
Requisitos
- Docker (obtén Docker)
- Una versión reciente de Android Studio (v4.1.2 o posterior)
- Android Emulator o un dispositivo Android físico que ejecute Android 7.0 Nougat o versiones posteriores
- El código de muestra
- Conocimientos básicos sobre el desarrollo de Android en Kotlin
Si nunca compilaste apps para Android, puedes comenzar por compilar tu primera app.
2. Configura un servidor local de HAPI FHIR con datos de prueba
HAPI FHIR es un servidor de FHIR de código abierto popular. Usamos un servidor local de HAPI FHIR en nuestro codelab para que la app para Android se conecte.
Configura el servidor local de HAPI FHIR
- Ejecuta el siguiente comando en una terminal para obtener la imagen más reciente de HAPI FHIR.
docker pull hapiproject/hapi:latest - Crea un contenedor de HAPI FHIR con Docker Desktop para ejecutar la imagen descargada anteriormente
hapiproject/hapio ejecutando el siguiente comando. Más información.docker run -p 8080:8080 hapiproject/hapi:latest - Para inspeccionar el servidor, abre la URL
http://localhost:8080/en un navegador. Deberías ver la interfaz web de HAPI FHIR.
Propaga el servidor local de HAPI FHIR con datos de prueba
Para probar nuestra aplicación, necesitaremos algunos datos de prueba en el servidor. Usaremos datos sintéticos generados por Synthea.
- Primero, debemos descargar datos de muestra de synthea-samples. Descarga y extrae
synthea_sample_data_fhir_r4_sep2019.zip. Los datos de muestra descomprimidos tienen varios archivos.json, cada uno de los cuales es un paquete de transacciones para un paciente individual. - Subiremos datos de prueba para tres pacientes al servidor local de HAPI FHIR. Ejecuta el siguiente comando en el directorio que contiene archivos JSON.
curl -X POST -H "Content-Type: application/json" -d @./Aaron697_Brekke496_2fa15bc7-8866-461a-9000-f739e425860a.json http://localhost:8080/fhir/ curl -X POST -H "Content-Type: application/json" -d @./Aaron697_Stiedemann542_41166989-975d-4d17-b9de-17f94cb3eec1.json http://localhost:8080/fhir/ curl -X POST -H "Content-Type: application/json" -d @./Abby752_Kuvalis369_2b083021-e93f-4991-bf49-fd4f20060ef8.json http://localhost:8080/fhir/ - Para subir datos de prueba para todos los pacientes al servidor, ejecuta
Sin embargo, esto puede tardar mucho en completarse y no es necesario para el codelab.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - Para verificar que los datos de prueba estén disponibles en el servidor, abre la URL
http://localhost:8080/fhir/Patient/en un navegador. Deberías ver el textoHTTP 200 OKy la secciónResponse Bodyde la página que contiene datos de pacientes en un paquete de FHIR como resultado de la búsqueda con un recuentototal.
3. Configura la app para Android
Descarga el código
Para descargar el código de este codelab, clona el repositorio del SDK de FHIR para Android: git clone https://github.com/ohs-foundation/android-fhir.git
El proyecto inicial de este codelab se encuentra en codelabs/engine.
Importa la app a Android Studio
Comenzaremos por importar la app de partida a Android Studio.
Abre Android Studio, selecciona Import Project (Gradle, Eclipse ADT, etc.) y elige la carpeta codelabs/engine/ del código fuente que descargaste anteriormente.

Sincroniza tu proyecto con archivos de Gradle
Para tu comodidad, las dependencias de la biblioteca de FHIR Engine ya se agregaron al proyecto. Esto te permite integrar la biblioteca de FHIR Engine en tu app. Observa las siguientes líneas hasta el final del archivo app/build.gradle.kts de tu proyecto:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Para asegurarte de que todas las dependencias estén disponibles para tu app, debes sincronizar tu proyecto con archivos de Gradle en este punto.
Selecciona Sync Project with Gradle Files (
) en la barra de herramientas de Android Studio. También puedes volver a ejecutar la app para verificar que las dependencias funcionen correctamente.
Ejecuta la app de partida
Ahora que importaste el proyecto a Android Studio, tienes todo listo para ejecutar la app por primera vez.
Inicia el emulador de Android Studio y haz clic en Run (
) en la barra de herramientas de Android Studio.

4. Crea una instancia de FHIR Engine
Para incorporar FHIR Engine en tu app para Android, deberás usar la biblioteca de FHIR Engine y, luego, iniciar una instancia de FHIR Engine. Los pasos que se describen a continuación te guiarán por el proceso.
- Navega a tu clase Application, que en este ejemplo es
FhirApplication.kt, ubicada enapp/src/main/java/com/google/android/fhir/codelabs/engine. - Dentro del método
onCreate(), agrega el siguiente código para inicializar FHIR Engine: Notas:FhirEngineProvider.init( FhirEngineConfiguration( enableEncryptionIfSupported = true, RECREATE_AT_OPEN, ServerConfiguration( baseUrl = "http://10.0.2.2:8080/fhir/", httpLogger = HttpLogger( HttpLogger.Configuration( if (BuildConfig.DEBUG) HttpLogger.Level.BODY else HttpLogger.Level.BASIC, ), ) { Log.d("App-HttpLog", it) }, ), ), )enableEncryptionIfSupported: Habilita la encriptación de datos si el dispositivo la admite.RECREATE_AT_OPEN: Determina la estrategia de error de la base de datos. En este caso, vuelve a crear la base de datos si se produce un error al abrirla.baseUrlenServerConfiguration: Es la URL base del servidor de FHIR. La dirección IP proporcionada10.0.2.2está reservada especialmente para localhost, al que se puede acceder desde el emulador de Android. Más información.
- En la clase
FhirApplication, agrega la siguiente línea para crear una instancia diferida de FHIR Engine: Esto garantiza que la instancia de FhirEngine solo se cree cuando se acceda a ella por primera vez, no de inmediato cuando se inicia la app.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Agrega el siguiente método de conveniencia en la clase
FhirApplicationpara facilitar el acceso en toda la aplicación: Este método estático te permite recuperar la instancia de FHIR Engine desde cualquier lugar de la app con el contexto.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Sincroniza datos con el servidor de FHIR
- Crea una clase nueva
DownloadWorkManagerImpl.kt. En esta clase, definirás cómo la aplicación recupera el siguiente recurso de la lista para descargar: Esta clase tiene una cola de tipos de recursos que quiere descargar. Procesa las respuestas y extrae los recursos del paquete que se muestra, que se guardan en la base de datos local.class DownloadWorkManagerImpl : DownloadWorkManager { private val urls = LinkedList(listOf("Patient")) override suspend fun getNextRequest(): DownloadRequest? { val url = urls.poll() ?: return null return DownloadRequest.of(url) } override suspend fun getSummaryRequestUrls() = mapOf<ResourceType, String>() override suspend fun processResponse(response: Resource): Collection<Resource> { var bundleCollection: Collection<Resource> = mutableListOf() if (response is Bundle && response.type == Bundle.BundleType.SEARCHSET) { bundleCollection = response.entry.map { it.resource } } return bundleCollection } } - Crea una clase nueva
AppFhirSyncWorker.kt. Esta clase define cómo la app se sincronizará con el servidor de FHIR remoto mediante un trabajador en segundo plano. Aquí, definimos qué administrador de descargas, solucionador de conflictos y instancia de FHIR Engine usar para la sincronización.class AppFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) : FhirSyncWorker(appContext, workerParams) { override fun getDownloadWorkManager() = DownloadWorkManagerImpl() override fun getConflictResolver() = AcceptLocalConflictResolver override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) override fun getUploadStrategy() = UploadStrategy.forBundleRequest( methodForCreate = HttpCreateMethod.PUT, methodForUpdate = HttpUpdateMethod.PATCH, squash = true, bundleSize = 500, ) } - En tu ViewModel,
PatientListViewModel.kt, configurarás un mecanismo de sincronización único. Busca y agrega este código a la funcióntriggerOneTimeSync(): Esta corrutina inicia una sincronización única con el servidor de FHIR mediante AppFhirSyncWorker que definimos anteriormente. Luego, actualizará la IU según el estado del proceso de sincronización.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - En el archivo
PatientListFragment.kt, actualiza el cuerpo de la funciónhandleSyncJobStatus: Aquí, cuando finalice el proceso de sincronización, se mostrará un mensaje de notificación al usuario y, luego, la app mostrará a todos los pacientes invocando una búsqueda con un nombre vacío.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Ahora que todo está configurado, ejecuta la app. Haz clic en el botón Sync del menú. Si todo funciona correctamente, deberías ver que los pacientes de tu servidor local de FHIR se descargan y se muestran en la aplicación.

6. Modifica y sube datos de pacientes
En esta sección, te guiaremos por el proceso de modificación de los datos de los pacientes según criterios específicos y la carga de los datos actualizados en tu servidor de FHIR. En particular, intercambiaremos las ciudades de dirección de los pacientes que residen en Wakefield y Taunton.
Paso 1: Configura la lógica de modificación en PatientListViewModel
El código de esta sección se agrega a la función triggerUpdate en PatientListViewModel.
- Accede a FHIR Engine:Para comenzar, obtén una referencia a FHIR Engine en
PatientListViewModel.kt. Este código inicia una corrutina dentro del alcance de ViewModel y, luego, inicializa FHIR Engine.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Busca pacientes de Wakefield:Usa FHIR Engine para buscar pacientes con una ciudad de dirección de
Wakefield. Aquí, usamos el métodoval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchde FHIR Engine para filtrar pacientes según su ciudad de dirección. El resultado será una lista de pacientes de Wakefield. - Busca pacientes de Taunton:Del mismo modo, busca pacientes con una ciudad de dirección de
Taunton. Ahora tenemos dos listas de pacientes: una de Wakefield y otra de Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - Modifica las direcciones de los pacientes:Revisa a cada paciente de la lista
patientsFromWakefield, cambia su ciudad aTauntony actualízalos en FHIR Engine. Del mismo modo, actualiza a cada paciente de la listapatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTauntonpara que su ciudad cambie aWakefield.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - Inicia la sincronización:Después de modificar los datos de forma local, activa una sincronización única para asegurarte de que los datos se actualicen en el servidor de FHIR.
La llave de cierretriggerOneTimeSync() }}indica el final de la corrutina que se inició al principio.
Paso 2: Prueba la funcionalidad
- Pruebas de IU:Ejecuta la app. Haz clic en el botón
Updatedel menú. Deberías ver que se intercambiaron las ciudades de dirección de los pacientesAaron697yAbby752. - Verificación del servidor:Abre un navegador y navega a
http://localhost:8080/fhir/Patient/. Verifica que la ciudad de dirección de los pacientesAaron697yAbby752se actualice en el servidor local de FHIR.
Si sigues estos pasos, habrás implementado correctamente un mecanismo para modificar los datos de los pacientes y sincronizar los cambios con tu servidor de FHIR.
7. Busca pacientes por nombre
Buscar pacientes por sus nombres puede proporcionar una forma fácil de usar para recuperar información. Aquí, te guiaremos por el proceso de implementación de esta función en tu aplicación.
Paso 1: Actualiza la firma de la función
Navega a tu archivo PatientListViewModel.kt y busca la función llamada searchPatientsByName. Agregaremos código a esta función.
Para filtrar los resultados según la consulta de nombre proporcionada y emitir los resultados para que se actualice la IU, incorpora el siguiente bloque de código condicional:
viewModelScope.launch {
val fhirEngine = FhirApplication.fhirEngine(getApplication())
if (nameQuery.isNotEmpty()) {
val searchResult = fhirEngine.search<Patient> {
filter(
Patient.NAME,
{
modifier = StringFilterModifier.CONTAINS
value = nameQuery
},
)
}
liveSearchedPatients.value = searchResult.map { it.resource }
}
}
Aquí, si nameQuery no está vacío, la función de búsqueda filtrará los resultados para incluir solo a los pacientes cuyos nombres contengan la consulta especificada.
Paso 2: Prueba la nueva funcionalidad de búsqueda
- Vuelve a iniciar la app:Después de realizar estos cambios, vuelve a compilar y ejecutar la app.
- Busca pacientes: En la pantalla de la lista de pacientes, usa la funcionalidad de búsqueda. Ahora deberías poder ingresar un nombre (o parte de un nombre) para filtrar la lista de pacientes según corresponda.
Una vez completados estos pasos, mejoraste tu aplicación, ya que proporcionaste a los usuarios la capacidad de buscar pacientes de manera eficiente por sus nombres. Esto puede mejorar significativamente la experiencia del usuario y la eficiencia en la recuperación de datos.
8. ¡Felicitaciones!
Usaste la biblioteca de FHIR Engine para administrar recursos de FHIR en tu app:
- Usa la API de Sync para sincronizar recursos de FHIR con un servidor de FHIR.
- Usa la API de Data Access para crear, leer, actualizar y borrar recursos locales de FHIR.
- Usa la API de Search para buscar recursos locales de FHIR.
Temas abordados
- Cómo configurar un servidor local de HAPI FHIR
- Cómo subir datos de prueba al servidor local de HAPI FHIR
- Cómo compilar una app para Android con la biblioteca de FHIR Engine
- Cómo usar la API de Sync, la API de Data Access y la API de Search en la biblioteca de FHIR Engine
Próximos pasos
- Explora la documentación de la biblioteca de FHIR Engine.
- Explora las funciones avanzadas de la API de Search.
- Aplica la biblioteca de FHIR Engine en tu propia app para Android.