Skip to content

C3-PRO/c3-pro-demo-android

Repository files navigation

C3PRO Android Demo

C3PRO uses the HAPI FHIR library and ResearchStack in an attempt to bring the C3-PRO functionality to Android.

Combining 🔥 FHIR and ResearchStack, usually for data storage into i2b2, this framework allows you to use FHIR Questionnaire resources directly with a ResearchStack ViewTaskActivity and will return FHIR QuestionnaireResponse that you can send to your server.

Usage

This is a sample application, demonstrating how to use the C3PRO Android Framework. It is available here as a Android / Gradle Project. It can be inported in Android Studio by clicking "VCS" -> "Check out from Version Control" -> GitHub. The few things that need to be set up in order for a project to run with C3PRO are marked as TODOs. In this project they are all set up and should work out of the box.

To set up a new project using the C3PRO framework, the library is available on jCenter and can simply be added as a dependency:

dependencies {
    compile ('ch.usz.c3pro:c3-pro-android-framework:0.1.2'){
        exclude module: 'javax.servlet-api'
        exclude module: 'hapi-fhir-base'
    }

}

Some packages of third party dependencies need to be excluded to avoid duplicate class names.

#####The setup

The app has a class called C3PROApplication which is a subclass of Application and is set as the main application in the AndroidManifest. It seems that for now, multidex is needed to accomodate the large number of references in the library's dependencies. So it is necessary to enable Multidex in the application and the gradle build file. Most setup methods are found in the onCreate() method of the C3PROApplication class. The C3PRO class is initialized with the application's context and a FHIR Server URL. There are also some ResearchStack settings. More details about that can be found on the ResearchStack website.

The Applicationfile should look something like this:

public class C3PROApplication extends Application {

    /* with HAPI it seemed necessary to enable multidex to accomodate the large
    number of operations provided by the package. It seems to work without it now. Leaving it here
    for now just in case.*/
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        /**
         * Initialize C3PRO:
         * C3PRO will provide you with a FhirContext. This Object is expensive and you should
         * only have one instance in your app. Therefore, C3PRO will keep it as a singleton.
         * Access it by calling C3PRO.getFhirContext();
         * <p />
         * If you provide a context (your application) and an URL, C3PRO
         * will create a DataQueue for you to create and read Resources from your server in a
         * background thread.
         * */
        C3PRO.init(this, "http://fhirtest.uhn.ca/baseDstu3");

        // ResearchStack: Customize your pin code preferences
        PinCodeConfig pinCodeConfig = new PinCodeConfig(); // default pin config (4-digit, 1 min lockout)

        // ResearchStack: Customize encryption preferences
        EncryptionProvider encryptionProvider = new UnencryptedProvider(); // No pin, no encryption

        // ResearchStack: If you have special file handling needs, implement FileAccess
        FileAccess fileAccess = new SimpleFileAccess();

        // ResearchStack: If you have your own custom database, implement AppDatabase
        AppDatabase database = new DatabaseHelper(this,
                DatabaseHelper.DEFAULT_NAME,
                null,
                DatabaseHelper.DEFAULT_VERSION);

        StorageAccess.getInstance().init(pinCodeConfig, encryptionProvider, fileAccess, database);
    }
}

The AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ch.usz.c3pro.demo.android">

    <application
        android:name=".C3PROApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

The build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "ch.usz.c3pro.demo"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        // TODO: enabling multidex support.
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dexOptions {
        javaMaxHeapSize "3g"
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    // TODO: include C3PRO framework, but exclude some of the hapi library
    compile ('ch.usz.c3pro:c3-pro-android-framework:0.1.2'){
        exclude module: 'javax.servlet-api'
        exclude module: 'hapi-fhir-base'
    }
}
The C3PRO

Once set up (preferably in your Application class, so it survives the Activities' lifesycles), the C3PRO will provide you with a HAPI FhirContext and a DataQueue if you have provided a FHIR Server URL.

You can access it anywhere in your app code, for example to get a JsonParser:

C3PRO.getFhirContext().newJsonParser();

Or to upload a resource:

C3PRO.getDataQueue.create(resource);
The QuestionnaireFragment

Use the QuestionnaireFragment to represent a Questionnaire and conduct a Survey based on it.

    private void launchSurvey(Questionnaire questionnaire) {
        /**
         * Looking up if a fragment for the given questionnaire has been created earlier. if so,
         * the survey is started, assuming that the TaskViewActivity has been created before!!
         * The questionnaire IDs are used for identification, assuming they are unique.
         * */
        QuestionnaireFragment fragment = (QuestionnaireFragment) getSupportFragmentManager().findFragmentByTag(questionnaire.getId());
        if (fragment != null) {
            /**
             * If the fragment has been added before, the TaskViewActivity can be started directly,
             * assuming that it was prepared right after the fragment was created.
             * */
            fragment.startTaskViewActivity();
        } else {
            /**
             * If the fragment does not exist, create it, add it to the fragment manager and
             * let it prepare the TaskViewActivity
             * */
            final QuestionnaireFragment questionnaireFragment = new QuestionnaireFragment();
            questionnaireFragment.newInstance(questionnaire, new QuestionnaireFragment.QuestionnaireFragmentListener() {
                @Override
                public void whenTaskReady(String requestID) {
                    /**
                     * Only when the task is ready, the survey is started
                     * */
                    questionnaireFragment.startTaskViewActivity();
                }

                @Override
                public void whenCompleted(String requestID, QuestionnaireResponse questionnaireResponse) {
                    /**
                     * Where the response for a completed survey is received. Here it is printed
                     * to a TextView defined in the app layout.
                     * */
                    printQuestionnaireAnswers(questionnaireResponse);
                }

                @Override
                public void whenCancelledOrFailed(C3PROErrorCode code) {
                    /**
                     * If the task can not be prepared, a backup plan is needed.
                     * Here the fragment is removed from the FragmentManager so it can be created
                     * again later
                     * */
                    if (code == C3PROErrorCode.RESULT_CANCELLED) {
                        /**
                         * user just cancelled activity. do nothing
                         * */
                    } else {
                        /**
                         * If the task can not be prepared, a backup plan is needed.
                         * Here the fragment is removed from the FragmentManager so it can be created
                         * again later.
                         * */
                        Log.e(LTAG, code.toString());
                        getSupportFragmentManager().beginTransaction().remove(questionnaireFragment).commit();
                    }
                }
            });

            /**
             * In order for the fragment to get the context and be found later on, it has to be added
             * to the fragment manager.
             * */
            getSupportFragmentManager().beginTransaction().add(questionnaireFragment, questionnaire.getId()).commit();
            /**
             * prepare the TaskViewActivity. As defined above, it will start the survey once the
             * TaskViewActivity is ready.
             * */
            questionnaireFragment.prepareTaskViewActivity();
        }
    }

Versions

The library uses HAPI FHIR 1.5 for dstu3. Questionnaires in dstu2 (with group and question elements) will not work with this demo setup. Target Android sdk is 23, minimum sdk 16 due to ResearchStack.

Issues

Implementation is ongoing, not everything is complete and nothing has been systematically tested.

  • EnableWhen conditions have only been tested with boolean and singlechoice answertypes
  • No proper error handling implemented as of yet.

Modules

The framework will consist of several modules that complement each other, similar to the C3-PRO ios framework.

Questionnaires

Enables the conversion of a FHIR Questionnaire resource to a ResearchSTack task that can be presented to the user using a ViewTaskActivity and conversion back from a TaskResult to a FHIR QuestionnaireResponse resource.

DataQueue

This module provides a FHIR server implementation used to move FHIR resources, created on device, to a FHIR server, without the need for user interaction nor -confirmation.

Licence

This work will be Apache 2 licensed. A NOTICE.txt file will follow at some point, and don't forget to also add the licensing information of the submodules somewhere in your product:

About

Android Demo App for C3-PRO

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published