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 模擬器或搭載 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 程式庫依附元件已新增至專案。這樣一來,您就能在應用程式中整合 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 執行個體
如要在 Android 應用程式中加入 FHIR Engine,您需要使用 FHIR Engine 程式庫,並啟動 FHIR Engine 的執行個體。請按照下列步驟完成程序。
- 前往您的 Application 類別,在本範例中為
FhirApplication.kt,位於app/src/main/java/com/google/android/fhir/codelabs/engine中。 - 在
onCreate()方法中新增下列程式碼,初始化 FHIR Engine: 注意: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:決定資料庫錯誤策略。如果開啟時發生錯誤,系統會重新建立資料庫。baseUrlinServerConfiguration:這是 FHIR 伺服器的基準網址。提供的 IP 位址10.0.2.2是專為 localhost 保留,可從 Android 模擬器存取。瞭解詳情。
- 在
FhirApplication類別中,新增下列程式碼行,以延遲例項化 FHIR Engine: 這可確保 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函式的主體: 在這裡,同步程序完成後,系統會顯示通知使用者的訊息,然後應用程式會叫用空白名稱的搜尋,顯示所有病患。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()) - 搜尋來自韋克菲爾德的病患:使用 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 程式庫建構 Android 應用程式
- 如何在 FHIR Engine 程式庫中使用 Sync API、Data Access API 和 Search API
後續步驟
- 探索 FHIR Engine 程式庫的說明文件
- 探索 Search API 的進階功能
- 在自己的 Android 應用程式中套用 FHIR Engine 程式庫