Introduction

AWARE plugins have many uses. In a nutshell, they are extensions that allow developers to implement custom code leveraging the other offered sensors, or even other plugins. A plugin may refine context offered by other sensors, thus providing new type of perhaps more accurate or more human readable context. Basically, when you need custom code and logic for your study, or custom user interfaces, you’ll need to create an AWARE plugin.

1. Downloading the template AWARE plugin project

You can find a ready-to-deploy template plugin project in GitHub: here. On that page, you’ll need to download the project:

screen-shot-2016-11-08-at-9-54-39

2. Importing project to Android Studio

Extract this zip file to a folder. We’ll refer to this folder as TEMPLATE_FOLDER. Now we’ll import this project into Android Studio. Android Studio has a few quirks (i.e., bugs) which eventually will be resolved by Google when importing/adding a new project from existing source. Open up Android Studio and choose “Open an existing Android Studio project”:

screen-shot-2016-11-08-at-11-02-34

Browse to the TEMPLATE_FOLDER. You’ll notice the TEMPLATE_FOLDER will have the Android Studio icon, hence it is being recognised as a valid Android Studio project:

screen-shot-2016-11-08-at-11-04-22

Press OK and Android Studio will start loading the project. Gradle also needs to be up-to-date. If it’s not, you get a request like this:

screen-shot-2016-11-08-at-11-07-10

Press Update. After this step, Android Studio loads the project. At this point, Android Studio will request any missing libraries, updates, etc that may be required. The import will be seamless if you have an up-to-date Android Studio + Android SDK libraries. Once all the dependencies are installed (simply follow Android Studio instructions), the plugin project is ready for editing.

3. Tell Android Studio that it’s OK to have an application that does not have an Activity!

Before we can install the plugin on the mobile phone, we need to change the deployment configuration of the project because Android Studio expects valid applications to have an activity on the application launcher of your smartphone. The AWARE Client is listening for the installation of “com.aware.plugin.*” packages, and automatically initiates a newly installed plugin. So we need to tell Android Studio not to worry about launching the application. You do so in Edit configurations, as follow:

screen-shot-2016-11-08-at-11-18-41 screen-shot-2016-11-08-at-11-19-13

Press OK.

4. Disable Instant Run for AWARE Plugin development.

Instant Run is great. However, it interferes with how AWARE Client loads resources that are present in a different package than its own (plugin architecture). In a nutshell, if instant run is active, when you install the package on the phone, the class names get a randomly generated class name. This means the client won’t know what to initiate when the plugin is installed, so class instantiation won’t work properly. To disable Instant Run, you need to change Android Studio preferences:

screen-shot-2016-11-08-at-11-27-41

5. Installing the plugin!

You can now press the Run button (the screen-shot-2016-11-08-at-11-21-03 button on the menu). That will trigger the project build. If everything is OK, the Android package is installed on your phone. AWARE Client detects this event and starts your plugin, automatically. Since Marshmallow, permissions need to be explicitly granted per package. AWARE handles semi-automatically the requests for permissions – you still need to declare them on the manifest and inside onCreate of the Plugin.java class. You get this following prompt on your device (Android 6.x or higher):

device-2016-11-08-113010

Access to the storage space is mandatory to every plugin, otherwise we could not read existing data, save new data, etc. As such, any plugin automatically has this permission as default in the REQUIRED_PERMISSIONS variable on the Plugin.java class.

You can check the “Stream” to find your plugin running:

device-2016-11-08-114157

If you are just running the template project, without any changes, you will see a counter:

device-2016-11-08-113457

This shows the ContextCard.java output (it’s a simple View). It’s here you can summarize and visualise the data your plugin may collect. It serves to also to inform the usefulness of the plugin’s collected data. On the right, pressing the (…), takes you to the Settings.java interface, where plugin’s parameters can be changed. Depending on the plugin, you get a different set of parameters.

If you already have other plugins installed and running, you will see all the active plugins:

screenshot_20161017-193911

New plugins can be installed from the Play Store using “Plugins” from the left-sided menu on the AWARE Client. If you publish your plugin on the Play Store, it will be listed too. So, what are you building? 🙂

6. Modifying the template: showing a questionnaire every day at 8AM and another one at 9PM.

6.1 Renaming the package name

First we need to change the package name to something other than com.aware.plugin.template. Right-click the package folder on the left and choose Refactor (alternatively, selecting the folder and pressing Shift-F6):

screen-shot-2016-11-08-at-11-48-10

You will get a prompt asking if you are renaming the directory or the package:

screen-shot-2016-11-08-at-11-49-33

Choose “Rename package” to something valid (no spaces, no uppercases, no special characters except underscore _ ), e.g., daily_survey. Also make sure to select “Search in comments and strings” and “Search for text occurrences”:

screen-shot-2016-11-08-at-11-51-15

Android Studio will now show on the bottom of the screen a list of proposed changes. Press “Do Refactor”:

screen-shot-2016-11-08-at-11-53-58

6.2 Renaming the plugin name

You can change the plugin name by editing the file inside res/values/strings.xml, the app_name value:

screen-shot-2016-11-08-at-11-57-33

6.3 Making the questionnaire

For this example, we are extending the Plugin.java class to:

  • Ask AWARE to initiate the ESM functionality
  • Create a questionnaire using the ESM Factory
  • Schedule the questionnaire using the Scheduler functionality

The final code of onStartCommand() looks as follow:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (PERMISSIONS_OK) {
            //Check if the user has toggled the debug messages
            DEBUG = Aware.getSetting(this, Aware_Preferences.DEBUG_FLAG).equals("true");

            //Initialize our plugin's settings
            Aware.setSetting(this, Settings.STATUS_PLUGIN_TEMPLATE, true);

            //Ask AWARE to start ESM
            Aware.setSetting(this, Aware_Preferences.STATUS_ESM, true);

            //Setting morning question
            try {
                //Using PAM to get users' affect state in the morning
                ESMFactory esmFactory = new ESMFactory();

                ESM_PAM morning_question = new ESM_PAM();
                morning_question.setTitle("Morning!")
                        .setInstructions("How are you feeling today?")
                        .setExpirationThreshold(0) //no expiration = shows a notification the user can use to answer at any time
                        .setNotificationTimeout(5 * 60) //the notification is automatically removed and the questionnaire expired after 5 minutes ( 5 * 60 seconds)
                        .setSubmitButton("OK");

                esmFactory.addESM(morning_question);

                //Schedule this question for the morning, only if not yet defined
                Scheduler.Schedule morning = Scheduler.getSchedule(this, "morning_question");
                if (morning == null) {
                    morning = new Scheduler.Schedule("morning_question"); //schedule with morning_question as ID
                    morning.addHour(8); //8 AM (24h format), every day
                    morning.setActionType(Scheduler.ACTION_TYPE_BROADCAST); //sending a request to the client via broadcast
                    morning.setActionIntentAction(ESM.ACTION_AWARE_QUEUE_ESM); //with the action of ACTION_AWARE_QUEUE_ESM, i.e., queueing a new ESM
                    morning.addActionExtra(ESM.EXTRA_ESM, esmFactory.build()); //add the questions from the factory

                    Scheduler.saveSchedule(this, morning); //save the questionnaire and schedule it
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            //Setting evening question
            try {
                //Using Likert scale to get users' rating of the day
                ESMFactory esmFactory = new ESMFactory();

                ESM_Likert evening_question = new ESM_Likert();
                evening_question.setLikertMax(5)
                        .setLikertMinLabel("Awful")
                        .setLikertMaxLabel("Awesome!")
                        .setLikertStep(1)
                        .setTitle("Evening!")
                        .setInstructions("How would you rate today?")
                        .setExpirationThreshold(0) //no expiration = shows a notification the user can use to answer at any time
                        .setNotificationTimeout(5 * 60) //the notification is automatically removed and the questionnaire expired after 5 minutes ( 5 * 60 seconds)
                        .setSubmitButton("OK");

                esmFactory.addESM(evening_question);

                //Schedule this question for the evening, only if not yet defined
                Scheduler.Schedule evening = Scheduler.getSchedule(this, "evening_question");
                if (evening == null) {
                    evening = new Scheduler.Schedule("evening_question"); //schedule with morning_question as ID
                    evening.addHour(20); //8 PM (24h format), every day
                    evening.setActionType(Scheduler.ACTION_TYPE_BROADCAST); //sending a request to the client via broadcast
                    evening.setActionIntentAction(ESM.ACTION_AWARE_QUEUE_ESM); //with the action of ACTION_AWARE_QUEUE_ESM, i.e., queueing a new ESM
                    evening.addActionExtra(ESM.EXTRA_ESM, esmFactory.build()); //add the questions from the factory

                    Scheduler.saveSchedule(this, evening); //save the questionnaire and schedule it
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            
            Aware.startAWARE(this); //bind to the framework
        }

        return START_STICKY;
    }

 

 

 

Creating a new AWARE Plugin