Add Validic dynamic-link libraries to your project’s References. In Xamarin Studio, double click References in the left panel. In the .Net Assembly tab click Browse and select ValidicCore.iOS.dll, ValidicBluetooth.iOS.dll, ValidicHealthKit.iOS.dll, ValidicOCR.iOS.dll.
You should now see ValidicMobile.iOS under “References” in the panel on the left.
iOS 10 requires usage descriptions to be declared in project’s Info.plist
.
Privacy - Camera Usage Description
key and value if edited in Xcode,
or NSCameraUsageDescription
if viewed as XML.Privacy - Health Share Usage Description
key and value if edited in Xcode, or NSHealthShareUsageDescription
if viewed as XML. It also requires filling in the Privacy - Health Update Usage Description
key and value if edited in Xcode, or NSHealthUpdateUsageDescription
if viewed as XML.Privacy - Bluetooth Peripheral Usage Description
key and value if edited in Xcode, or NSBluetoothPeripheralUsageDescription
if viewed as XML.If these values are not provided, the app will crash at runtime with an error reported to the console log.
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 retreive the Validic credentials.
The Validic Mobile library supports the following record types:
VLDSession
stores a user, their current HealthKit subscriptions
and all pending record uploads. This data is persisted between
app launches but is deleted if endSession
is called.
VLDSession
is a singleton object and must be accessed by its
SharedInstance
method. The different components of the Validic
Mobile library rely on a valid user existing in the current
VLDSession
singleton object.
To start a VLDSession
you will need a VLDUser
object. Generally you retrieve the credentials to instantiate a user object from your server.
The credentials needed are a Validic user ID, an organization ID and a user access token.
VLDUser user = new VLDUser ("user_id", "organization_id", "access_token");
The user object is then passed to the StartSessionWithUser()
method. Note: starting a session will delete the current session if it exists.
VLDSession.SharedInstance().StartSessionWithUser (user);
When VLDSession uploads a record it will send an NSNotification. To listen for this
notification add an observer to the NSNotificationCenter with the string Constants.kVLDRecordSubmittedNotification
.
The object
property of the notification will contain the VLDRecord object uploaded.
When VLDSession uploads an image, it will send a different notification, Constants.kVLDRecordImageSubmittedNotification
. The object
property of the notification will contain the VLDRecord object with the media property populated.
If a 400 error is returned from the server, the record will be discarded and an NSNotification will be posted.
To listen for this notification add an observer to the NSNotificationCenter with the constant
Constants.kVLDRecordSubmissionFailedNotification
. The object
property of the notification
will contain the invalid VLDRecord object.
The userInfo dictionary for this notification will contain one key, error
with the NSError object for the failed upload.
If VLDSession attempts to upload the image associated with a record and the upload fails, an NSNotification, Constants.kVLDRecordImageSubmissionFailedNotification
will be posted.
VLDBluetoothPeripheral
represents Bluetooth peripheral models that can be discovered or read from by VLDBluetoothPeripheralController
.
A peripheral object contains various information to be displayed to the user:
name
- Name of the peripheral comprised of the the manufacturer name and model number.pairingInstructions
- Text telling the user how to pair the peripheral, if the peripheral requires pairing.instructions
- Text telling the user how to initialize the reading process with the peripheral.readingInstructions
- Text telling the user what to do during the reading process.imageURL
- URL for an image of the peripheral.To retrieve a List of supported peripherals simply call:
foreach (VLDBluetoothPeripheral peripheral in VLDBluetoothPeripheral.SupportedPeripherals)
{
Console.WriteLine(peripheral.Name);
}
Other methods are available on VLDBluetoothPeripheral to allow retrival of a specific peripheral, or to retrieve a list of peripherals of a specific peripheral type. See the VLDBluetoothPeripheral documentation for additional information.
Certain peripherals require pairing with the mobile device before a reading can be taken. You can check the requiresPairing
property on the VLDBluetoothPeripheral
object to know if it must be paired.
To pair a peripheral with the mobile device, call the PairPeripheral()
method on VLDBluetoothPeripheralController
.
VLDBluetoothPeripheral peripheral = // A peripheral from the supportedPeripherals list
VLDBluetoothPeripheralController controller = new VLDBluetoothPeripheralController();
controller.WeakDelegate = this;
controller.PairPeripheral(peripheral);
To know if a peripheral was successfully paired you will need to implement the pairing methods of the VLDBluetoothPeripheralControllerDelegate
protocol.
[Export("bluetoothPeripheralController:didPairPeripheral:")]
public void BluetoothPeripheralControllerDidPairPeripheral (VLDBluetoothPeripheralController controller, VLDBluetoothPeripheral peripheral)
{
// Peripheral paired successfully
}
[Export("bluetoothPeripheralController:didNotPairPeripheral:error:")]
public void BluetoothPeripheralControllerDidNotPairPeripheral(VLDBluetoothPeripheralController controller, VLDBluetoothPeripheral peripheral, NSError error)
{
// Peripheral did not pair
}
Once you are ready to read from a peripheral, the process is fairly similar to the pairing process. You’ll want to first show peripheral.Instructions
and eventually show peripheral.ReadingInstructions
once BluetoothPeripheralControllerIsReadyToReadFromPeripheral()
is called.
VLDBluetoothPeripheralController controller = new VLDBluetoothPeripheralController ();
controller.WeakDelegate = this;
controller.ReadFromPeripheral (peripheral);
You must also implement the reading methods of the VLDBluetoothPeripheralControllerDelegate
protocol.
[Export("bluetoothPeripheralController:isReadyToReadFromPeripheral:")]
public void BluetoothPeripheralControllerIsReadyToReadFromPeripheral (VLDBluetoothPeripheralController controller, VLDBluetoothPeripheral peripheral)
{
// Time to present the readingInstructions to the user
}
[Export("bluetoothPeripheralController:shouldSubmitReadings:fromPeripheral:")]
public bool BluetoothPeripheralControllerShouldSubmitReadings (VLDBluetoothPeripheralController controller, VLDRecord[] records, VLDBluetoothPeripheral peripheral)
{
// To have the reading automatically added to the session and uploaded
// return true from this method. To first have the reading validated by the user
// you can return false from this method. Once the user has validated the reading
// you must manually submit the record by calling VLDSession.SharedInstance().submitRecords(record);
return true;
}
[Export("bluetoothPeripheralController:readingFailedForPeripheral:error:")]
public void BluetoothPeripheralControllerReadingFailed (VLDBluetoothPeripheralController controller, VLDBluetoothPeripheral peripheral, NSError error)
{
// Reading failed
}
The ValidicMobile library supports passively reading from a given set of Bluetooth peripherals. Passive Bluetooth reading is a long lived capability. Once enabled, the library will listen for and read from the specified peripherals. Reading will automatically occur once the peripheral is discovered regardless of app state. This includes if the application is currently in the foreground, in the background, or has been terminated due to memory pressure. Apps using this feature must have been started by the user at least once since the iOS device has booted otherwise the feature will not be active even if enabled.
VLDBluetoothPassiveManager
is a singleton which coordinates the passive reading process. Passive reading is enabled by passing it an array of peripheral IDs:
VLDBluetoothPassiveManager.SharedInstance().PeripheralIDs = new NSNumber[] { 1, 2 };
To disable passive reading, set the peripheralIDs
property to an empty array or nil.
VLDBluetoothPassiveManager.SharedInstance().PeripheralIDs = null;
Passive Bluetooth reading relies upon iOS Bluetooth state restoration and background processing support. Apps using passive reading need to set Bluetooth as a required background mode in the Info.plist
. In Xcode, in the Info.plist
add a new key, Required background modes
, add an item with value App communicates using CoreBluetooth
.
If editing the XML source file, add Bluetooth-central
background mode as follows:
<key>UIBackgroundModes</key>
<array>
<string>Bluetooth-central</string>
</array>
To support state restoration, a method on the passive manager must be called on app launch. This should be done in the application:didFinishLaunchingWithOptions:
method of the AppDelegate as follows:
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
// Bluetooth passive support if launched to handle discovered peripheral
VLDBluetoothPassiveManager.SharedInstance().RestoreState();
return true;
}
State restoration will automatically start the app in the background when a requested peripheral is discovered. Within application:didFinishLaunchingWithOptions:
, apps can determine if they were launched in background and avoid expensive operations.
Passive readings are automatically sent to the Validic server. Session notifications are sent on upload success or failure. Passive Bluetooth specific notifications are sent when a device is discovered and becomes ready to read. Notifications are also sent for reading success and failure. These notifications specify the associated peripheral ID in the userInfo dictionary with a key, peripheralID
.
kVLDBluetoothPassiveDidReadNotification
is sent when records are read. The notification object is an array of VLDRecord
read from the peripheral.kVLDBluetoothPassiveDidFailNotification
is sent when failing to read from a discovered peripheral.kVLDBluetoothPassiveIsReadyToReadNotification
is sent when the peripheral becomes ready to read. This notification is only sent out for devices that are discoverable before a measurement is taken. It is important to handle this notification in an app and provide feedback to the user that the device has been discovered and is ready to take a measurement. Since Passive Bluetooth reading is usually performed in the background, a standard UI is not available. A local notification can be sent with sound to provide feedback to the user that the app is ready to read from the peripheral. If the user doesn’t hear the sound, it indicates that the device has not been discovered.There are situations where passive Bluetooth reading is stopped and requires the app to be relaunched. These situations include:
Passive Bluetooth reading has some additional considerations due to the behavior of the iOS Bluetooth stack and background support.
The Validic Mobile library provides a simple way to read and upload data from HealthKit to Validic. VLDHealthKitManager
can subscribe to specific HealthKit sample types and automatically upload them to Validic in the background as new data is recorded.
Subscribing to HealthKit updates only needs to be done once for a user. The subscriptions will be persisted across app launches in the VLDSession
object. A typical use of the HealthKit component would be to create a UISwitch that adds the required subscriptions when turned on and removes them when turned off.
To properly process the delivery of data in the background, the subscription observers need to be recreated immediately when the app is launched. To do this, you need to call VLDHealthKitManager.SharedInstance().ObserveCurrentSubscriptions();
inside your application delegate’s FinishedLaunching()
function. Example:
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
VLDHealthKitManager.SharedInstance().ObserveCurrentSubscriptions();
return true;
}
Note: Calling VLDSession.SharedInstance().EndSession();
will remove all HealthKit subscriptions and stop listening for new data.
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 VLDHealthKitHistoricalSet
enum.
To fetch 6 months of historical HealthKit data, call the FetchHistoricalSets()
method on VLDHealthKitManager
and pass in the datasets you want to fetch.
OCR provides the capability to obtain readings from devices without requiring Bluetooth or HealthKit integration. The simplest way to use this feature is to present an instance of the VLDOCRViewController
after initializing it with the ID of a VLDOCRPeripheral
.