1. Prima di iniziare
Cosa creerai
In questo codelab, creerai un'app per Android utilizzando la libreria FHIR Engine. La tua app utilizzerà la libreria FHIR Engine per scaricare le risorse FHIR da un server FHIR e caricare le modifiche locali sul server.
Obiettivi didattici
- Come creare un server HAPI FHIR locale utilizzando Docker
- Come integrare la libreria FHIR Engine nella tua applicazione Android
- Come utilizzare l'API Sync per configurare un job una tantum o periodico per scaricare e caricare risorse FHIR
- Come utilizzare l'API Search
- Come utilizzare le API Data Access per creare, leggere, aggiornare ed eliminare le risorse FHIR in locale
Che cosa ti serve
- Docker (scarica Docker)
- Una versione recente di Android Studio (v4.1.2+)
- Android Emulator o un dispositivo Android fisico con Android 7.0 Nougat o versioni successive
- Il codice campione
- Conoscenza di base dello sviluppo Android in Kotlin
Se non hai mai creato app per Android, puoi iniziare creando la tua prima app.
2. Configura un server HAPI FHIR locale con dati di test
HAPI FHIR è un server FHIR open source molto diffuso. Nel nostro codelab utilizziamo un server HAPI FHIR locale a cui connettersi per l'app per Android.
Configura il server HAPI FHIR locale
- Esegui questo comando in un terminale per ottenere l'ultima immagine di HAPI FHIR
docker pull hapiproject/hapi:latest - Crea un container HAPI FHIR utilizzando Docker Desktop per eseguire l'immagine scaricata in precedenza
hapiproject/hapio eseguendo il seguente comando Scopri di più.docker run -p 8080:8080 hapiproject/hapi:latest - Controlla il server aprendo l'URL
http://localhost:8080/in un browser. Dovresti visualizzare l'interfaccia web HAPI FHIR.
Compilare il server HAPI FHIR locale con dati di test
Per testare la nostra applicazione, abbiamo bisogno di alcuni dati di test sul server. Utilizzeremo i dati sintetici generati da Synthea.
- Innanzitutto, dobbiamo scaricare i dati di esempio da synthea-samples. Scarica ed estrai
synthea_sample_data_fhir_r4_sep2019.zip. I dati di esempio decompressi contengono numerosi file.json, ognuno dei quali è un bundle di transazioni per un singolo paziente. - Caricheremo i dati di test per tre pazienti sul server HAPI FHIR locale. Esegui questo comando nella directory contenente i file 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/ - Per caricare i dati di test per tutti i pazienti sul server, esegui
Tuttavia, il completamento di questa operazione può richiedere molto tempo e non è necessario per il codelab.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - Verifica che i dati di test siano disponibili sul server aprendo l'URL
http://localhost:8080/fhir/Patient/in un browser. Dovresti visualizzare il testoHTTP 200 OKe la sezioneResponse Bodydella pagina contenente i dati del paziente in un FHIR Bundle come risultato di ricerca con un conteggio ditotal.
3. Configurare l'app Android
Scarica il codice
Per scaricare il codice di questo codelab, clona il repository Android FHIR SDK: git clone https://github.com/google/android-fhir.git
Il progetto iniziale per questo codelab si trova in codelabs/engine.
Importa l'app in Android Studio
Iniziamo importando l'app iniziale in Android Studio.
Apri Android Studio, seleziona Import Project (Gradle, Eclipse ADT, etc.) e scegli la cartella codelabs/engine/ del codice sorgente che hai scaricato in precedenza.

Sincronizzare il progetto con i file Gradle
Per comodità, le dipendenze della libreria FHIR Engine sono già state aggiunte al progetto. In questo modo puoi integrare la libreria FHIR Engine nella tua app. Osserva le seguenti righe fino alla fine del file app/build.gradle.kts del tuo progetto:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Per assicurarti che tutte le dipendenze siano disponibili per la tua app, a questo punto devi sincronizzare il progetto con i file Gradle.
Seleziona Sincronizza progetto con file Gradle (
) dalla barra degli strumenti di Android Studio. Puoi anche eseguire di nuovo l'app per verificare che le dipendenze funzionino correttamente.
Esegui l'app di base
Ora che hai importato il progetto in Android Studio, puoi eseguire l'app per la prima volta.
Avvia l'emulatore Android Studio e fai clic su Esegui (
) nella barra degli strumenti di Android Studio.

4. Crea un'istanza FHIR Engine
Per incorporare FHIR Engine nella tua app per Android, devi utilizzare la libreria FHIR Engine e avviare un'istanza di FHIR Engine. I passaggi descritti di seguito ti guideranno nella procedura.
- Vai alla classe Application, che in questo esempio è
FhirApplication.kt, situata inapp/src/main/java/com/google/android/fhir/codelabs/engine. - All'interno del metodo
onCreate(), aggiungi il seguente codice per inizializzare FHIR Engine: Note: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: attiva la crittografia dei dati se il dispositivo la supporta.RECREATE_AT_OPEN: determina la strategia di errore del database. In questo caso, ricrea il database se si verifica un errore all'apertura.baseUrlinServerConfiguration: è l'URL di base del server FHIR. L'indirizzo IP fornito10.0.2.2è riservato in modo speciale a localhost, accessibile dall'emulatore Android. Scopri di più.
- Nella classe
FhirApplication, aggiungi la seguente riga per creare un'istanza differita di FHIR Engine: In questo modo, l'istanza FhirEngine viene creata solo quando viene eseguito l'accesso per la prima volta, non immediatamente all'avvio dell'app.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Aggiungi il seguente metodo di convenienza nella classe
FhirApplicationper un accesso più semplice in tutta l'applicazione: Questo metodo statico ti consente di recuperare l'istanza di FHIR Engine da qualsiasi punto dell'app utilizzando il contesto.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Sincronizzare i dati con il server FHIR
- Crea un nuovo corso
DownloadWorkManagerImpl.kt. In questa classe, definirai il modo in cui l'applicazione recupera la risorsa successiva dall'elenco da scaricare. Questa classe ha una coda di tipi di risorse che vuole scaricare. Elabora le risposte ed estrae le risorse dal bundle restituito, che vengono salvate nel database locale.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 nuova classe
AppFhirSyncWorker.ktQuesta classe definisce il modo in cui l'app si sincronizzerà con il server FHIR remoto utilizzando un worker in background. Qui abbiamo definito quale download manager, risoluzione dei conflitti e istanza del motore FHIR utilizzare per la sincronizzazione.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, ) } - Nel ViewModel,
PatientListViewModel.kt, configurerai un meccanismo di sincronizzazione una tantum. Individua e aggiungi questo codice alla funzionetriggerOneTimeSync(): Questa coroutine avvia una sincronizzazione una tantum con il server FHIR utilizzando AppFhirSyncWorker che abbiamo definito in precedenza. Successivamente, l'interfaccia utente verrà aggiornata in base allo stato del processo di sincronizzazione.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - Nel file
PatientListFragment.kt, aggiorna il corpo della funzionehandleSyncJobStatus: Al termine della procedura di sincronizzazione, viene visualizzato un messaggio di notifica per l'utente e l'app mostra tutti i pazienti richiamando una ricerca con un nome vuoto.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Ora che tutto è configurato, esegui l'app. Fai clic sul pulsante Sync nel menu. Se tutto funziona correttamente, dovresti vedere i pazienti del tuo server FHIR locale scaricati e visualizzati nell'applicazione.

6. Modificare e caricare i dati dei pazienti
In questa sezione, ti guideremo nella procedura di modifica dei dati dei pazienti in base a criteri specifici e nel caricamento dei dati aggiornati sul tuo server FHIR. Nello specifico, scambieremo le città degli indirizzi per i pazienti residenti in Wakefield e Taunton.
Passaggio 1: configura la logica di modifica in PatientListViewModel
Il codice in questa sezione viene aggiunto alla funzione triggerUpdate in PatientListViewModel
- Accedi a FHIR Engine:inizia ottenendo un riferimento a FHIR Engine in
PatientListViewModel.kt. Questo codice avvia una coroutine nell'ambito di ViewModel e inizializza il motore FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Cerca pazienti di Wakefield:utilizza il motore FHIR per cercare pazienti con la città dell'indirizzo
Wakefield. Qui utilizziamo il metodoval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchdel motore FHIR per filtrare i pazienti in base alla città del loro indirizzo. Il risultato sarà un elenco di pazienti di Wakefield. - Cerca pazienti di Taunton:in modo analogo, cerca i pazienti con la città dell'indirizzo
Taunton. Ora abbiamo due elenchi di pazienti: uno di Wakefield e l'altro di Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - Modifica indirizzi pazienti:esamina ogni paziente nell'elenco
patientsFromWakefield, modifica la città inTauntone aggiorna i dati nel motore FHIR. Allo stesso modo, aggiorna ogni paziente nell'elencopatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTauntonin modo che la sua città venga modificata inWakefield.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - Avvia sincronizzazione:dopo aver modificato i dati localmente, attiva una sincronizzazione una tantum per assicurarti che i dati vengano aggiornati sul server FHIR.
La parentesi chiusatriggerOneTimeSync() }}indica la fine della coroutine avviata all'inizio.
Passaggio 2: testa la funzionalità
- Test UI:esegui l'app. Fai clic sul pulsante
Updatenel menu. Dovresti vedere le città degli indirizzi dei pazientiAaron697eAbby752scambiati. - Verifica del server:apri un browser e vai all'indirizzo
http://localhost:8080/fhir/Patient/. Verifica che la città dell'indirizzo per i pazientiAaron697eAbby752sia aggiornata sul server FHIR locale.
Seguendo questi passaggi, hai implementato correttamente un meccanismo per modificare i dati dei pazienti e sincronizzare le modifiche con il server FHIR.
7. Cercare pazienti per nome
La ricerca dei pazienti per nome può fornire un modo semplice per recuperare le informazioni. Qui ti guideremo attraverso la procedura di implementazione di questa funzionalità nella tua applicazione.
Passaggio 1: aggiorna la firma della funzione
Vai al file PatientListViewModel.kt e trova la funzione denominata searchPatientsByName. Aggiungeremo il codice a questa funzione.
Per filtrare i risultati in base alla query sul nome fornita ed emettere i risultati per l'aggiornamento della UI, incorpora il seguente blocco di codice condizionale:
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 }
}
}
Qui, se nameQuery non è vuoto, la funzione di ricerca filtra i risultati in modo da includere solo i pazienti i cui nomi contengono la query specificata.
Passaggio 2: testa la nuova funzionalità di ricerca
- Riavvia l'app:dopo aver apportato queste modifiche, ricompila ed esegui l'app.
- Cerca pazienti: nella schermata dell'elenco dei pazienti, utilizza la funzionalità di ricerca. Ora dovresti essere in grado di inserire un nome (o parte di un nome) per filtrare l'elenco dei pazienti di conseguenza.
Una volta completati questi passaggi, hai migliorato la tua applicazione fornendo agli utenti la possibilità di cercare in modo efficiente i pazienti in base al loro nome. Ciò può migliorare significativamente l'esperienza utente e l'efficienza nel recupero dei dati.
8. Complimenti!
Hai utilizzato la libreria FHIR Engine per gestire le risorse FHIR nella tua app:
- Utilizzare l'API Sync per sincronizzare le risorse FHIR con un server FHIR
- Utilizza l'API Data Access per creare, leggere, aggiornare ed eliminare risorse FHIR locali
- Utilizzare l'API Search per cercare risorse FHIR locali
Argomenti trattati
- Come configurare un server HAPI FHIR locale
- Come caricare i dati di test sul server HAPI FHIR locale
- Come creare un'app Android utilizzando la libreria FHIR Engine
- Come utilizzare l'API Sync, l'API Data Access e l'API Search nella libreria FHIR Engine
Passaggi successivi
- Esplora la documentazione della libreria FHIR Engine
- Esplora le funzionalità avanzate dell'API Search
- Applica la libreria FHIR Engine nella tua app per Android