spike_flutter_sdk

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

spike flutter sdk

Spike Flutter SDK allows you to read the Apple HealthKit and Android Health Connect data. Then, it allows you to send the data to your backend chosen, and get the data returned which is processed by the backend. Also, you can enable background delivery in case iOS device is being used. And finally, it is possible to enable event tracking to see if everything works as intended or just provide your own event tracking library.
Features #

Read the Apple HealthKit data.
Send this data to backend.
Register periodic background tasks to send and read the data.
Track various events of the package by utilizing shared preferences.

SDK version update guide #
iOS Considerations #
Sometimes we need to update the native SDK version regarding iOS part. It is always recommended to call pod update --repo-update command from the Flutter's iOS folder when you change the Flutter SDK version.
Getting started #
iOS Setup Guide #
At first in your app's entitlements select HealthKit and in your app's info.plist file add permissions:
<key>NSHealthShareUsageDescription</key>
<string>WHY_YOU_NEED_TO_SHARE_DATA</string>
<key>NSHealthUpdateUsageDescription</key>
<string>WHY_YOU_NEED_TO_USE_DATA</string>
copied to clipboard
If you plan to use WorkoutRoute Series please provide additionally CoreLocation permissions:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>WHY_YOU_NEED_TO_ALWAYS_SHARE_LOCATION</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>WHY_YOU_NEED_TO_SHARE_LOCATION</string>
copied to clipboard
Note. You must configure XCode appropriately. You should add the following capability: Background Delivery and Clinical Health Records from the HealthKit. This is crucial, since otherwise you will be unable to extract the iOS data.
Another note. Each time you see in the updates CHANGELOG that iOS Native SDK version was updated, you should run the following command from your project's iOS folder:
pod update
copied to clipboard
Otherwise, you risk your app to be not working as native code changes might result in changes required for you as a client.
Android Setup Guide #
Note. All these steps ARE COMPLETELY NECESSARY! However, if you want this to work with Android 14, you MUST VERY CAREFULLY READ Android 14 Setup Guide, and execute the steps written there exactly as they are written.
First of all you have to add the required health permissions to a resource file. You can reuse an existing one or create a new one. That allows you to fully utilise this SDK and to read the necessary data from apps that integrate with HealthConnect.

Create config.xml in the following path: android/app/src/main/res/values. Content of this file must be the following:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="health_permissions">
<item>androidx.health.permission.Nutrition.READ</item>
<item>androidx.health.permission.ActiveCaloriesBurned.READ</item>
<item>androidx.health.permission.TotalCaloriesBurned.READ</item>
<item>androidx.health.permission.Steps.READ</item>
<item>androidx.health.permission.Distance.READ</item>
<item>androidx.health.permission.ElevationGained.READ</item>
<item>androidx.health.permission.RestingHeartRate.READ</item>
<item>androidx.health.permission.HeartRateVariabilityRmssd.READ</item>
<item>androidx.health.permission.FloorsClimbed.READ</item>
<item>androidx.health.permission.BasalMetabolicRate.READ</item>
<item>androidx.health.permission.SleepSession.READ</item>
<item>androidx.health.permission.HeartRate.READ</item>
<item>androidx.health.permission.ExerciseSession.READ</item>
<item>androidx.health.permission.Speed.READ</item>
<item>androidx.health.permission.Power.READ</item>
<item>androidx.health.permission.OxygenSaturation.READ</item>
<item>androidx.health.permission.BloodGlucose.READ</item>
<item>androidx.health.permission.RespiratoryRate.READ</item>
<item>androidx.health.permission.Weight.READ</item>
<item>androidx.health.permission.Height.READ</item>
<item>androidx.health.permission.BodyFat.READ</item>
<item>androidx.health.permission.LeanBodyMass.READ</item>
<item>androidx.health.permission.BodyWaterMass.READ</item>
<item>androidx.health.permission.BodyTemperature.READ</item>
<item>androidx.health.permission.BloodPressure.READ</item>
<item>androidx.health.permission.BoneMass.READ</item>
</array>
</resources>
copied to clipboard

Now comes the AndroidManifest.xml modification part. Add the following query in the

<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
copied to clipboard

Then reference the permissions to your AndroidManifest.xml file in the activity that will call for health permissions. This meta-data reference should be added under the

<meta-data
android:name="health_permissions"
android:resource="@array/health_permissions" />
copied to clipboard

As well as that you have to add intent filter to your activity definition so that you can request the permissions at runtime. This intent filter reference should be added under the

<intent-filter>
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
</intent-filter>
copied to clipboard

In case permissions handling is not working, this might be related to launch mode being singleTop. This might be not needed, but some apps faced problems when requesting permissions. If you face them, then you should try removing the following line:

android:launchMode="singleTop"
copied to clipboard

In case app is not building, it might be related to label replacement issue. In this case, you should add the following line to the

tools:replace="android:label"
copied to clipboard

Afterwards, add the following line into the android/app/build.gradle under dependencies:

implementation 'androidx.appcompat:appcompat:1.3.1'
copied to clipboard

Since we are using closed source native Android SDK, separate repository is needed. Thus, add the following dependency into your android/builde.gradle file (it must be added both in repositories and allprojects node of repositories):


maven {
url 'https://gitlab.com/api/v4/projects/43396247/packages/maven'
}

copied to clipboard

Finally, in local.properties of your project for Flutter, add these lines:

flutter.minSdkVersion=28
flutter.compileSdkVersion=34
copied to clipboard

In case your default Flutter project does not take these values, do the necessary changes in the android/app/build.gradle:

def flutterCompileSdkVersion = localProperties.getProperty('flutter.compileSdkVersion')
if (flutterCompileSdkVersion == null) {
flutterCompileSdkVersion = '34'
}

copied to clipboard

And then, add or change compileSdkVersion under android node like this:

compileSdkVersion flutterCompileSdkVersion.toInteger()
copied to clipboard

In case you face an issue not described here, feel free to contact us, and give us as much information as possible for us to provide more information about how to resolve your specific issue. The problems sometimes are caused by just different environments, and there is no way to test all of them when there are so many of them.

Android 14 Setup Guide #


You must make sure you have followed "Android Setup Guide", and it works completely with devices before Android 14. Otherwise, these steps might not work, because you did not set-up initially.


Check the contents of android/app/src/main/kotlin/{YOUR_PACKAGE_ID}/MainActivity.kt. You must see something like that in case it is the new app being developed:


import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
copied to clipboard
The main thing here is that you must change FlutterActivity to the FlutterFragmentActivity which means that you code should turn into the result similar to the one below:
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
}
copied to clipboard

In the Health Connect permissions activity there is a link to your privacy policy. You need to grant the Health Connect app access in order to link back to your privacy policy. In the example below, you should either replace .MainActivity with an activity that presents the privacy policy or have the Main Activity route the user to the policy. This step may be required to pass Google app review when requesting access to sensitive permissions.

<activity-alias
android:name="ViewPermissionUsageActivity"
android:exported="true"
android:targetActivity=".MainActivity"
android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
<intent-filter>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
<category android:name="android.intent.category.HEALTH_PERMISSIONS" />
</intent-filter>
</activity-alias>
copied to clipboard

Android 14 uses different model for the Health permissions. So you must add the following permissions for requesting into the AndroidManifest.xml:

<!-- Health permissions -->
<uses-permission android:name="android.permission.health.READ_SLEEP "/>
<uses-permission android:name="android.permission.health.READ_WEIGHT" />
<uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_BASAL_METABOLIC_RATE" />
<uses-permission android:name="android.permission.health.READ_BLOOD_GLUCOSE" />
<uses-permission android:name="android.permission.health.READ_BLOOD_PRESSURE" />
<uses-permission android:name="android.permission.health.READ_BODY_FAT" />
<uses-permission android:name="android.permission.health.READ_BONE_MASS" />
<uses-permission android:name="android.permission.health.READ_EXERCISE" />
<uses-permission android:name="android.permission.health.READ_DISTANCE" />
<uses-permission android:name="android.permission.health.READ_ELEVATION_GAINED" />
<uses-permission android:name="android.permission.health.READ_FLOORS_CLIMBED" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE_VARIABILITY" />
<uses-permission android:name="android.permission.health.READ_HEIGHT" />
<uses-permission android:name="android.permission.health.READ_OXYGEN_SATURATION" />
<uses-permission android:name="android.permission.health.READ_POWER" />
<uses-permission android:name="android.permission.health.READ_RESPIRATORY_RATE" />
<uses-permission android:name="android.permission.health.READ_RESTING_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_SPEED" />
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.READ_TOTAL_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_BODY_TEMPERATURE" />
<uses-permission android:name="android.permission.health.READ_BASAL_METABOLIC_RATE" />
copied to clipboard
Spike SDK Usage #
The examples below demonstrate how to use this package in various of cases.
Initialization #
First, you must get the correct credentials in order for this package to be usable. In case you want to test web hooks, but do not have or want to set-up your own environment, you can try the following free service: https://webhook.site

const authToken = '{YOUR_AUTH_TOKEN}';

const appId = '{YOUR_APP_ID}';

const customerEndUserId = '{YOUR_CUSTOMER_END_USER_ID}';

const postbackURL = 'https://example.com/';

copied to clipboard
Creating Spike connection #
Using the credentials received, you can create the connection. This is done in the following way.
final connection = await SpikeSDK.createConnection(
appId: appId,
authToken: authToken,
customerEndUserId: customerEndUserId,
postbackURL: postbackURL, // Optional, provides functionality to send data to webhook and use background deliveries.
logger: const PrintLogger() // Optional, class which conforms to SpikeLogger interface
);
copied to clipboard
Creating Spike connection (For the specified environment) #
Using the credentials received, you can create the connection. This is done in the following way.
final connection = await SpikeSDK.createConnection(
appId: appId,
authToken: authToken,
customerEndUserId: customerEndUserId,
postbackURL: postbackURL, // Optional, provides functionality to send data to webhook and use background deliveries.
logger: const PrintLogger(), // Optional, class which conforms to SpikeLogger interface
);
copied to clipboard
Also, you can add a logger that logs the most important events in the connection. First, you would need to implement the SpikeLogger abstract class. Example of how to do so is below.

import 'package:spike_flutter_sdk/spike_flutter_sdk.dart';



class PrintLogger extends SpikeLogger {

const PrintLogger();



// You specify if you want to receive debug messages through this logger.

@override

bool get isDebugEnabled => true;



// You specify if you want to receive error messages through this logger.

@override

bool get isErrorEnabled => true;



// You specify if you want to receive info messages through this logger.

@override

bool get isInfoEnabled => true;



@override

void debug(SpikeConnection connection, String message) =>

_log(connection, message, 'debug');



@override

void error(SpikeConnection connection, String message) =>

_log(connection, message, 'error');



@override

void info(SpikeConnection connection, String message) =>

_log(connection, message, 'info');



/*

* Of course, in the production apps using 'print' is an antipattern in Flutter,

* but this is intended to give you an idea how to use logger, and also to have

* a compilable version of the logger to get you started as fast as possible.

*/

void _log(SpikeConnection connection, String message, String level) =>

print('[$level] [${connection.connectionId}]: $message');

}

copied to clipboard
Requesting permissions #
In order to use the connection properly, you must first ask for the permissions needed for your purposes. Let us assume you want to get heart data. For this, you must to ask for heart data permissions. See the example below about how easy it is to do so.
connection.ensurePermissionsAreGrantedV2(types: [SpikeDataType.heart]);
copied to clipboard
Just one line of code, and you are requesting the permissions.
Note. During the next release, this method is going to be changed into 'ensurePermissionsAreGranted' as this way of returning the result is more preferable.
Requesting permissions (before 1.2.0) #
In order to use the connection properly, you must first ask for the permissions needed for your purposes. Let us assume you want to get heart data. For this, you must to ask for heart data permissions. See the example below about how easy it is to do so.
connection.ensurePermissionsAreGranted(types: [SpikeDataType.heart]);
copied to clipboard
Just one line of code, and you are requesting the permissions.
Note. During the next release, this method is going to change the return type.
Requesting permissions (additional considerations) #
It is worth to mention that Health Kit does not support feedbacking about if user actually gave requested permissions or not, so the return type is always going to be SpikePermissionsResult.undefined. However, on Android Health Connect gives us more information, but in a very limited way. For instance, if user cancels giving permissions two times, then Health Connect app is never going to open again for the user until you call 'revokeAllPermissions' (or clear your app or Health Connect storage). In the table below, we describe potential return types for the SpikePermissionsResult enum:



Method
Platforms
Description




SpikePermissionsResult.granted
Android
It means all the requested permissions for the specified Spike data type have been given.


SpikePermissionsResult.grantedPartially
Android
It means that user gave only a subset of permissions for your app regarding Health Connect data, but not all the data required for the Spike data type


SpikePermissionsResult.canceled
Android
User did not give any permissions at all.


SpikePermissionsResult.blocked
Android
User cancelled giving permissions two times, and Health Connect blocked your app. You either should call revokeAllPermissions() or ask your users to clear the app storage (or storage of the Health Connect).


SpikePermissionsResult.undefined
iOS
This is going to be returned on iOS in all cases, since there is no way to check if user gave permissions or not for the Health Kit.



Using the connection to get the data (without specified date range) #
Using both simple and Web Hook connections are very easy to use. See the examples below how to use both simple and WebHook connections without date range specified.

final stepsData = await connection.extractData(SpikeDataType.steps);

if (stepsData.data.isNotEmpty) {

print("Steps (Count): ${stepsData.data.length}");

print("Steps[0]: ${stepsData.data[0].value}");

}



final heartJobDetails = await connection.extractAndPostData(SpikeDataType.heart);

print('submittedAt: ${heartJobDetails.submittedAt}');

print('notificationId: ${heartJobDetails.notificationId}');

copied to clipboard
Using the connection to get the data (with specified date range) #
Also, you are allowed to specify the date range wanted. Flutter does not use extractDataInRange or something like that, since Dart gives us a way to use optional parameters, and this feature if Dart is being used here. See the examples below:

final now = DateTime.now()

final stepsData = await connection.extractData(

SpikeDataType.steps,

from: now.subtract(const Duration(days: 1)),

to: now,

);



if (stepsData.data.isNotEmpty) {

print("Steps (Count): ${stepsData.data.length}");

print("Steps[0]: ${stepsData.data[0].value}");

}



final heartJobDetails = await connection.extractAndPostData(

SpikeDataType.heart,

from: now.subtract(const Duration(days: 1)),

to: now,

);

print('submittedAt: ${heartJobDetails.submittedAt}');

print('notificationId: ${heartJobDetails.notificationId}');

copied to clipboard
Configure for background deliveries (WebHook connection and iOS only) #
Under your project Signing & Capabilities section enable Background Delivery for HealthKit. Call Spike configure methods on each app start to trigger background deliveries tasks. Add Spike initialization code to ios/Runner/AppDelegate.swift file. The code should look like the one below.
import UIKit
import Flutter
import SpikeSDK

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
Spike.configure()

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
copied to clipboard
Enabling background delivery (WebHook connection and iOS only) #
Enabling the background delivery should be straightforward as shown below.
await connection.enableBackgroundDelivery(
types: [SpikeDataType.summary, SpikeDataType.heart],
);
copied to clipboard
Disabling background delivery (WebHook connection and iOS only) #
Disabling the background delivery should be straightforward as shown below.
await connection.disableBackgroundDelivery();
copied to clipboard
Creating listener for the background delivery and using it (WebHook connection and iOS only) #

In case you want to listen what happens with background delivery, you can implement SpikeWebhookConnectionListener, and provide your implementation as listener for the background delivery. Below, there is an example of how to implement SpikeWebhookConnectionListener.


import 'package:spike_flutter_sdk/spike_flutter_sdk.dart';



class PrintBackgroundListener extends SpikeWebhookConnectionListener {

const PrintBackgroundListener();



@override

void onBackgroundLog(String log) => print(log);

}

copied to clipboard

To listen for the events for the background delivery, you should not just enable it, but also set the listener. Example below shows how to both enable background delivery and set listener to it:


await connection.enableBackgroundDelivery(

types: [SpikeDataType.summary, SpikeDataType.heart],

);

connection.setListener(const PrintBackgroundListener());

copied to clipboard
Checking the background delivery types (WebHook connection and iOS only) #
Sometimes you may want to check for which types the connection are registered for the background delivery. You may use the following example in order to recieve the types for the background delivery.

final types = await connection.getBackgroundDeliveryTypes();

copied to clipboard
Get Spike End User ID #
Use the following.

final result = await connection.getSpikeEndUserId();

copied to clipboard
Errors and Exceptions #
SpikeException #
The abstract parent of all concrete exceptions.
SpikeConnectionIsClosedException #
Thrown if any method is invoked on SpikeConnection or one of its subclasses after the connection has been closed.
SpikeInvalidCredentialsException #
Thrown if the credentials provided are not recognised, i.e. are invalid or expired.
SpikeInvalidDateRangeException #
Thrown if duration exceeds the allowed maximum or if ‘from’ date is greater than ‘to’ date. The message will contain a specific cause description.
SpikeInvalidPostbackUrlException #
Thrown if the callback URL is not a valid URL, does not have HTTPS schema, or is not a sub-URL of the main callback URL configured for the application. The exception message will contain a specific reason.
SpikePackException #
Thrown when a connection cannot be serialised to a packed state. The exception cause will contain the underlying error.
SpikePermissionsNotGrantedException #
Thrown when Spike SDK is unable to access the data due to permissions not being granted.
SpikeServerException #
Whenever any operation with the Spike backend fails and the error does not fall into any of the above exceptions. The exception cause will contain the underlying error.
SpikeUnpackException #
Thrown when a connection cannot be deserialised from a packed state. The exception cause will contain the underlying error.
Flutter Spike SDK Classes and Information #
Spike Data Types #

SpikeDataType.activitiesStream
SpikeDataType.activitiesSummary
SpikeDataType.body
SpikeDataType.breathing
SpikeDataType.calories
SpikeDataType.distance
SpikeDataType.ecg
SpikeDataType.glucose
SpikeDataType.heart
SpikeDataType.oxygenSaturation
SpikeDataType.sleep
SpikeDataType.steps

SpikeSDK #
This is static class intended to be used in order to create new connections, check for existing connections, and so on.
Methods



Method
Platforms
Description




createConnection
iOS, Android
Creates a new SpikeConnection instance with the given user details.


getBackgroundConnections
iOS
Returns all connections that are configured to deliver data in the background.


isPackageInstalled
Android
Check if Health Connect installed on a device.



SpikeConnection #
This is the main class that is used for managing the Spike connection. It is not allowed to instantiate it directly, thus use SpikeSDK.createConnection.
Methods



Method
Platforms
Description




manageHealthConnect
Android
Opens Health Connect app (Android only)


ensurePermissionsAreGranted
iOS, Android
Use this in order to request permissions from the user


revokeAllPermissions
Android
Revokes all permissions (Android only)


close
iOS, Android
Terminates any ongoing connections with Spike’s backend servers, clears any caches, and removes provided user details and tokens from the memory. Once the connection is closed, it cannot be used, and any method other than close() will throw a SpikeConnectionIsClosedException exception.


extractData
iOS, Android
Extracts local device data for the current date in the end-user’s time zone. Optionally time range can be provided. On iOS, the maximum allowed single-query time interval is 90 days. If required, data of any longer time period can be accessed by iterating multiple queries of 90 days. On Android the earliest date data can be requested for is 30 days before a permission was given to the user's app to read from HealthConnect. There is no limit on how many days in total.


extractAndPostData
iOS, Android
Extracts local device data for the current date in the local user time zone and sends it as a webhook notification to the customer’s backend. Optionally time range can be provided. On iOS, the maximum allowed single-query time interval is 90 days. If required, data of any longer time period can be accessed by iterating multiple queries of 90 days. On Android the earliest date data can be requested for is 30 days before a permission was given to the user's app to read from HealthConnect. There is no limit on how many days in total.


getSpikeEndUserId
iOS, Android
Retrieves the unique identifier assigned to the end-user by Spike.


setListener
iOS, Android
Sets a listener that is to handle notifications from the background delivery process.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files:

Customer Reviews

There are no reviews.