1. 事前準備
建構項目
在本程式碼研究室中,您將使用 FHIR Engine 程式庫建構 Android 應用程式。您的應用程式會使用 FHIR Engine 程式庫,從 FHIR 伺服器下載 FHIR 資源,並將任何本機變更上傳至伺服器。
課程內容
- 如何使用 Docker 建立本機 HAPI FHIR 伺服器
- 如何將 FHIR Engine 程式庫整合至 Android 應用程式
- 如何使用 Sync API 設定一次性或定期工作,以便下載及上傳 FHIR 資源
- 如何使用 Search API
- 如何使用資料存取 API 在本機建立、讀取、更新及刪除 FHIR 資源
軟硬體需求
- Docker (取得 Docker)
- 最新版 Android Studio (4.1.2 以上版本)
- Android Emulator 或搭載 Android 7.0 Nougat 以上版本的實體 Android 裝置
- 程式碼範例
- 對 Kotlin 中的 Android 開發作業有基本瞭解
如果您之前未建構過 Android 應用程式,可以先建構第一個應用程式。
2. 設定本機 HAPI FHIR 伺服器,並加入測試資料
HAPI FHIR 是熱門的開放原始碼 FHIR 伺服器。我們在程式碼研究室中使用本機 HAPI FHIR 伺服器,供 Android 應用程式連線。
設定本機 HAPI FHIR 伺服器
- 在終端機中執行下列指令,取得 HAPI FHIR 的最新映像檔
docker pull hapiproject/hapi:latest - 使用 Docker Desktop 執行先前下載的映像檔
hapiproject/hapi,或執行下列指令,建立 HAPI FHIR 容器 瞭解詳情。docker run -p 8080:8080 hapiproject/hapi:latest - 在瀏覽器中開啟網址
http://localhost:8080/,檢查伺服器。您應該會看到 HAPI FHIR 網頁介面。
使用測試資料填入本機 HAPI FHIR 伺服器
為了測試應用程式,我們需要在伺服器上建立一些測試資料。我們會使用 Synthea 產生的合成資料。
- 首先,我們需要從 synthea-samples 下載範例資料。下載並解壓縮
synthea_sample_data_fhir_r4_sep2019.zip。解壓縮的範例資料包含許多.json檔案,每個檔案都是個別病患的交易套件。 - 我們會將三位病患的測試資料上傳至本機 HAPI FHIR 伺服器。在包含 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/ - 如要將所有病患的測試資料上傳至伺服器,請執行
不過,這可能需要很長的時間才能完成,而且本程式碼研究室並不需要這麼做。for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - 在瀏覽器中開啟網址
http://localhost:8080/fhir/Patient/,確認伺服器上有測試資料。您應該會看到文字HTTP 200 OK和Response Body部分,其中包含 FHIR 束帶中的病患資料,並以total計數的搜尋結果。
3. 設定 Android 應用程式
下載程式碼
如要下載本程式碼研究室的程式碼,請複製 Android FHIR SDK 存放區:git clone https://github.com/google/android-fhir.git
這個程式碼研究室的範例專案位於 codelabs/engine 中。
將應用程式匯入 Android Studio
首先,我們會將範例應用程式匯入 Android Studio。
開啟 Android Studio,選取「Import Project (Gradle, Eclipse ADT, etc.)」,然後從先前下載的來源程式碼中選擇 codelabs/engine/ 資料夾。

將專案與 Gradle 檔案同步處理
為方便起見,我們已將 FHIR Engine Library 依附元件新增至專案。這樣一來,您就能在應用程式中整合 FHIR Engine 程式庫。請觀察專案 app/build.gradle.kts 檔案結尾的以下行程式碼:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
為確保應用程式可使用所有依附元件,您應在此時將專案與 Gradle 檔案同步。
在 Android Studio 工具列中選取「Sync Project with Gradle Files」 (
)。您也可以再次執行應用程式,檢查依附元件是否正常運作。
執行範例應用程式
專案已匯入 Android Studio,您可以開始執行應用程式。
啟動 Android Studio 模擬器,然後按一下 Android Studio 工具列中的「Run」(執行) (
)。

4. 建立 FHIR Engine 例項
如要將 FHIR Engine 整合至 Android 應用程式,您必須使用 FHIR Engine 程式庫並啟動 FHIR Engine 的例項。請按照下列步驟完成程序。
- 前往「Application」類別,在本例中為
app/src/main/java/com/google/android/fhir/codelabs/engine中的FhirApplication.kt。 - 在
onCreate()方法中加入下列程式碼,初始化 FHIR 引擎: 注意事項: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:如果裝置支援,則啟用資料加密功能。RECREATE_AT_OPEN:決定資料庫錯誤策略。在這種情況下,如果開啟時發生錯誤,系統就會重新建立資料庫。ServerConfiguration中的baseUrl:這是 FHIR 伺服器的基準網址。提供的 IP 位址10.0.2.2是專門為 localhost 保留,可透過 Android 模擬器存取。瞭解詳情。
- 在
FhirApplication類別中,新增下列程式碼,以便延遲實例化 FHIR 引擎: 這可確保 FhirEngine 例項只在首次存取時建立,而不會在應用程式啟動時立即建立。private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - 在
FhirApplication類別中新增下列便利方法,方便在應用程式中存取: 這個靜態方法可讓您透過使用結構定義的應用程式中的任何位置,擷取 FHIR Engine 例項。companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. 將資料與 FHIR 伺服器同步處理
- 建立新的類別
DownloadWorkManagerImpl.kt。在這個類別中,您將定義應用程式如何從下載清單擷取下一個資源: 這個類別包含要下載的資源類型佇列。它會處理回應,並從傳回的套件中擷取資源,然後儲存至本機資料庫。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 } } - 建立新類別
AppFhirSyncWorker.kt這個類別會定義應用程式如何使用背景工作者與遠端 FHIR 伺服器同步處理。 我們已在此定義要用於同步處理的下載管理器、衝突解決程式和 FHIR 引擎例項。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, ) } - 在 ViewModel
PatientListViewModel.kt中,您將設定一次性同步處理機制。找出並將以下程式碼新增至triggerOneTimeSync()函式: 這個協同程式會使用我們先前定義的 AppFhirSyncWorker,與 FHIR 伺服器啟動一次性同步處理作業。接著,系統會根據同步處理程序的狀態更新 UI。viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - 在
PatientListFragment.kt檔案中,更新handleSyncJobStatus函式的主體: 在這個範例中,同步處理程序完成後,系統會顯示 Toast 訊息通知使用者,然後應用程式會呼叫空白名稱的搜尋,並顯示所有病患。when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
一切設定完成後,請執行應用程式。按一下選單中的 Sync 按鈕。如果一切正常,您應該會看到從本機 FHIR 伺服器下載的患者,並顯示在應用程式中。

6. 修改及上傳病患資料
在本節中,我們將引導您根據特定條件修改病患資料,並將更新後的資料上傳至 FHIR 伺服器。具體來說,我們會為居住在 Wakefield 和 Taunton 的病患交換地址城市。
步驟 1:在 PatientListViewModel 中設定修改邏輯
本節中的程式碼會新增至 PatientListViewModel 中的 triggerUpdate 函式
- 存取 FHIR 引擎:請先取得
PatientListViewModel.kt中的 FHIR 引擎參照。 這段程式碼會在 ViewModel 範圍內啟動協同程式,並初始化 FHIR 引擎。viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - 搜尋 Wakefield 的病患:使用 FHIR 引擎搜尋地址城市為
Wakefield的病患。 我們在這裡使用 FHIR 引擎的val patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }search方法,根據病患的地址所在城市篩選病患。結果會是 Wakefield 的病患清單。 - 搜尋 Taunton 的病患:同樣地,搜尋地址城市為
Taunton的病患。 我們現在有兩份病患名單,一份來自韋克菲爾德,另一份來自唐頓。val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - 修改病患地址:逐一查看
patientsFromWakefield清單中的每位病患,將他們的城市更改為Taunton,並在 FHIR 引擎中更新。 同樣地,請更新patientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTaunton清單中的每位病患,將他們的城市變更為Wakefield。patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - 啟動同步作業:在本機修改資料後,觸發一次性同步作業,確保 FHIR 伺服器上的資料已更新。
右括號triggerOneTimeSync() }}表示一開始啟動的協同程式已結束。
步驟 2:測試功能
- 使用者介面測試:執行應用程式。按一下選單中的
Update按鈕。您應該會看到病患Aaron697和Abby752的地址城市互換。 - 伺服器驗證:開啟瀏覽器並前往
http://localhost:8080/fhir/Patient/。確認患者Aaron697和Abby752的地址城市已在本機 FHIR 伺服器上更新。
按照這些步驟操作後,您已成功實作修改病患資料的機制,並將變更內容同步處理至 FHIR 伺服器。
7. 依名稱搜尋病患
您可以透過患者姓名搜尋,以便於擷取資訊。我們將逐步說明如何在應用程式中實作這項功能。
步驟 1:更新函式簽名
前往 PatientListViewModel.kt 檔案,找出名為 searchPatientsByName 的函式。我們會在這個函式中加入程式碼。
如要根據提供的名稱查詢篩選結果,並發出結果供 UI 更新,請納入下列條件式程式碼區塊:
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 }
}
}
在此情況下,如果 nameQuery 非空白,搜尋函式會篩選結果,只保留姓名含有指定查詢的病患。
步驟 2:測試新搜尋功能
- 重新啟動應用程式:完成這些變更後,請重新建構並執行應用程式。
- 搜尋病患:在病患名單畫面上使用搜尋功能。您現在應該可以輸入名稱 (或名稱的一部分),藉此篩選患者清單。
完成這些步驟後,您就能讓使用者透過姓名快速搜尋病患,進而提升應用程式的效能。這麼做可以大幅改善使用者體驗,並提高資料擷取效率。
8. 恭喜!
您已使用 FHIR Engine 程式庫管理應用程式中的 FHIR 資源:
- 使用 Sync API 將 FHIR 資源與 FHIR 伺服器同步
- 使用 Data Access API 建立、讀取、更新及刪除本機 FHIR 資源
- 使用 Search API 搜尋本機 FHIR 資源
涵蓋內容
- 如何設定本機 HAPI FHIR 伺服器
- 如何將測試資料上傳至本機 HAPI FHIR 伺服器
- 如何使用 FHIR Engine Library 建構 Android 應用程式
- 如何在 FHIR Engine 程式庫中使用 Sync API、Data Access API 和 Search API
後續步驟
- 探索 FHIR Engine 程式庫的說明文件
- 探索 Search API 的進階功能
- 在自有 Android 應用程式中套用 FHIR Engine 程式庫