1. Hinweis
Aufgaben
In diesem Codelab erstellen Sie eine Android-App mit der FHIR Engine Library. Ihre App verwendet die FHIR Engine Library, um FHIR-Ressourcen von einem FHIR-Server herunterzuladen und alle lokalen Änderungen auf den Server hochzuladen.
Lerninhalte
- Lokalen HAPI FHIR-Server mit Docker erstellen
- FHIR Engine Library in Ihre Android-Anwendung einbinden
- Mit der Sync API einen einmaligen oder regelmäßigen Job zum Herunter- und Hochladen von FHIR-Ressourcen einrichten
- Search API verwenden
- So erstellen, lesen, aktualisieren und löschen Sie FHIR-Ressourcen lokal mithilfe der Data Access APIs
Voraussetzungen
- Docker (Docker herunterladen)
- Eine aktuelle Version von Android Studio (Version 4.1.2 oder höher)
- Android-Emulator oder ein Android-Gerät mit Android 7.0 Nougat oder höher
- Der Beispielcode
- Grundkenntnisse in der Android-Entwicklung mit Kotlin
Wenn Sie noch keine Android-Apps entwickelt haben, können Sie mit dem Erstellen Ihrer ersten App beginnen.
2. Lokalen HAPI FHIR-Server mit Testdaten einrichten
HAPI FHIR ist ein beliebter Open-Source-FHIR-Server. In unserem Codelab verwenden wir einen lokalen HAPI FHIR-Server, mit dem die Android-App eine Verbindung herstellen kann.
Lokalen HAPI FHIR-Server einrichten
- Führen Sie den folgenden Befehl in einem Terminal aus, um das neueste Image von HAPI FHIR abzurufen:
docker pull hapiproject/hapi:latest
- Erstellen Sie einen HAPI FHIR-Container, indem Sie entweder mit Docker Desktop das zuvor heruntergeladene Image
hapiproject/hapi
ausführen oder den folgenden Befehl ausführen: Weitere Informationendocker run -p 8080:8080 hapiproject/hapi:latest
- Prüfen Sie den Server, indem Sie die URL
http://localhost:8080/
in einem Browser öffnen. Die HAPI FHIR-Weboberfläche sollte angezeigt werden.
Lokalen HAPI FHIR-Server mit Testdaten füllen
Zum Testen unserer Anwendung benötigen wir einige Testdaten auf dem Server. Wir verwenden synthetische Daten, die von Synthea generiert wurden.
- Zuerst müssen wir Beispieldaten von synthea-samples herunterladen. Laden Sie
synthea_sample_data_fhir_r4_sep2019.zip
herunter und entpacken Sie es. Die entpackten Beispieldaten enthalten zahlreiche.json
-Dateien, die jeweils ein Transaktionsbundle für einen einzelnen Patienten sind. - Wir laden Testdaten für drei Patienten auf den lokalen HAPI FHIR-Server hoch. Führen Sie den folgenden Befehl im Verzeichnis mit den JSON-Dateien aus:
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/
- Wenn Sie Testdaten für alle Patienten auf den Server hochladen möchten, führen Sie
Das kann jedoch sehr lange dauern und ist für das Codelab nicht erforderlich.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done
- Prüfen Sie, ob die Testdaten auf dem Server verfügbar sind, indem Sie die URL
http://localhost:8080/fhir/Patient/
in einem Browser öffnen. Sie sollten den TextHTTP 200 OK
und den AbschnittResponse Body
der Seite mit Patientendaten in einem FHIR-Bundle als Suchergebnis mit einer Anzahl vontotal
sehen.
3. Android-App einrichten
Code herunterladen
Wenn Sie den Code für dieses Codelab herunterladen möchten, klonen Sie das Repository des Android FHIR SDK: git clone https://github.com/google/android-fhir.git
Das Starterprojekt für dieses Codelab befindet sich unter codelabs/engine
.
App in Android Studio importieren
Zuerst importieren wir die Starter-App in Android Studio.
Öffnen Sie Android Studio, wählen Sie Import Project (Gradle, Eclipse ADT, etc.) (Projekt importieren (Gradle, Eclipse ADT usw.)) aus und wählen Sie den Ordner codelabs/engine/
aus dem zuvor heruntergeladenen Quellcode aus.
Projekt mit Gradle-Dateien synchronisieren
Die Abhängigkeiten der FHIR Engine Library wurden dem Projekt bereits hinzugefügt. So können Sie die FHIR Engine Library in Ihre App einbinden. Beachten Sie die folgenden Zeilen bis zum Ende der app/build.gradle.kts
-Datei Ihres Projekts:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Damit alle Abhängigkeiten für Ihre App verfügbar sind, sollten Sie Ihr Projekt jetzt mit den Gradle-Dateien synchronisieren.
Wählen Sie in der Android Studio-Symbolleiste Projekt mit Gradle-Dateien synchronisieren () aus. Sie können die App auch noch einmal ausführen, um zu prüfen, ob die Abhängigkeiten ordnungsgemäß funktionieren.
Start-App ausführen
Nachdem Sie das Projekt in Android Studio importiert haben, können Sie die App zum ersten Mal ausführen.
Starten Sie den Android Studio-Emulator und klicken Sie in der Android Studio-Symbolleiste auf „Ausführen“ ().
4. FHIR Engine-Instanz erstellen
Wenn Sie die FHIR Engine in Ihre Android-App einbinden möchten, müssen Sie die FHIR Engine Library verwenden und eine Instanz der FHIR Engine initiieren. Die folgenden Schritte führen Sie durch den Prozess.
- Rufen Sie die Anwendungsklasse auf, in diesem Beispiel
FhirApplication.kt
inapp/src/main/java/com/google/android/fhir/codelabs/engine
. - Fügen Sie in der Methode
onCreate()
den folgenden Code hinzu, um die FHIR-Engine zu initialisieren: Hinweise: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
: Aktiviert die Datenverschlüsselung, sofern das Gerät diese Funktion unterstützt.RECREATE_AT_OPEN
: Bestimmt die Datenbankfehlerstrategie. In diesem Fall wird die Datenbank neu erstellt, wenn beim Öffnen ein Fehler auftritt.baseUrl
inServerConfiguration
: Dies ist die Basis-URL des FHIR-Servers. Die angegebene IP-Adresse10.0.2.2
ist speziell für den Localhost reserviert, auf den über den Android-Emulator zugegriffen werden kann. Weitere Informationen
- Fügen Sie in der Klasse
FhirApplication
die folgende Zeile hinzu, um die FHIR-Engine verzögert zu instanziieren: So wird sichergestellt, dass die FhirEngine-Instanz erst erstellt wird, wenn zum ersten Mal darauf zugegriffen wird, und nicht sofort beim Starten der App.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) }
- Fügen Sie der Klasse
FhirApplication
die folgende praktische Methode hinzu, um den Zugriff in Ihrer Anwendung zu vereinfachen: Mit dieser statischen Methode können Sie die FHIR Engine-Instanz an einer beliebigen Stelle in der App mithilfe des Kontexts abrufen.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Daten mit FHIR-Server synchronisieren
- Erstellen Sie einen neuen Kurs
DownloadWorkManagerImpl.kt
. In dieser Klasse definieren Sie, wie die Anwendung die nächste Ressource aus der Liste zum Herunterladen abruft: Diese Klasse hat eine Warteschlange mit Ressourcentypen, die heruntergeladen werden sollen. Er verarbeitet Antworten und extrahiert die Ressourcen aus dem zurückgegebenen Bundle, die in der lokalen Datenbank gespeichert werden.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 } }
- Neue Klasse erstellen
AppFhirSyncWorker.kt
: Diese Klasse definiert, wie die App mit dem Remote-FHIR-Server über einen Hintergrund-Worker synchronisiert wird. Hier haben wir festgelegt, welcher Downloadmanager, Konfliktlöser und welche FHIR-Engine-Instanz für die Synchronisierung verwendet werden soll.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, ) }
- In Ihrem ViewModel
PatientListViewModel.kt
richten Sie einen Mechanismus für die einmalige Synchronisierung ein. Suchen Sie den folgenden Code und fügen Sie ihn der FunktiontriggerOneTimeSync()
hinzu: Diese Coroutine initiiert eine einmalige Synchronisierung mit dem FHIR-Server mithilfe des zuvor definierten AppFhirSyncWorker. Die Benutzeroberfläche wird dann entsprechend dem Status des Synchronisierungsvorgangs aktualisiert.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } }
- Aktualisieren Sie in der Datei
PatientListFragment.kt
den Body der FunktionhandleSyncJobStatus
: Wenn der Synchronisierungsvorgang abgeschlossen ist, wird dem Nutzer eine Toast-Nachricht angezeigt. Anschließend werden in der App alle Patienten angezeigt, indem eine Suche mit einem leeren Namen aufgerufen wird.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Nachdem alles eingerichtet ist, können Sie die App ausführen. Klicken Sie dazu im Menü auf die Schaltfläche Sync
. Wenn alles richtig funktioniert, sollten die Patienten von Ihrem lokalen FHIR-Server heruntergeladen und in der Anwendung angezeigt werden.
6. Patientendaten ändern und hochladen
In diesem Abschnitt erfahren Sie, wie Sie Patientendaten anhand bestimmter Kriterien ändern und die aktualisierten Daten auf Ihren FHIR-Server hochladen. Insbesondere tauschen wir die Städte der Adressen von Patienten in Wakefield
und Taunton
aus.
Schritt 1: Änderungslogik in PatientListViewModel einrichten
Der Code in diesem Abschnitt wird der Funktion triggerUpdate
in PatientListViewModel
hinzugefügt.
- Auf die FHIR-Engine zugreifen:Rufen Sie zuerst eine Referenz auf die FHIR-Engine in der
PatientListViewModel.kt
ab. Mit diesem Code wird eine Coroutine im Bereich des ViewModels gestartet und die FHIR-Engine initialisiert.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication())
- Nach Patienten aus Wakefield suchen:Mit der FHIR-Engine nach Patienten mit der Adresse
Wakefield
suchen. Hier verwenden wir dieval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }
search
-Methode der FHIR-Engine, um Patienten anhand ihrer Wohnortstadt zu filtern. Das Ergebnis ist eine Liste der Patienten aus Wakefield. - Nach Patienten aus Taunton suchen:Sie können auch nach Patienten mit der Adresse
Taunton
suchen. Wir haben jetzt zwei Listen mit Patienten, eine aus Wakefield und eine aus Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) }
- Patientenadressen ändern:Gehen Sie alle Patienten in der Liste
patientsFromWakefield
durch, ändern Sie die Stadt inTaunton
und aktualisieren Sie sie in der FHIR-Engine. Ändern Sie bei allen Patienten in der ListepatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }
patientsFromTaunton
die Stadt inWakefield
.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) }
- Synchronisierung starten:Nachdem Sie die Daten lokal geändert haben, lösen Sie eine einmalige Synchronisierung aus, damit die Daten auf dem FHIR-Server aktualisiert werden.
Die schließende KlammertriggerOneTimeSync() }
}
kennzeichnet das Ende der zu Beginn gestarteten Coroutine.
Schritt 2: Funktion testen
- UI-Test:Führen Sie die App aus. Klicken Sie im Menü auf die Schaltfläche
Update
. Die Städte der Adressen von PatientAaron697
undAbby752
sollten vertauscht sein. - Serverüberprüfung:Öffnen Sie einen Browser und rufen Sie
http://localhost:8080/fhir/Patient/
auf. Prüfen Sie, ob die Stadt der Adresse für die PatientenAaron697
undAbby752
auf dem lokalen FHIR-Server aktualisiert wurde.
Sie haben damit einen Mechanismus zum Ändern von Patientendaten und zum Synchronisieren der Änderungen mit Ihrem FHIR-Server implementiert.
7. Nach Patientennamen suchen
Die Suche nach Patienten anhand ihres Namens kann eine nutzerfreundliche Möglichkeit zum Abrufen von Informationen bieten. In diesem Artikel zeigen wir Ihnen, wie Sie diese Funktion in Ihrer App implementieren.
Schritt 1: Funktionssignatur aktualisieren
Rufen Sie die Datei PatientListViewModel.kt
auf und suchen Sie die Funktion mit dem Namen searchPatientsByName
. Wir fügen dieser Funktion Code hinzu.
Wenn Sie die Ergebnisse anhand der angegebenen Namensabfrage filtern und die Ergebnisse für die Aktualisierung der Benutzeroberfläche ausgeben möchten, fügen Sie den folgenden bedingten Codeblock ein:
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 }
}
}
Wenn das Feld nameQuery
hier nicht leer ist, werden die Ergebnisse von der Suchfunktion so gefiltert, dass nur Patienten enthalten sind, deren Namen die angegebene Suchanfrage enthalten.
Schritt 2: Neue Suchfunktion testen
- App neu starten:Nachdem Sie diese Änderungen vorgenommen haben, erstellen Sie die App neu und führen Sie sie aus.
- Nach Patienten suchen: Verwenden Sie auf dem Bildschirm mit der Patientenliste die Suchfunktion. Sie sollten jetzt einen Namen (oder einen Teil eines Namens) eingeben können, um die Liste der Patienten entsprechend zu filtern.
Nachdem Sie diese Schritte ausgeführt haben, können Nutzer jetzt effizient nach Patientennamen suchen. Dies kann die Nutzerfreundlichkeit und Effizienz der Datenabfrage erheblich verbessern.
8. Glückwunsch!
Sie haben die FHIR Engine Library verwendet, um FHIR-Ressourcen in Ihrer App zu verwalten:
- FHIR-Ressourcen mit einem FHIR-Server über die Sync API synchronisieren
- Mit der Data Access API lokale FHIR-Ressourcen erstellen, lesen, aktualisieren und löschen
- Mit der Search API nach lokalen FHIR-Ressourcen suchen
Behandelte Themen
- Lokalen HAPI FHIR-Server einrichten
- Testdaten auf den lokalen HAPI FHIR-Server hochladen
- Android-App mit der FHIR Engine Library entwickeln
- Sync API, Data Access API und Search API in der FHIR Engine Library verwenden
Nächste Schritte
- Dokumentation für die FHIR Engine Library
- Erweiterte Funktionen der Search API
- FHIR Engine Library in Ihrer eigenen Android-App anwenden