Validic Mobile Library - Cordova plugin

Requirements

This plugin provides a bridge between a Cordova based application and native Validic Mobile libraries. The native libraries are required for use of this plugin.

Plugin requirements:

Prerequisites

The Cordova plugin requires the Validic Mobile native library be downloaded and the library files copied to the plugin prior to adding the plugin to a cordova project. Setting up SHealth and Healthkit also have special considerations.

Android

The native Android ValidicMobile libraries needs to be copied into the plugin before adding the plugin to a Cordova app supporting Android. Copy the aar files from the native library into the plugin/lib folder of the unzipped plugin

Ex. if the plugin has been unzipped to a directory named, ‘ValidicMobileLibraryCordova’, copy the aars file to ‘ValidicMobileLibraryCordova/plugin/lib`.

Full

Copy validicmobile-shared.aar validicmobile-ble.aar validicmobile-ocr.aar validicmobile-shealth.aar from the Android library to the plugin/lib directory within the unzipped plugin. Create the 'lib’ subdirectory if not present.

Aggregator

Copy validicmobile-shared.aar validicmobile-shealth.aar from the Android library to the plugin/lib directory within the unzipped plugin. Create the ‘lib’ subdirectory if not present.

Samsung Health

In order to use Samsung Health with ValidicMobile a valid copy of the Samsung Health SDK must be provided by the developer. This can be downloaded from the SHealth developer portal: Samsung SHealth Developer.

Place the samsung-digital-health-***.jar in the same plugin/lib/samsung folder next to the validicmobile-release.aar described in the Plugin Installation section. If the plugin has previously been added to the project before adding the samsung-digital-health***.jar to the plugin/lib/ folder the plugin must be removed and readded to the project to pull the Samsung SHealth SDK into the project.

iOS

After Cordova has created the iOS Xcode project, it needs to be manually configured to include the native ValidicMobile library.

Copy ‘ValidicMobile.framework’ and ‘copy-validicmobile.rb’ to the platforms\ios folder of your project.

In Xcode, open your project and select your target. In the General tab there will be a panel at the bottom of the screen labeled “Linked Frameworks and Libraries”. Drag the ‘ValidicMobile.framework’ into the panel.

Linked Frameworks

You should now see ValidicMobile.framework under “Linked Frameworks and Libraries”. If the framework is not listed in the file browser on the left, right click the panel, select “Add files to …”, and proceed to select the ValidicMobile.framework and copy-validicmobile.rb files.

Adding Framework

Go to the build settings of your target. In the “Build Phases” tab add a new build phase by clicking the plus button at the top and selecting “New Run Script Phase”.

Build Phase

In the new phase’s text area paste in ruby copy-validicmobile.rb.

Copy Script

To enable use of HealthKit in the app, within the build settings of your target, select the ‘Capabilities’ tab and enable ‘HealthKit’.

HealthKit

If HealthKit is not enabled, an error is reported in the console log on app launch but will not report a error during build.

There is currently an issue with Cordova 6.3 generated Xcode project which prevents frameworks from linking Release builds. To correct this,

  1. Go to the build settings of your target.
  2. Search of scroll down to “Runpath Search Paths”.
  3. Expand to show values for Debug and Release.

Before

  1. The value should be @exeutable_path/Frameworks for both Debug and Release. Cordova is setting this value for the Debug build only. Add the same value, @executable_path/Frameworks for Release as well.

After

Passive Bluetooth support requires enabling background mode support. To enable it:

  1. Edit info.plist
  2. Create new top level entry, Required background modes.
  3. Select App communicates using CoreBluetooth as the value.

Supporting iOS 10

iOS 10 requires usage descriptions to be declared in project’s Info.plist for usage of the camera, Bluetooth and to access and update health data.

The plugin creates these entries in the Info.plist when the iOS platform is added to the project. Custom descriptions can be specified when the plugin is added to the project by specifying values for the following variables in the cordova plugin add CLI command:

The extended command to add the plugin is of the following form:

cordova plugin add <path to unzipped plugin> --variable CAMERA_USAGE_DESCRIPTION=<usage message> --variable HEALTH_SHARE_USAGE_DESCRIPTION=<usage message> --variable HEALTH_UPDATE_USAGE_DESCRIPTION=<usage message> --variable BLUETOOTH_USAGE_DESCRIPTION=<usage message>

If you don’t pass a variable on plugin installation, the plugin provides a generic default message.

Adding plugin to Cordova project

Creating a Cordova project using the ValidicMobile plugin involves the following steps. Additional Cordova commands and options are available. Consult Cordova documentation for additional information.

  1. Install Cordova.
  2. Create Cordova project. cordova create <path> [id name]. id and name are optional. Additional Cordova options are available.
  3. Change directory to the root of the newly created project cd <path>
  4. Add the desired platforms to the project, cordova platform add [ios | android] --save
  5. Add the ValidicMobile plugin to the cordova project, cordova plugin add <path to unzipped plugin> --save. See Supporting iOS 10 for additional parameters to set usage descriptions.

Upgrading plugin

To upgrade the plugin to a new version, the old version of the plugin should be removed and the new version added.

-cordova plugin remove com.validic.mobile -cordova plugin add <path_to_plugin>

Provisioning a User

The Validic Mobile library requires a Validic user. A Validic user can be provisioned using the Validic API. The library requires a Validic user ID, user access token and organization ID. It is recommended to provision the user on your server, the mobile app could then authenticate to the server and retrieve the Validic credentials.

Record types

The Validic Mobile library supports the following record types:

Managing a Session

Overview

The Session stores a user, their current HealthKit or SHealth subscriptions and all pending record uploads. This data is persisted between app launches but is deleted if the ValidicMobile.Session.endSession function is called.

A new Session is started by passing previously provisioned Validic user credentials to the startSession function.

ValidicMobile.Session.startSession(user.USER_ID, user.ORGANIZATION_ID, user.USER_ACCESS_TOKEN);

The supplied credentials are not validated when the session is created. Records will fail to upload if invalid credentials have been provided. Credentials are stored persistently. To change credentials, call:

ValidicMobile.Session.endSession();

or uninstall the app. When a new session is created, pending record uploads and subscriptons are reset. For this reason, a new session should only be created if a session it not already active.

The app can be informed of record upload success and failure by registering callbacks using:

ValidicMobile.Session.setSessionListener(logSuccess, logFail)

The success callback is invoked after each record has successfully uploaded to the server. Fail is invoked if a record upload fails. Setting the session listeners is optional.

Registration of listeners is typically done during app initialization to catch events for record uploads which may occur upon app restart.

Session initialization is typically done when your users log in to your (non-Validic) system, and retrieve your user’s Validic authentication information as stored on your system. The Validic authentication information for your user is then used with the Validic Mobile Library to initialize your Session.

The following example starts a session if a session is not already active and registers session listeners.

var user = {
    "USER_ID": "replace with userid",
    "USER_ACCESS_TOKEN": "replace with access token",
    "ORGANIZATION_ID": "replace with organization id"
};
var logSuccess = function (object) {
    console.log(object);
};
var logFail = function (object) {
    console.log(object)
};
ValidicMobile.Session.setSessionListener(logSuccess, logFail);
ValidicMobile.Session.isSessionActive(function (response) {
    if (!response.isActive) {
        // Only do this if your user is logging in
        ValidicMobile.Session.startSession(user.USER_ID, user.ORGANIZATION_ID, user.USER_ACCESS_TOKEN);
    }
});

Bluetooth

Peripherals

Peripheral objects contain information regarding supported Bluetooth peripherals. Several function calls are provided to retrieve one or more peripherals.

A peripheral object contains various properties used during the reading and pairing process:

Supported Peripherals

To retrieve an array of supported peripherals:

ValidicMobile.BLE.getSupportedPeripherals(function (response) {
    var peripherals = response.peripherals;
};

To retrieve a specific peripheral:

ValidicMobile.BLE.getPeripheral(3, function (response) {
    var peripheral = response.peripheral;
}, function (err) {
    alert(err.error);
});

Peripherals are grouped by type, such as thermometer, glucose, scale, etc. To retrieve an array of peripherals of a specific type, use the ValidicMobile.BLE.PeripheralType constants and invoke the following function:

ValidicMobile.BLE.getPeripheralsOfType(ValidicMobile.PeripheralType.THERMOMETER, function (response) {
    app.peripheral = response.peripheral;
}, function (err) {
    alert(err.error);
});

Pairing

Certain peripherals require pairing with the mobile device before a reading can be taken. You can check the RequiresPairing property on the peripheral object to know if it must be paired. To begin a pairing process, the PairingInstruction property of a Bluetooth peripheral object can be displayed to the user. To start the pairing process, call:

ValidicMobile.BLE.pair(peripheralID, successCallback(), failCallback())

The pairing process can generate multiple callbacks. A response object is passed to the successCallback which includes an event property and a payload containing information specific to the request.

var success = function (response) {
    console.log('Successful pair with peripheral ID:' + response.payload.peripheralID);
};
var fail = function(response) {
    console.log('Error: ' + response.payload.error);
};
ValidicMobile.BLE.pair(15, success, fail);

Reading

When the BLE read process is first initiated, the user should be presented with instructions from the peripheral object using the Instruction property.

When the ValidicMobile.BLE.EventName.ON_READY_TO_READ event is received, the user should be presented with instructions from the peripheral object using the ReadingInstruction property.

Assuming event listeners have been registered as shown below, the BLE read process is initiated as follows:

ValidicMobile.BLE.read(peripheral.ID);

The ValidicMobile.BLE.EventName.ON_READ_SUCCESS event is posted when the read successfully completes and is passed a object with a records property containing an array of records read via BLE.

Some peripherals return a single record while others may return multiple records. To submit a single record to the server,

var onBLEReadSuccess = function (event) {
    ValidicMobile.Session.submitRecord(event.records[0]);
}

To submit multiple records,

var onBLEReadSuccess = function (event) {
    ValidicMobile.Session.submitRecords(event.records);
}

Events

Events are generated for the possible responses from bluetooth pair and read requests. These events are posted from the window. Event names are defined within the ValidicMobile.BLE.EventName set of constants.

Event listeners for the pairing events can be registered as follows:

window.addEventListener(ValidicMobile.BLE.EventName.ON_PAIR_SUCCESS, this.onBLEPairingSuccess);
window.addEventListener(ValidicMobile.BLE.EventName.ON_PAIR_FAIL, this.onBLEPairingFailed);
window.addEventListener(ValidicMobile.BLE.EventName.ON_PAIR_START, this.onBLEPairingStarted);

Note: The ValidicMobile.BLE.Event.ON_PAIR_START event is only posted on Android, not on iOS.

If using event listeners, callbacks can be left off of the pair request. The event listener receives the payload object.

ValidicMobile.BLE.pair(15);

To register for events associated with the BLE reading process:

window.addEventListener(ValidicMobile.BLE.EventName.ON_READY_TO_READ, this.onBLEReadyToRead);
window.addEventListener(ValidicMobile.BLE.EventName.ON_READ_SUCCESS, this.onBLEReadSuccess);
window.addEventListener(ValidicMobile.BLE.EventName.ON_READ_FAIL, this.onBLEReadFailed);
window.addEventListener(ValidicMobile.BLE.EventName.ON_READ_CANCEL, this.onBLEReadCancelled);

Pairing and reading is initiated using pair and read functions which can be invoked with optional success and fail callbacks. These callbacks are invoked passing a response object that described the event. The response includes an event property with the event name, and a payload property containing the appropriate data.

When event listeners are registered, the object passed to the listener is simplified. The passed object is the value of the payload property.

HealthKit

Calls to HealthKit functions should only be performed on devices supporting HealthKit. In particular, HealthKit does not function on Android devices. To determine if HealthKit is available on the current device the following call is provided:

var success = function (response) {
    if (response.isAvailable) {
        console.log("HealthKit is available");
    }
}
ValidicMobile.HealthKit.isHealthKitAvailable(success);

The Validic Mobile library provides a simple way to read and upload data from HealthKit to Validic. The ValidicMobile plugin can subscribe to specific HealthKit sample types and automatically upload them to Validic in the background as new data is recorded, even if the app is no longer active.

Subscribing to HealthKit updates only needs to be done once for a user. The subscriptions will be persisted across app launches in the Session object. A typical use of the HealthKit component would be to create a checkbox or equivalent that adds the required subscriptions when turned on and removes them when turned off.

Healthkit subscriptions are based on sample types. Constants representing each available sample type are defined within ValidicMobile.HealthKit.SampleType.

The Validic Mobile library provides subscription sets which are a collection of predefined sample types declared in ValidicMobile.HealthKit.SubscriptionSet. Sample types for a subscription set can be retrieved using the getSampleTypesForSubscriptionSet function. The following subscription sets are available:

To subscribe to HealthKit sample types:

ValidicMobile.HealthKit.setSubscriptions(sampleTypes, successCallback, errorCallback);

The function accepts an array of strings mapping to HealthKit sample types. Sample types can be aggregated into an array using various calls to retrieve sample types.

The following example retrieves samples types for a subscription set for WEIGHT, adds a specific sample type for step count, and sets those subscriptions.

var success = function (object) {
    var sampleTypes = object.sampleTypes;
    sampleTypes.push(ValidicMobile.HealthKit.SampleType.HKQuantityTypeIdentifierStepCount);
    ValidicMobile.HealthKit.setSubscriptions(sampleTypes);
};
ValidicMobile.HealthKit.getSampleTypesForSubscriptionSet(ValidicMobile.HealthKit.SubscriptionSet.WEIGHT, success);

Note: Calling

ValidicMobile.Session.endSession();

will remove all HealthKit subscriptions and stop listening for new data.

Historical Fetch

The Validic Mobile library provides the ability to query 6 months of data for a subset of data types provided by HealthKit by specifying one of more values of the HealthKit.HistoricalSet enum.

Two historical sets are available

To fetch 6 months of historical HealthKit data, call the HealthKit.fetchHistoricalSets function and pass in the datasets you want to fetch. The function accepts a success function parameter which is called when historical records have been queued for upload to the server. The success function is called with an object that contains the number of records processed for each record type. An error function can also be passed which is invoked if invalid parameters are passed.

ValidicMobile.HealthKit.fetchHistoricalSets([ValidicMobile.HealthKit.HistoricalSet.ROUTINE, ValidicMobile.HealthKit.HistoricalSet.FITNESS],
    function (response) {
        document.getElementById("recordsLog").innerHTML += "HealthKit historical records processed: "
            + JSON.stringify(response) + "<br/><br/>";
    },
    function (response) {
        document.getElementById("recordsLog").innerHTML += "HealthKit historical error: "
            + JSON.stringify(response) + "<br/><br/>";
    });

Doing this may display a permission dialogue from HealthKit so it’s important to call this at an appropriate time in your app. It is recommended to explain to the user why you want this data before attempting to fetch it. This operation may take several seconds to complete so it would be advisable to display an activity indicator to the user until the completion block is called. There should be no need to call this method more than once for a user. When the fetch completes all the data will have been fetched locally and queued up for submission to the server. The amount of time needed to upload the records may vary based on the user’s internet speed. The queued records are uploaded automatically by the library based on connectivity, but it is possible for the user to suspend the app before all the records have been uploaded, the remaining records will be uploaded when the user resumes the app. This should be kept in mind when receiving records from the Validic server.

SHealth

IMPORTANT: Before you begin development, please note that the Samsung Health integration requires pre-approval from Samsung for their Device SDK. Validic is working with Samsung on a process for new approvals. Please reach out to Validic Support at support@validic.com to be notified when Samsung begins accepting new approvals.

The Validic Mobile library provides a simple way to read and upload data from S Health to Validic. Through ValidicMobile.SHealth you can subscribe to specific SHealth data types and automatically upload them to Validic in the background as new data is recorded.

Developer mode

In order to test you must enable developer mode in the S Health app on your phone. As of shealth sdk version 1.2.1, you enable developer mode by going to the More->Settings->About S Health and tapping the version number until “(Developer Mode)” is displayed next to it.

S Health Developer Mode

SHealth is only available if Shealth is installed on the device and the SHealth SDK Jar is available in the project. To check if both of these are true call:

ValidicMobile.SHealth.isSHealthAvailable(function(response) {
    if (response.isAvailable) {
        // SHealth is available
    } else {
        // SHealth is not available log error
        console.log(response.error);
    }   
});

Note: Calling a “ValidicMobile.SHealth’ function when SHealth is not available will fail and pass the error through the callback.

Subscriptions

Samsung provides several data types that can be subscribed to for notification when data changes.

The available data types are:

NOTE: Data types that are going to be used in your application must be added to the AndroidManifest.xml. It is recommended to not manually edit the AndroidManifest.xml directly. It could possibly be overwritten during the Cordova build process. As of Cordova version 6.3.0 it is possible to modify the AndroidManifest.xml file using the <config-file> tag from Cordova

Example using

config.xml


    <platform name="android">
        <allow-intent href="market:*"/>
        <config-file parent="./application" target="AndroidManifest.xml">
            <meta-data android:name="com.samsung.android.health.platform_type" android:value="rel"/>
            <meta-data android:name="com.samsung.android.health.permission.read"
                       android:value="com.samsung.health.blood_glucose;com.samsung.health.exercise"/>
        </config-file>
    </platform>

Subscription Sets

Data types are grouped into logical sets, ValidicMobile.SHealth.SubscriptionSet is an Enum that groups several data types together to register for related data types. The available subscription sets are:

The group of data types for each subscription set can be found using:

    ValidicMobile.SHealth.getSubscriptionsFromSet(ValidicMobile.SHealth.SubscriptionSet.FITNESS);

Subscribing

Current subscriptions will automatically be restarted inside your application’s initialization.

Data types can be subscribed to individually:

ValidicMobile.SHealth.addSubscriptions("com.samsung.health.exercise");

Or as part of a subscription set:

ValidicMobile.SHealth.addSubscriptionSets([ValidicMobile.SHealth.SubscriptionSet.NUTRITION]);

NOTE: Calling ValidicMobile.Session.endSession() will remove all SHealth subscriptions and stop listening for new data.

Historical Fetch

Validic provides the ability to query 6 months of data for a subset of data types provided by Samsung Health by querying a group of SHealthSubscription.HistoricalSet

Currently 2 historical sets are available

Listener

To listen for events from SHealth an eventListener should be added to the window

window.addEventListener(ValidicMobile.SHealth.EventName.ON_SHEALTH_PERMISSIONS, function(event){
    // SHealth permissions have changed
});

window.addEventListener(ValidicMobile.SHealth.EventName.ON_SHEALTH_ERROR, function(event){
    // An error has occurred with SHealth
});

window.addEventListener(ValidicMobile.SHealth.EventName.ON_SHEALTH_RECORDS, function(event){
    // Validic has gathered records because of a data type subscription change
});

window.addEventListener(ValidicMobile.SHealth.EventName.ON_SHEALTH_HISTORY function(event){
    // Validic data has pulled 6 months of records from SHealth
});

OCR

OCR provides the capability to obtain readings from devices without requiring Bluetooth, HealthKit or SHealth integration.

Peripherals

Peripheral objects contain information regarding supported OCR peripherals. Several function calls are provided to retrieve one or more peripherals.

A peripheral object contains various properties to be displayed to the user:

Supported Peripherals

To retrieve a List of supported peripherals:

ValidicMobile.OCR.getSupportedPeripherals(function (response) {
    var peripherals = response.peripherals;
});

To retrieve a specific peripheral:

ValidicMobile.OCR.getPeripheral(3, function (response) {
    var peripheral = response.peripheral;
}, function (err) {
    alert(err.error);
});

Peripherals are grouped by type, such as thermometer, glucose, scale, etc. To retrieve an array of peripherals of a specific type, use the PeripheralType constants and invoke the following function:

ValidicMobile.OCR.getPeripheralsOfType(ValidicMobile.PeripheralType.THERMOMETER, function (response) {
    app.peripheral = response.peripheral;
}, function (err) {
    alert(err.error);
});

Note: OCR and BLE peripheral objects are similar yet different and are not interchangeable.

OCR Read

To use OCR to scan a peripheral, the following call is provided,

ValidicMobile.OCR.read(app.peripheral.ID, successCallback, failCallback)

The ID parameter is the ID property from the OCR peripheral object. The successCallback is passed an object containing the generated record in the record property. The image which was recognized is also returned in the image property as a base64 encoded string.

The following snippet initiates a OCR read. On success the image is displayed and record submitted. On failure the error is displayed.

var success = function (obj) {
    var record = obj.record;
    if (obj.hasOwnProperty("image")) {
        document.getElementById("ocrImage").setAttribute("src", "data:image/png;base64," + obj.image);
    }
    var r = confirm("Would you like to submit a blood glucose of " + record.blood_glucose + "mg/dL");
    if (r) {
        ValidicMobile.Session.submitRecord(record, obj.image, function (obj) {
            console.log("Record was added to the processing queue");
        }, function (obj) {
            console.log("Record was not added to queue");
        });
    }
};
/**
 * Failure callback function. This indicates a failure by Validic to take a reading from the device. This could be due to
 * a timeout or for denying permissions for using the camera. Each failure callback e, has the form({peripheralId: 3, error: "..."}
 * @param e
 */
var fail = function (e) {
    alert(e.error);
};
ValidicMobile.OCR.read(app.ocrPeripheral.ID, success, fail); // 3

Runtime unit selection

For any glucose meter in our lineup of supported meters, you can now specify mmol/l or mg/dL at runtime for a given reading. If no unit is provided, mg/dL is assumed.

Example:

ValidicMobile.OCR.readWithGlucoseUnit(3, ValidicMobile.GlucoseUnits.MMOLL, success, fail); // Start reading a mmol/L one touch