ResearchDroid: An Android Forms and Consent Library

by Mir Suhail

Overview

ResearchDroid is a port of Apple’s ResearchKit for the Android platform. It is actually an android library developed for automating survey forms and information consent building process. The initial launch of ResearchDroid was announced on Nov 9, 2015 at the mHealth conference. ResearchDroid is highly useful in developing health apps, for getting patient consent, and conducting surveys (whether it is demographic or any other survey). To demonstrate the full capabilities of ResearchDroid library, we launched a step-count study in February 2016 on both Android and iOS platforms that leverages ResearchKit features to quickly build a study app –America Walks Study. The app leverages mobile phone’s step count sensor technology to automatically determine participants’ daily walking activity, thus being the first research study to measure such activity using mobile phones, instead of self reported surveys, pedometers or tracking devices.

Features Of ResearchDroid

  • Create informed Consent Using Json File
    • Create Consent Pages
    • Swipeable  Views
    • Indicator to show progress of consent
  • Create Surveys Forms Using Json File
    • Creating Form Fields
    • Validating Form Fields
    • Wizard form (page by page)
    • Create signature field for getting user’s consent or any other doc signed
  • UI:
    • Material Design UI
    • ResearchKit like UI
    • Override style as per own specifications

Getting Started

ResearchDroid acts as a machinery in which we feed specific structured json files and in return we get either the consent pages or survey form wizard. You as a developer do not need to create separate pages for each new informed consent heading or the newly added survey form question/questions.

 

researchdroid

Adding Dependency

In order to use researchdroid library and start exploring its features, you have to first get researchdroid.aar file.  Contact us and we will send you the researchdroid.aar file. Store the file on your pc and, proceed as follows:

  1. Add the researchdroid.aar (compiled AAR  file) to your project:
    1. Click File > New Module.
    2. Click Import .JAR/.AAR Package then click Next.
    3. Enter the location of the AAR or JAR file then click Finish.
  2. Make sure the library is listed at the top of your settings.gradle file, as shown here for a library named “my-library-module”:
    include ':app', ':researchdroid'
  3. Open the app module’s build.gradle file and add a new line to the dependencies block as shown in the following snippet:
    dependencies {
        compile project(":researchdroid")
    }
  4. In addition, add the following dependencies also to the app module’s build.gradle file inside dependencies block as shown below:
    dependencies {
        compile 'com.github.rey5137:material:1.1.0'
        compile 'com.rengwuxian.materialedittext:library:2.1.4'
        compile('com.github.ganfra:material-spinner:1.1.1') {
            exclude group: 'com.nineoldandroids', module: 'library'
            exclude group: 'com.android.support', module: 'appcompat-v7'\
        }
    }
  5. Click Sync Project with Gradle Files.

After importing the library into your android package, you are ready to get your stuff done. Let’s see how you can create informed consent first and then form survey wizard.

Creating the Informed Consent

Let’s suppose you want to create informed consent swipeable views having two pages with title as follows:

  1. Data Gathering
  2. Data Privacy

First you need to create json file with the below specified format, which will contain all the information to be displayed on the screens. Below is the json file and we call it consent_screens.json.

{
 "app_identifier": "",
 "data": {
   "screens": [
     {
       "elements": [
         {
           "identifier": null,
           "properties": {
            “font_size”: “34”,
            “font_color”: “#000000”,
             "text_value": "Data Gathering"
           },
           "element": "title"
         },
         {
           "identifier": null,
           "properties": {
            “font_size”: “17”,
            “font_color”: “#000000”,
             "text_value":"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"
           },
           "element": "short_description"
         },
         {
           "identifier": null,
           "properties": {
            “font_size”: “17”,
            “font_color”: “#000000”,
             "text_value": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"
           },
           "element": "description"
         }
       ],
       "type": "consent_data_gathering",
       "id": 20,
       "order": 0
     },
     {
       "elements": [
         {
           "identifier": null,
           "properties": {
            “font_size”: “34”,
            “font_color”: “#000000”,
             "text_value": "Data Privacy"
           },
           "element": "title"
         },
         {
           "identifier": null,
           "properties": {
            “font_size”: “17”,
            “font_color”: “#000000”,
             "text_value":"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"
           },
           "element": "short_description"
         },
         {
           "identifier": null,
           "properties": {
            “font_size”: “17”,
            “font_color”: “#000000”,
             "text_value":"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"
           },
           "element": "description"
         }
       ],
       "type": "consent_privacy",
       "id": 21,
       "order": 15
     }
   ]
 }
}

The above file is to passed to the library’s ConsentActivity.java as an intent parameter as follows:

 

   public static int  CONSENT_REQUEST_CODE=1;
   String json;

public void startConsent(){
   json = loadJSONFromAsset(getApplicationContext(), "consent_screens.json");
   /*Calling the ResearchDroid’s Consent Activity()*/
   Log.i(Constants.TAG, "Starting Consent Activity");
   Intent intent = new Intent(ConsentControllerActivity.this, ConsentActivity.class);
   intent.putExtra(Constants.INTENT_JSON, json);
   startActivityForResult(intent, CONSENT_REQUEST_CODE);
}

Note: We use the method startActivityForResult() instead of simple startActivity(). The reason being that when user is done with the subsequent activity and returns, the system calls your calling activity’s onActivityResult() method. This means that we can know whether user has cancelled the activity midway or carried on all the way. This method includes three arguments:

  • The request code you passed to startActivityForResult().
  • A result code specified by the second activity. This is either RESULT_OK if the operation was successful or RESULT_CANCELED if the user backed out or the operation failed for some reason.
  • An Intent that carries the result data.

When the ConsentActivity() is called, it fetches the json string from the intent object, reconverts it into jsonObject, iterates through this JsonObject, fetches the JsonArray with key “screens”. Each entry in JsonArray gets converted into the informed consent page/screen. An informed consent page has three main parts:

  1. Page Title
  2. Short Description
  3. Long Description

Note: Long description is by default hidden from page and gets visible only after pressing the Learn more link.

Each JsonArray entry  with key “screens” itself contains a JsonArray with key “elements”. This JsonArray has three JsonObjects for each of the three parts of screen.

After ResearchDroid’s ConsentActivity finishes, it returns and we get the response in the calling activity’s onActivityResult() method, and we can handle the cases accordingly. Below is the code snippet:

 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (resultCode == RESULT_OK){
      //This means activity is successfully finished. Next do your stuff here
   }
   if (resultCode == RESULT_CANCELED){
     //Activity got cancelled. Handle the code here
       try{
           String result_data = null;
           result_data = data.getStringExtra(Constants.ACTIVITY_STATUS);
           if (result_data.equals(Constants.RESULT_DISAGREE) ){
           }
           else if (result_data.equals(Constants.RESULT_NO_CONSENT_SCREENS)){
           }
           else if (result_data.equals(Constants.RESULT_CANCEL)){
           }
           else{
           }
       }catch (Exception e){
           e.printStackTrace();
       }
   }
   super.onActivityResult(requestCode, resultCode, data);
}

In addition to the above screens/pages, one more page called review gets created which summarises all information in a single place. This also contains two buttons for Agree/ Disagree for consent. If user clicks Agree, the activity returns RESULT_OK status. On clicking Disagree, activity returns RESULT_CANCELED status with return parameter Constants.RESULT_DISAGREE.

 researchkit android

 

Creating the Survey Form Fields

After the user agrees or gives consent, you can either navigate them to consent confirmation, where user enters their basic details like first name, last name and email id. After this, user is required to draw/write their signature on the screen, or user is directly taken to survey forms. In either of the cases, we must call ResearchDroid’s JsonFormActivity.  Following are the various fields/widgets which we can create with JsonFromActivity:

  1. Dropdown/Spinner Field
  2. Checkbox Field
  3. Radio Buttons Field
  4. Label or Text view
  5. Text Input/ Edit Text (It has sub categories)
       Simple Input Field
       Integer Field
       Email Field
       Password Field
  6. Signature/Drawing Field

Each field is created by passing a JsonObject. This JsonObject contains information about the display type of the field, label text, validation (is required) etc. Below is the format of JsonObject to be used for generating single form field.

{
 "show_question": true,
 "title": "Enter your gender",
 "order": 1,
 "display_type": "dropdown",
 "is_required": true,
 "id": 46,
 "options": [
   {
     "display_name": "male",
     "is_expected_value": false,
     "value": "male",
     "id": 83,
     "order": 0
   },
   {
     "display_name": "female",
     "is_expected_value": false,
     "value": "female",
     "id": 84,
     "order": 1
   },
   {
     "display_name": "other",
     "is_expected_value": false,
     "value": "other",
     "id": 85,
     "order": 2
   }
 ]
}

I will try to explain some of the keys in this JsonObject.

 

Key Features
show_question This depicts whether to show the question label or not. It takes Boolean value e.g true.
name Name of the question field. This is not displayed. It can be empty.
display_type This is important and required. It tells which field will be created out of this object e.g: if we set display_type : checkbox, a checkbox field will be created. Similarly radio for radio buttons, dropdown for Dropdown items, email for Email field, password for Password field, text for simple Input text, integer for Numerical fields and signature for Signature/Drawing field.
is_required This is the validation key. For required fields, is_required is set to true.
id This is the unique id for each question item.
options For input type fields, this field can be either empty or absent and is only important for multi-value questions like checkbox, radio buttons, and dropdown. This is a JsonArray of JsonObjects. Each JsonObject is a single entry/option in the field which contains the following entries. Each JsonObject has following entries,

  • display_name : Label of the option
  • value: Corresponding value of that option
  • Is_expected_value : If this is set to true, it means that user has to anyhow select this value. This is useful in checking eligibility criteria
  • Id : Inique id of the option
  • order : Order of display of the item

The above shown JsonObject would create a single question in the wizard. Let’s see the full json file to be passed to JsonFormActivity and the code snippet and how it is passed.

Below is the Json file called profile_survey.json

 

{
 "app_identifier": "",
 "data": {
   "surveys": [
     {
       "type": "Profile",
       "id": 27,
       "questions": [
         {
           "show_question": true,
           "name": "",
           "title": "Enter your name",
           "sub_title": null,
           "display_params": null,
           "question_survey": 46,
           "order": 1,
           "children": null,
           "options": [
           ],
           "display_type": "edit_text",
           "is_required": true,
           "id": 46
         },
         {
           "show_question": true,
           "name": "",
           "title": "enter your zip code",
           "sub_title": null,
           "display_params": null,
           "question_survey": 47,
           "order": 1,
           "children": null,
           "options": [

           ],
           "display_type": "integer",
           "is_required": true,
           "id": 47
         }
       ],
       "title": "Profile"
     }
   ]
 },
 "generated_on": "2016-09-27T07:09:14.757816"
}

Here is the code snippet for reading this json file and passing the same to JsonFormActivity.

public int SURVEY_CODE = 11;
public void startForms(){
    /*Calling the Form Activity */
   String json =loadJSONFromAsset(this, "profile_survey.json");
   String survey_json = null;
   Log.i(Constants.TAG, "Starting Form Activity");
   try {
       JSONObject Surveyjson = new JSONObject(json);
       JSONObject e = Surveyjson.getJSONObject("data");
       JSONArray dataArray = e.getJSONArray("surveys");
       JSONObject survey = dataArray.getJSONObject(0);
       survey_json = String.valueOf(survey);
   } catch (JSONException e) {
       e.printStackTrace();
   }
   Intent intent = new Intent(SurveyControllerActivity.this, JsonFormActivity.class);
   if (survey_json != null){
       intent.putExtra(Constants.INTENT_SURVEY_JSON, survey_json);
       startActivityForResult(intent, SURVEY_CODE);
   }else{
       Log.i(Constants.TAG, "Survey JSON is null");
   }
}

With the above code snippet and json file, survey form of two pages with one question each will be created. The validation of each field is done by the library itself on clicking ‘Next’ button at the bottom of the page. When the user finishes filling information in the form and clicks ‘Submit’ button at the last page, the activity finishes with RESULT_OK status and control reaches the onActivityResult() method of calling activity along with the filled information in the form of key value pair where key is the id of the question and value is the entered value. Below is the code snippet for this

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (resultCode == Activity.RESULT_OK){
       HashMap<String, String> surveyDataReceived = (HashMap<String, String>) data.getSerializableExtra("data");
       Log.i(TAG, String.valueOf(surveyDataReceived));
       //write 
   }
   if (resultCode == Activity.RESULT_CANCELED) {
       //write 
   }
   super.onActivityResult(requestCode, resultCode, data);
}

Returned data format:

{zip_code=10011, name=Mir Suhail}

Note: the signature/drawing data is returned in the form of base_64 format .

 

researchdroid applied

 

This way we are able to generate consent screens and form pages without extra effort every time while adding a new question or consent page.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

Mobile Research Apps

We have deep expertise in design and development of mobile research apps that work on both iOS and Android securely.

Contact us now

Popular Posts