1. Antes de começar
O que você vai criar
Neste codelab, você vai criar um app Android usando a biblioteca do FHIR Engine. Seu app vai usar a biblioteca FHIR Engine para fazer o download de recursos FHIR de um servidor FHIR e enviar mudanças locais para o servidor.
O que você vai aprender
- Como criar um servidor HAPI FHIR local usando o Docker
- Como integrar a biblioteca do FHIR Engine ao seu app Android
- Como usar a API Sync para configurar um job único ou periódico para fazer download e upload de recursos do FHIR
- Como usar a API Search
- Como usar as APIs de acesso a dados para criar, ler, atualizar e excluir recursos do FHIR localmente
O que é necessário
- Docker (fazer o download do Docker)
- Uma versão recente do Android Studio (v4.1.2 ou mais recente)
- Um Android Emulator ou um dispositivo Android físico com o Android 7.0 Nougat ou mais recente
- Código de amostra
- Conhecimento básico de desenvolvimento para Android em Kotlin.
Se você nunca criou apps Android, comece criando seu primeiro app.
2. Configurar um servidor HAPI FHIR local com dados de teste
O HAPI FHIR é um servidor FHIR de código aberto conhecido. Usamos um servidor HAPI FHIR local no nosso codelab para o app Android se conectar.
Configurar o servidor HAPI FHIR local
- Execute o seguinte comando em um terminal para receber a imagem mais recente do HAPI FHIR:
docker pull hapiproject/hapi:latest - Crie um contêiner HAPI FHIR usando o Docker Desktop para executar a imagem baixada anteriormente
hapiproject/hapiou executando o seguinte comando: Saiba mais.docker run -p 8080:8080 hapiproject/hapi:latest - Abra o URL
http://localhost:8080/em um navegador para inspecionar o servidor. A interface da Web do HAPI FHIR vai aparecer.
Preencher o servidor HAPI FHIR local com dados de teste
Para testar o aplicativo, precisamos de alguns dados de teste no servidor. Vamos usar dados sintéticos gerados pelo Synthea.
- Primeiro, faça o download dos dados de exemplo de synthea-samples. Faça o download e extraia
synthea_sample_data_fhir_r4_sep2019.zip. Os dados de amostra descompactados têm vários arquivos.json, cada um sendo um pacote de transações para um paciente individual. - Vamos fazer upload de dados de teste de três pacientes para o servidor HAPI FHIR local. Execute o comando a seguir no diretório que contém os arquivos 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/ - Para fazer upload dos dados de teste de todos os pacientes para o servidor, execute
No entanto, isso pode levar muito tempo para ser concluído e não é necessário para o codelab.for f in *.json; do curl -X POST -H "Content-Type: application/json" -d @$f http://localhost:8080/fhir/ ; done - Verifique se os dados de teste estão disponíveis no servidor abrindo o URL
http://localhost:8080/fhir/Patient/em um navegador. O textoHTTP 200 OKe a seçãoResponse Bodyda página com dados de pacientes em um pacote FHIR vão aparecer como resultado da pesquisa com uma contagem detotal.
3. Configurar o app Android
Fazer o download do código
Para fazer o download do código deste codelab, clone o repositório do SDK FHIR Android: git clone https://github.com/google/android-fhir.git
O projeto inicial para este codelab está localizado em codelabs/engine.
Importar o app para o Android Studio
Começamos importando o app inicial para o Android Studio.
Abra o Android Studio, selecione Import Project (Gradle, Eclipse ADT, etc.) e escolha a pasta codelabs/engine/ no código-fonte que você baixou anteriormente.

Sincronizar o projeto com arquivos do Gradle
Para sua conveniência, as dependências da biblioteca do FHIR Engine já foram adicionadas ao projeto. Isso permite integrar a biblioteca FHIR Engine ao seu app. Observe as seguintes linhas até o final do arquivo app/build.gradle.kts do projeto:
dependencies {
// ...
implementation("com.google.android.fhir:engine:1.1.0")
}
Para garantir que todas as dependências estejam disponíveis para seu app, sincronize o projeto com os arquivos do Gradle neste momento.
Selecione Sync Project with Gradle Files (
) na barra de ferramentas do Android Studio. Você também pode executar o app novamente para verificar se as dependências estão funcionando corretamente.
Executar o app inicial
Agora que você importou o projeto para o Android Studio, está tudo pronto para executar o app pela primeira vez.
Inicie o emulador do Android Studio e clique em Executar (
) na barra de ferramentas do Android Studio.

4. Criar uma instância do FHIR Engine
Para incorporar o FHIR Engine ao seu app Android, use a biblioteca do FHIR Engine e inicie uma instância dele. As etapas descritas abaixo vão orientar você nesse processo.
- Navegue até a classe Application, que neste exemplo é
FhirApplication.kt, localizada emapp/src/main/java/com/google/android/fhir/codelabs/engine. - No método
onCreate(), adicione o seguinte código para inicializar o FHIR Engine: ObservaçõesFhirEngineProvider.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: ativa a criptografia de dados se o dispositivo for compatível.RECREATE_AT_OPEN: determina a estratégia de erro do banco de dados. Nesse caso, ele recria o banco de dados se ocorrer um erro ao abrir.baseUrlemServerConfiguration: é o URL de base do servidor FHIR. O endereço IP10.0.2.2fornecido é reservado especialmente para localhost, acessível pelo emulador do Android. Saiba mais.
- Na classe
FhirApplication, adicione a seguinte linha para instanciar o FHIR Engine de forma lenta: Isso garante que a instância do FhirEngine seja criada apenas quando for acessada pela primeira vez, e não imediatamente quando o app for iniciado.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Adicione o seguinte método de conveniência à classe
FhirApplicationpara facilitar o acesso em todo o aplicativo: Esse método estático permite recuperar a instância do FHIR Engine de qualquer lugar do app usando o contexto.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Sincronizar dados com o servidor FHIR
- Crie uma classe
DownloadWorkManagerImpl.kt. Nesta classe, você vai definir como o aplicativo busca o próximo recurso da lista para fazer o download: Essa classe tem uma fila de tipos de recursos que ela quer baixar. Ele processa respostas e extrai os recursos do pacote retornado, que são salvos no banco de dados local.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 } } - Crie uma nova classe
AppFhirSyncWorker.kt. Essa classe define como o app vai sincronizar com o servidor FHIR remoto usando um worker em segundo plano. Aqui, definimos qual gerenciador de downloads, resolvedor de conflitos e instância do mecanismo FHIR usar para a sincronização.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, ) } - No ViewModel,
PatientListViewModel.kt, você vai configurar um mecanismo de sincronização única. Localize e adicione este código à funçãotriggerOneTimeSync(): Essa corrotina inicia uma sincronização única com o servidor FHIR usando o AppFhirSyncWorker que definimos anteriormente. Em seguida, ele vai atualizar a interface com base no estado do processo de sincronização.viewModelScope.launch { Sync.oneTimeSync<AppFhirSyncWorker>(getApplication()) .shareIn(this, SharingStarted.Eagerly, 10) .collect { _pollState.emit(it) } } - No arquivo
PatientListFragment.kt, atualize o corpo da funçãohandleSyncJobStatus: Aqui, quando o processo de sincronização terminar, uma mensagem de toast será exibida notificando o usuário, e o app vai mostrar todos os pacientes invocando uma pesquisa com um nome vazio.when (syncJobStatus) { is SyncJobStatus.Finished -> { Toast.makeText(requireContext(), "Sync Finished", Toast.LENGTH_SHORT).show() viewModel.searchPatientsByName("") } else -> {} }
Agora que tudo está configurado, execute o app. Clique no botão Sync no menu. Se tudo funcionar corretamente, os pacientes do seu servidor FHIR local serão baixados e exibidos no aplicativo.

6. Modificar e fazer upload de dados de pacientes
Nesta seção, vamos orientar você no processo de modificação dos dados do paciente com base em critérios específicos e no upload dos dados atualizados para o servidor FHIR. Especificamente, vamos trocar as cidades de endereço dos pacientes que moram em Wakefield e Taunton.
Etapa 1: configurar a lógica de modificação em PatientListViewModel
O código nesta seção é adicionado à função triggerUpdate em PatientListViewModel.
- Acessar o FHIR Engine:comece recebendo uma referência ao FHIR Engine no
PatientListViewModel.kt. Esse código inicia uma corrotina no escopo do ViewModel e inicializa o mecanismo FHIR.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Pesquisar pacientes de Wakefield:use o mecanismo FHIR para pesquisar pacientes com uma cidade de endereço
Wakefield. Aqui, estamos usando o métodoval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchdo mecanismo FHIR para filtrar pacientes com base na cidade do endereço. O resultado será uma lista de pacientes de Wakefield. - Pesquisar pacientes de Taunton:da mesma forma, pesquise pacientes com uma cidade de endereço
Taunton. Agora temos duas listas de pacientes: uma de Wakefield e outra de Taunton.val patientsFromTaunton = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Taunton" } ) } - Modificar endereços de pacientes:acesse cada paciente na lista
patientsFromWakefield, mude a cidade paraTauntone atualize no mecanismo FHIR. Da mesma forma, atualize cada paciente na listapatientsFromWakefield.forEach { it.resource.address.first().city = "Taunton" fhirEngine.update(it.resource) }patientsFromTauntonpara que a cidade seja alterada paraWakefield.patientsFromTaunton.forEach { it.resource.address.first().city = "Wakefield" fhirEngine.update(it.resource) } - Iniciar sincronização:depois de modificar os dados localmente, acione uma sincronização única para garantir que os dados sejam atualizados no servidor FHIR.
A chave de fechamentotriggerOneTimeSync() }}indica o fim da corrotina iniciada no começo.
Etapa 2: testar a funcionalidade
- Teste de UI:execute o app. Clique no botão
Updateno menu. As cidades dos endereços dos pacientesAaron697eAbby752vão aparecer trocadas. - Verificação do servidor:abra um navegador e acesse
http://localhost:8080/fhir/Patient/. Verifique se a cidade do endereço dos pacientesAaron697eAbby752foi atualizada no servidor FHIR local.
Ao seguir estas etapas, você implementou um mecanismo para modificar os dados do paciente e sincronizar as mudanças com o servidor FHIR.
7. Pesquisar pacientes por nome
Pesquisar pacientes pelo nome pode ser uma maneira fácil de recuperar informações. Aqui, vamos mostrar o processo de implementação desse recurso no seu aplicativo.
Etapa 1: atualizar a assinatura da função
Navegue até o arquivo PatientListViewModel.kt e encontre a função chamada searchPatientsByName. Vamos adicionar código a essa função.
Para filtrar os resultados com base na consulta de nome fornecida e emitir os resultados para atualização da interface, incorpore o seguinte bloco de código condicional:
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 }
}
}
Aqui, se nameQuery não estiver vazio, a função de pesquisa vai filtrar os resultados para incluir apenas pacientes cujos nomes contenham a consulta especificada.
Etapa 2: testar a nova funcionalidade de pesquisa
- Reinicie o app:depois de fazer essas mudanças, recrie e execute o app.
- Pesquisar pacientes: na tela da lista de pacientes, use a funcionalidade de pesquisa. Agora você pode inserir um nome (ou parte dele) para filtrar a lista de pacientes.
Com essas etapas concluídas, você aprimorou seu aplicativo, oferecendo aos usuários a capacidade de pesquisar pacientes de forma eficiente pelos nomes. Isso pode melhorar significativamente a experiência do usuário e a eficiência na recuperação de dados.
8. Parabéns!
Você usou a biblioteca FHIR Engine para gerenciar recursos FHIR no seu app:
- Usar a API Sync para sincronizar recursos FHIR com um servidor FHIR
- Usar a API Data Access para criar, ler, atualizar e excluir recursos locais do FHIR
- Usar a API Search para pesquisar recursos FHIR locais
O que aprendemos
- Como configurar um servidor HAPI FHIR local
- Como fazer upload de dados de teste para o servidor HAPI FHIR local
- Como criar um app Android usando a biblioteca FHIR Engine
- Como usar a API Sync, a API Data Access e a API Search na biblioteca do FHIR Engine
Próximas etapas
- Confira a documentação da biblioteca do FHIR Engine
- Conheça os recursos avançados da API Search
- Aplicar a biblioteca FHIR Engine no seu próprio app Android