1. Antes de começar
O que você vai criar
Neste codelab, você vai criar um app Android usando a biblioteca FHIR Engine. Seu app vai usar a biblioteca FHIR Engine para fazer o download de recursos FHIR de um servidor FHIR e fazer o upload de 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 FHIR Engine ao seu app Android
- Como usar a API Sync para configurar um job único ou periódico para fazer o download e upload de recursos FHIR
- Como usar a API Search
- Como usar as APIs Data Access para criar, ler, atualizar e excluir recursos 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)
- Android Emulator ou um dispositivo Android físico com o Android 7.0 Nougat ou mais recente
- Exemplo de código
- Conhecimento básico de desenvolvimento Android em Kotlin
Se você nunca criou apps Android antes, comece criando seu primeiro app.
2. Configurar um servidor HAPI FHIR local com dados de teste
HAPI FHIR é um servidor FHIR de código aberto conhecido. Usamos um servidor HAPI FHIR local no nosso codelab para que o app Android se conecte.
Configurar o servidor HAPI FHIR local
- Execute o comando a seguir 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
hapiproject/hapitransferida por download anteriormente ou executando o comando a seguir Saiba mais.docker run -p 8080:8080 hapiproject/hapi:latest - Inspecione o servidor abrindo o URL
http://localhost:8080/em um navegador. Você verá a interface da Web do HAPI FHIR.
Preencher o servidor HAPI FHIR local com dados de teste
Para testar nosso aplicativo, precisamos de alguns dados de teste no servidor. Vamos usar dados sintéticos gerados pelo Synthea.
- Primeiro, precisamos fazer o download dos dados de amostra 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 o upload de dados de teste para três pacientes no servidor HAPI FHIR local. Execute o comando a seguir no diretório que contém 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 o upload de dados de teste para todos os pacientes no 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. Você verá o textoHTTP 200 OKe a seçãoResponse Bodyda página contendo dados do paciente em um pacote FHIR como resultado da pesquisa com uma contagemtotal.
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/ohs-foundation/android-fhir.git
O projeto inicial deste 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ê transferiu por download anteriormente.

Sincronizar o projeto com arquivos do Gradle
Para sua conveniência, as dependências da biblioteca FHIR Engine já foram adicionadas ao projeto. Isso permite integrar a biblioteca FHIR Engine ao seu app. Observe as linhas a seguir até o final do arquivo app/build.gradle.kts do seu 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 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 Run (
) na barra de ferramentas do Android Studio.

4. Criar instância do FHIR Engine
Para incorporar o FHIR Engine ao seu app Android, você precisa usar a biblioteca FHIR Engine e iniciar uma instância do FHIR Engine. As etapas descritas abaixo vão orientar você no processo.
- Navegue até a classe do aplicativo, que neste exemplo é
FhirApplication.kt, localizada emapp/src/main/java/com/google/android/fhir/codelabs/engine. - No método
onCreate(), adicione o código a seguir para inicializar o FHIR Engine: Observações: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: ativa a criptografia de dados se o dispositivo a oferecer.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: esse é o URL de base do servidor FHIR. O endereço IP fornecido10.0.2.2é reservado especialmente para localhost, acessível no emulador do Android. Saiba mais.
- Na classe
FhirApplication, adicione a linha a seguir para instanciar o FHIR Engine de forma lenta: Isso garante que a instância do FhirEngine só seja criada quando for acessada pela primeira vez, não imediatamente quando o app for iniciado.private val fhirEngine: FhirEngine by lazy { FhirEngineProvider.getInstance(this) } - Adicione o método de conveniência a seguir na 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 no app usando o contexto.companion object { fun fhirEngine(context: Context) = (context.applicationContext as FhirApplication).fhirEngine }
5. Sincronizar dados com o servidor FHIR
- Crie uma nova classe
DownloadWorkManagerImpl.kt. Nessa 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 fazer o download. Ela 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 será sincronizado com o servidor FHIR remoto usando um worker em segundo plano. Aqui, definimos qual gerenciador de downloads, resolvedor de conflitos e instância do FHIR Engine 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, ela 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 brinde 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, você verá os pacientes do seu servidor FHIR local sendo transferidos por download e exibidos no aplicativo.

6. Modificar e fazer o upload de dados do paciente
Nesta seção, vamos orientar você no processo de modificação dos dados do paciente com base em critérios específicos e fazer o upload dos dados atualizados para o servidor FHIR. Especificamente, vamos trocar as cidades de endereço dos pacientes que residem em Wakefield e Taunton.
Etapa 1: configurar a lógica de modificação no 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 FHIR Engine.viewModelScope.launch { val fhirEngine = FhirApplication.fhirEngine(getApplication()) - Pesquisar pacientes de Wakefield:use o FHIR Engine para pesquisar pacientes com uma cidade de endereço de
Wakefield. Aqui, estamos usando o métodoval patientsFromWakefield = fhirEngine.search<Patient> { filter( Patient.ADDRESS_CITY, { modifier = StringFilterModifier.MATCHES_EXACTLY value = "Wakefield" } ) }searchdo FHIR Engine 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 de
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:analise cada paciente na lista
patientsFromWakefield, mude a cidade paraTauntone atualize-os no FHIR Engine. 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 a 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 final da corrotina iniciada no começo.
Etapa 2: testar a funcionalidade
- Teste de interface:execute o app. Clique no botão
Updateno menu. Você verá as cidades de endereço dos pacientesAaron697eAbby752trocadas. - Verificação do servidor:abra um navegador e navegue até
http://localhost:8080/fhir/Patient/. Verifique se a cidade de endereço dos pacientesAaron697eAbby752está atualizada no servidor FHIR local.
Seguindo estas etapas, você implementou um mecanismo para modificar os dados do paciente e sincronizar as mudanças com o servidor FHIR.
7. Pesquisar pacientes pelo nome
A pesquisa de pacientes pelos nomes pode oferecer uma maneira fácil de usar para recuperar informações. Aqui, vamos orientar você no 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 a atualização da interface, incorpore o bloco de código condicional a seguir:
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 o 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
- Reiniciar 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 de um nome) para filtrar a lista de pacientes de acordo com ele.
Com essas etapas concluídas, você aprimorou seu aplicativo, oferecendo aos usuários a capacidade de pesquisar pacientes com eficiência 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:
- Use a API Sync para sincronizar recursos FHIR com um servidor FHIR
- Use a API Data Access para criar, ler, atualizar e excluir recursos FHIR locais
- Use a API Search para pesquisar recursos FHIR locais
O que aprendemos
- Como configurar um servidor HAPI FHIR local
- Como fazer o 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 FHIR Engine
Próximas etapas
- Confira a documentação da biblioteca FHIR Engine
- Confira os recursos avançados da API Search
- Aplique a biblioteca FHIR Engine no seu próprio app Android