1. Zanim zaczniesz
Co utworzysz
W tym ćwiczeniu utworzysz aplikację na Androida za pomocą biblioteki FHIR Engine. Aplikacja będzie używać biblioteki FHIR Engine do pobierania zasobów FHIR z serwera FHIR i przesyłania na serwer wszelkich lokalnych zmian.
Czego się nauczysz
- Jak utworzyć lokalny serwer HAPI FHIR za pomocą Dockera
- Jak zintegrować bibliotekę FHIR Engine z aplikacją na Androida
- Jak używać interfejsu Sync API do konfigurowania jednorazowych lub okresowych zadań pobierania i przesyłania zasobów FHIR
- Jak korzystać z interfejsu Search API
- Jak używać interfejsów Data Access API do tworzenia, odczytywania, aktualizowania i usuwania zasobów FHIR lokalnie
Czego potrzebujesz
- Docker (pobierz Dockera)
- Najnowsza wersja Android Studio (4.1.2 lub nowsza)
- Android Emulator lub fizyczne urządzenie z Androidem 7.0 Nougat lub nowszym.
- Przykładowy kod
- Podstawowa wiedza na temat tworzenia aplikacji na Androida w języku Kotlin
Jeśli nie masz jeszcze doświadczenia w tworzeniu aplikacji na Androida, możesz zacząć od utworzenia pierwszej aplikacji.
2. Konfigurowanie lokalnego serwera HAPI FHIR z danymi testowymi
HAPI FHIR to popularny serwer FHIR typu open source. W naszym laboratorium kodu używamy lokalnego serwera HAPI FHIR, z którym łączy się aplikacja na Androida.
Konfigurowanie lokalnego serwera HAPI FHIR
- Aby pobrać najnowszy obraz HAPI FHIR, uruchom w terminalu to polecenie:
docker pull hapiproject/hapi:latest - Utwórz kontener HAPI FHIR, uruchamiając pobrany wcześniej obraz
hapiproject/hapiza pomocą Docker Desktop lub uruchamiając to polecenie: Więcej informacjidocker run -p 8080:8080 hapiproject/hapi:latest - Sprawdź serwer, otwierając adres URL
http://localhost:8080/w przeglądarce. Powinien pojawić się interfejs internetowy HAPI FHIR.
Wypełnianie lokalnego serwera HAPI FHIR danymi testowymi
Aby przetestować aplikację, potrzebujemy na serwerze danych testowych. Użyjemy danych syntetycznych wygenerowanych przez Synthea.
- Najpierw musimy pobrać przykładowe dane z synthea-samples. Pobierz i rozpakuj
synthea_sample_data_fhir_r4_sep2019.zip. Rozpakowane dane przykładowe zawierają wiele plików.json, z których każdy jest pakietem transakcji dla konkretnego pacjenta. - Prześlemy dane testowe 3 pacjentów na lokalny serwer HAPI FHIR. Uruchom to polecenie w katalogu zawierającym pliki 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/ - Aby przesłać na serwer dane testowe wszystkich pacjentów, uruchom
Może to jednak potrwać długo i nie jest konieczne w przypadku tego ćwiczenia.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - Sprawdź, czy dane testowe są dostępne na serwerze, otwierając w przeglądarce adres URL
http://localhost:8080/fhir/Patient/. W wynikach wyszukiwania powinien się wyświetlić tekstHTTP 200 OKoraz sekcjaResponse Bodystrony zawierająca dane pacjenta w pakiecie FHIR z liczbątotal.
3. Konfigurowanie aplikacji na Androida
Pobieranie kodu
Aby pobrać kod do tego szkolenia, sklonuj repozytorium Android FHIR SDK: git clone https://github.com/google/android-fhir.git
Projekt początkowy tego ćwiczenia znajduje się w codelabs/engine.
Importowanie aplikacji do Android Studio
Zaczynamy od zaimportowania aplikacji startowej do Android Studio.
Otwórz Android Studio, wybierz Importuj projekt (Gradle, Eclipse ADT itp.) i wybierz folder codelabs/engine/ z pobranego wcześniej kodu źródłowego.

Synchronizowanie projektu z plikami Gradle
Dla Twojej wygody zależności biblioteki FHIR Engine zostały już dodane do projektu. Umożliwia to zintegrowanie biblioteki FHIR Engine z aplikacją. Zwróć uwagę na te wiersze na końcu pliku app/build.gradle.kts w projekcie:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Aby mieć pewność, że wszystkie zależności są dostępne dla aplikacji, na tym etapie zsynchronizuj projekt z plikami Gradle.
Na pasku narzędzi Android Studio wybierz Synchronizuj projekt z plikami Gradle (
). Możesz też ponownie uruchomić aplikację, aby sprawdzić, czy zależności działają prawidłowo.
Uruchamianie aplikacji startowej
Po zaimportowaniu projektu do Android Studio możesz po raz pierwszy uruchomić aplikację.
Uruchom emulator Android Studio i na pasku narzędzi Android Studio kliknij Uruchom (
).

4. Tworzenie instancji FHIR Engine
Aby zintegrować FHIR Engine z aplikacją na Androida, musisz użyć biblioteki FHIR Engine i utworzyć instancję FHIR Engine. Poniższe kroki pomogą Ci przejść przez ten proces.
- Otwórz klasę Application, która w tym przykładzie jest oznaczona jako
FhirApplication.kti znajduje się wapp/src/main/java/com/google/android/fhir/codelabs/engine. - W metodzie
onCreate()dodaj ten kod, aby zainicjować FHIR Engine: Uwagi: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: włącza szyfrowanie danych, jeśli urządzenie je obsługuje.RECREATE_AT_OPEN: określa strategię błędów bazy danych. W takim przypadku w razie błędu podczas otwierania baza danych zostanie utworzona ponownie.baseUrlwServerConfiguration: jest to podstawowy adres URL serwera FHIR. Podany adres IP10.0.2.2jest specjalnie zarezerwowany dla hosta lokalnego, do którego można uzyskać dostęp z emulatora Androida. Więcej informacji
- W klasie
FhirApplicationdodaj ten wiersz, aby leniwie utworzyć instancję FHIR Engine: Dzięki temu instancja FhirEngine jest tworzona tylko wtedy, gdy jest używana po raz pierwszy, a nie od razu po uruchomieniu aplikacji.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Dodaj do klasy
FhirApplicationtę metodę ułatwiającą dostęp w całej aplikacji: Ta metoda statyczna umożliwia pobranie instancji FHIR Engine z dowolnego miejsca w aplikacji za pomocą kontekstu.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Synchronizowanie danych z serwerem FHIR
- Utwórz nowe zajęcia
DownloadWorkManagerImpl.kt. W tej klasie określisz, jak aplikacja pobiera z listy kolejny zasób do pobrania. Ta klasa ma kolejkę typów zasobów, które chce pobrać. Przetwarza odpowiedzi i wyodrębnia zasoby z zwróconego pakietu, które są zapisywane w lokalnej bazie danych.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 } } - Utwórz nową klasę
AppFhirSyncWorker.ktTa klasa określa, jak aplikacja będzie synchronizować się ze zdalnym serwerem FHIR za pomocą procesu działającego w tle. W tym miejscu zdefiniowaliśmy, którego menedżera pobierania, narzędzia do rozwiązywania konfliktów i instancji silnika FHIR używać do synchronizacji.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, ) } - W obiekcie ViewModel
PatientListViewModel.ktskonfigurujesz jednorazowy mechanizm synchronizacji. Znajdź ten kod i dodaj go do funkcjitriggerOneTimeSync(): Ten współprogram inicjuje jednorazową synchronizację z serwerem FHIR za pomocą zdefiniowanego wcześniej elementu AppFhirSyncWorker. Następnie zaktualizuje interfejs na podstawie stanu procesu synchronizacji.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - W pliku
PatientListFragment.ktzaktualizuj treść funkcjihandleSyncJobStatus: Po zakończeniu procesu synchronizacji wyświetli się komunikat z powiadomieniem dla użytkownika, a następnie aplikacja wyświetli wszystkich pacjentów, wywołując wyszukiwanie z pustą nazwą.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Gdy wszystko będzie gotowe, uruchom aplikację. W menu kliknij przycisk Sync. Jeśli wszystko działa prawidłowo, pacjenci z lokalnego serwera FHIR powinni zostać pobrani i wyświetleni w aplikacji.

6. Modyfikowanie i przesyłanie danych pacjentów
W tej sekcji przeprowadzimy Cię przez proces modyfikowania danych pacjentów na podstawie określonych kryteriów i przesyłania zaktualizowanych danych na serwer FHIR. W przypadku pacjentów mieszkających w Wakefield i Taunton zamienimy miasta adresowe.
Krok 1. Skonfiguruj logikę modyfikacji w klasie PatientListViewModel
Kod w tej sekcji jest dodawany do funkcji triggerUpdate w pliku PatientListViewModel.
- Uzyskiwanie dostępu do FHIR Engine: zacznij od uzyskania odwołania do FHIR Engine w
PatientListViewModel.kt. Ten kod uruchamia współprogram w zakresie ViewModel i inicjuje silnik FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Wyszukaj pacjentów z Wakefield: użyj silnika FHIR, aby wyszukać pacjentów, których miasto zamieszkania to
Wakefield. W tym przypadku używamy metodyval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchsilnika FHIR do filtrowania pacjentów na podstawie miasta, w którym mieszkają. Wynikiem będzie lista pacjentów z Wakefield. - Wyszukaj pacjentów z Taunton: podobnie możesz wyszukać pacjentów, których miasto zamieszkania to
Taunton. Mamy teraz 2 listy pacjentów – jedną z Wakefield i drugą z Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - Modify Patient Addresses:przejrzyj każdego pacjenta na liście
patientsFromWakefield, zmień miasto naTauntoni zaktualizuj dane w silniku FHIR. Podobnie zaktualizuj każdego pacjenta na liściepatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTaunton, aby zmienić jego miasto naWakefield.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - Rozpocznij synchronizację: po zmodyfikowaniu danych lokalnie uruchom jednorazową synchronizację, aby mieć pewność, że dane są aktualizowane na serwerze FHIR.
Nawias zamykającytriggerOneTimeSync() }}oznacza koniec współprogramu uruchomionego na początku.
Krok 2. Przetestuj funkcję
- Testowanie interfejsu:uruchom aplikację. W menu kliknij przycisk
Update. Powinny wyświetlić się zamienione miasta adresowe pacjentówAaron697iAbby752. - Weryfikacja serwera: otwórz przeglądarkę i przejdź na stronę
http://localhost:8080/fhir/Patient/. Sprawdź, czy miasto w adresie pacjentówAaron697iAbby752zostało zaktualizowane na lokalnym serwerze FHIR.
Wykonując te czynności, udało Ci się wdrożyć mechanizm modyfikowania danych pacjenta i synchronizowania zmian z serwerem FHIR.
7. Wyszukiwanie pacjentów według imienia i nazwiska
Wyszukiwanie pacjentów po imieniu i nazwisku może być wygodnym sposobem na uzyskanie informacji. W tym artykule przeprowadzimy Cię przez proces wdrażania tej funkcji w aplikacji.
Krok 1. Zaktualizuj sygnaturę funkcji
Otwórz plik PatientListViewModel.kt i znajdź funkcję o nazwie searchPatientsByName. Dodamy do tej funkcji kod.
Aby filtrować wyniki na podstawie podanego zapytania o nazwę i emitować wyniki w celu aktualizacji interfejsu, włącz ten blok kodu warunkowego:
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 }
}
}
Jeśli pole nameQuery nie jest puste, funkcja wyszukiwania odfiltruje wyniki, aby uwzględniać tylko pacjentów, których imiona i nazwiska zawierają określone zapytanie.
Krok 2. Przetestuj nową funkcję wyszukiwania
- Ponownie uruchom aplikację: po wprowadzeniu tych zmian ponownie skompiluj i uruchom aplikację.
- Wyszukiwanie pacjentów: na ekranie listy pacjentów użyj funkcji wyszukiwania. Teraz możesz wpisać nazwę (lub jej część), aby odpowiednio przefiltrować listę pacjentów.
Po wykonaniu tych czynności Twoja aplikacja będzie bardziej funkcjonalna, ponieważ użytkownicy będą mogli skutecznie wyszukiwać pacjentów po nazwisku. Może to znacznie zwiększyć wygodę użytkowników i skuteczność pobierania danych.
8. Gratulacje!
Do zarządzania zasobami FHIR w aplikacji używasz biblioteki FHIR Engine:
- Synchronizowanie zasobów FHIR z serwerem FHIR za pomocą interfejsu Sync API
- Tworzenie, odczytywanie, aktualizowanie i usuwanie lokalnych zasobów FHIR za pomocą interfejsu Data Access API
- Wyszukiwanie lokalnych zasobów FHIR za pomocą interfejsu Search API
Omówione zagadnienia
- Konfigurowanie lokalnego serwera HAPI FHIR
- Jak przesyłać dane testowe na lokalny serwer HAPI FHIR
- Tworzenie aplikacji na Androida za pomocą biblioteki FHIR Engine
- Jak korzystać z interfejsów Sync API, Data Access API i Search API w bibliotece FHIR Engine
Następne kroki
- Zapoznaj się z dokumentacją biblioteki FHIR Engine
- Poznaj zaawansowane funkcje interfejsu Search API
- Stosowanie biblioteki FHIR Engine we własnej aplikacji na Androida