Getting Started
This page describes how to configure an Android Studio project to use the Structured Data Capture Library, and simple examples of how to use the library.
This guide is intended for developers who are familiar with basic Android development with Kotlin, and proficient in working with FHIR concepts and resources.
Dependencies
The Structured Data Capture Library is available through Google's Maven repository, which should be already configured for Android projects created in Android Studio 3.0 and higher.
Add the following dependencies to your module's app-level build.gradle
file, typically app/build.gradle
:
dependencies {
// ...
implementation 'com.google.android.fhir:data-capture:1.0.0'
implementation 'androidx.fragment:fragment-ktx:1.5.5'
}
The minimum API level supported is 24. The library also requires Android Gradle Plugin version 4.0.0 or later for Java 8+ API desugaring support.
The following examples assume you already have a FHIR questionnaire as a JSON file. If you need one, the FHIR specification has several examples like this one.
Display a Questionnaire
QuestionnaireFragment
is the interface for working with FHIR questionnaires, and also a fragment for rendering them. See the QuestionnaireFragment guide for details. To render a questionnaire in your app, follow these steps:
-
Add a
FragmentContainerView
to your activity's layout to contain the Questionnaire.```xml <?xml version="1.0" encoding="utf-8"?>
```
-
Create a bundle with the JSON questionnaire content for the fragment, in this case as a
String
read from a JSON file stored in theassets
folder.```kotlin // Small questionnaires can be read directly as a string, larger ones // should be passed as a URI instead. val questionnaireJsonString = application.assets.open("questionnaire.json") .bufferedReader().use { it.readText() }
val bundle = bundleOf( QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_STRING to questionnaireJsonString ) ```
-
Set the fragment to the
FragmentContainerView
.kotlin if (savedInstanceState == null) { supportFragmentManager.commit { setReorderingAllowed(true) add<QuestionnaireFragment>(R.id.fragment_container_view, args = bundle) } }
Get a QuestionnaireResponse
The getQuestionnaireResponse
function of QuestionnaireFragment
returns the current form answers in a FHIR QuestionnaireResponse, specifically as an instance of the HAPI FHIR Structures data model's QuestionnaireResponse. This provides a convenient interface to work with the data:
val fragment: QuestionnaireFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container_view) as QuestionnaireFragment
val questionnaireResponse = fragment.getQuestionnaireResponse()
// For example, convert the whole response to a string
val questionnaireResponseString = context.newJsonParser().encodeResourceToString(questionnaireResponse)
Log.d(
"response", questionnaireResponseString
)
This could be in a callback for the user after pressing a Submit button.
Extract FHIR Resources from a QuestionnaireResponse
ResourceMapper
converts data between a QuestionnaireResponse and other FHIR resources by implementing data extraction and population from the HL7 Structured Data Capture Implementation Guide. See the ResourceMapper guide for more information.
The Structured Data Capture Library supports two mechanisms for data extraction: Definition-based extraction and StuctureMap-based extraction.
Both methods require a Questionnaire
and corresponding QuestionnaireResponse
:
val jsonParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser()
val myQuestionnaire =
jsonParser.parseResource(questionnaireJson) as Questionnaire
// also need the QuestionnaireResponse, probably like this
val myQuestionnaireResponse = fragment.getQuestionnaireResponse()
For Definition-based extraction, just pass the Questionnaire
and QuestionnaireResponse
to ResourceMapper.extract()
.
lifecycle.coroutineScope.launch {
val bundle =
ResourceMapper.extract(questionnaire, questionnaireResponse)
}
StructureMap-based Extraction also requires a StructureMapExtractionContext
that contains the StructureMap. For example, if your StructureMap is written in the FHIR Mapping Language:
val mappingStr = "map ..."
lifecycle.coroutineScope.launch {
val bundle =
ResourceMapper.extract(
myQuestionnaire,
myQuestionnaireResponse,
StructureMapExtractionContext(context = applicationContext) { _, worker ->
StructureMapUtilities(worker).parse(mappingStr, "")
},
)
}
The extract
function is a suspend function, so these examples must be called from an appropriate coroutine.