Mobile SDKs
SpikeSDK Flutter
current flutter sdk version 4 2 54 flutter package can be found here example app can be found here requirements ios 13 0+ android 9 0+ (level 28, p, pie) installation add ependency on spikesdk in your pubspec yaml file dependencies spike flutter sdk ^4 2 54 ios setup guide use pod install and pod update commands from ios/ folder of your app to install/update spikesdk ios signing & capabilities to add healthkit support to your application's capabilities open the ios/ folder of your project in xcode select the project name in the left sidebar open signing & capabilities section in the main view select '+ capability' and double click healthkit more details you can find here https //developer apple com/documentation/healthkit/setting up healthkit info plist add health kit permissions descriptions to your info plist file \<key>nshealthshareusagedescription\</key> \<string>we will use your health information to better track workouts \</string> \<key>nshealthupdateusagedescription\</key> \<string>we will update your health information to better track workouts \</string> android setup guide to add the sdk to your android project, you have to add the following to your project's build gradle file in the repositories block allprojects { repositories { // other repositories maven { url 'https //gitlab com/api/v4/projects/43396247/packages/maven' } } } set android sdk version in local properties file flutter minsdkversion=28 flutter compilesdkversion=34 android permissions include the necessary health permissions in your androidmanifest xml to fully leverage the spike sdk and access data from apps integrated with health connect please refer to this guide https //developer android com/health and fitness/guides/health connect/get started#declare permissions for details on the required permissions note only request permissions essential to your app’s functionality requesting unused permissions will lead to app store rejection! \<uses permission android\ name="android permission health read nutrition"/> \<uses permission android\ name="android permission health read active calories burned"/> \<uses permission android\ name="android permission health read total calories burned"/> \<uses permission android\ name="android permission health read steps"/> \<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 resting heart rate"/> \<uses permission android\ name="android permission health read heart rate variability"/> \<uses permission android\ name="android permission health read floors climbed"/> \<uses permission android\ name="android permission health read basal metabolic rate"/> \<uses permission android\ name="android permission health read sleep"/> \<uses permission android\ name="android permission health read heart rate"/> \<uses permission android\ name="android permission health read exercise"/> \<uses permission android\ name="android permission health read speed"/> \<uses permission android\ name="android permission health read power"/> \<uses permission android\ name="android permission health read oxygen saturation"/> \<uses permission android\ name="android permission health read blood glucose"/> \<uses permission android\ name="android permission health read respiratory rate"/> \<uses permission android\ name="android permission health read weight"/> \<uses permission android\ name="android permission health read height"/> \<uses permission android\ name="android permission health read body fat"/> \<uses permission android\ name="android permission health read lean body mass"/> \<uses permission android\ name="android permission health read body water mass"/> \<uses permission android\ name="android permission health read body temperature"/> \<uses permission android\ name="android permission health read blood pressure"/> \<uses permission android\ name="android permission health read bone mass"/> add an intent filter to your activity definition so that you can request the permissions at runtime \<intent filter> \<action android\ name="androidx health action show permissions rationale" /> \</intent filter> 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() { } you must change flutteractivity to the flutterfragmentactivity which means that your code should turn into the result similar to the one below import io flutter embedding android flutterfragmentactivity class mainactivity flutterfragmentactivity() { } 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> note if permissions handling is not working, this might be related to launch mode being singletop this might be not needed, but some apps face problems when requesting permissions if you face them, then you should try removing the following line android\ launchmode="singletop" note if app is not building, it might be related to label replacement issue in this case, you should add the following line tools\ replace="android\ label" \<manifest xmlns\ android="http //schemas android com/apk/res/android" xmlns\ tools="http //schemas android com/tools" \> \<application tools\ replace="android\ label" spike sdk usage step 1 create spike connection import 'package\ spike flutter sdk/spike flutter sdk dart'; final spikeconnection = await spikesdkv3 createconnection( applicationid appid, signature signature, enduserid appuser, ); step 2 ask user for permissions if you plan to use android health connect and/or apple healthkit data providers you should first get users permission to use their data // this call may present user with os native modal asking for read // permissions needed to get steps and distance data if you want to // present it only once, you should list all the statistic types you // plan to use otherwise, you can call this only before you actually // want to use the data await widget connection requesthealthpermissions( statistictypes \[statisticstype steps], includeenhancedpermissions false, ); step 3 get data info the maximum permitted date range is 90 days there are two types of data you can retrieve from spike records consist of the raw data points collected from user devices or applications statistics , on the other hand, are calculated values derived from records statistics now you can read hourly statistics data of steps and distance for today final now = datetime now(); final tomorrow = datetime(now\ year, now\ month, now\ day + 1); final weekago = now\ subtract(const duration(days 7)); final statistics = await widget connection getstatistics( oftypes \[statisticstype steps], from weekago, to tomorrow, interval statisticsinterval day, ); where enum statisticstype { steps, distancetotal, distancewalking, distancecycling, distancerunning, caloriesburnedtotal, caloriesburnedbasal, caloriesburnedactive; } enum statisticsinterval { hour, day; } // filter class statisticsfilter { final bool excludemanual; final set\<provider>? providers; final set\<activitytag>? activitytags; } // result class statistic { final datetime start; final datetime end; final int duration; final statisticstype type; final num value; final unit unit; final int? rowcount; final list\<string>? recordids; } records final now = datetime now(); final tomorrow = datetime(now\ year, now\ month, now\ day + 1); final weekago = now\ subtract(const duration(days 7)); final records = await connection getrecords( oftypes \[metrictype stepstotal], from weekago, to tomorrow, filter statisticsfilter(excludemanual false), ); where enum metrictype { heartratemax, heartrateavg, heartratemin, heartrate, heartrateresting, heartratevariabilityrmssd, heartratevariabilityrmssddeepsleep, elevationmax, elevationavg, elevationmin, elevationgain, elevationloss, ascent, descent, caloriesburnedactive, caloriesburnedbasal, caloriesburned, caloriesintake, stepstotal, floorsclimbed, distancetotal, distancewalking, distancecycling, distancerunning, distancewheelchair, distanceswimming, speedmax, speedavg, speedmin, airtemperaturemax, airtemperatureavg, airtemperaturemin, spo2max, spo2avg, spo2min, longitude, latitude, elevation, durationactive, swimminglengths, swimmingdistanceperstroke; } // result class record { final string recordid; final string? inputmethod; final datetime startat; final datetime? endat; final datetime modifiedat; final int? duration; final string? provider; final string? providersource; final bool? issourceaggregated; final recordsource? source; final map\<string, num>? metrics; final list\<activitytag>? activitytags; final string? activitytype; final list\<activityentry>? sessions; final list\<activityentry>? laps; final list\<activityentry>? segments; final list\<activityentry>? splits; final list\<activityentry>? samples; final list\<activityentry>? routepoints; final list\<activityentry>? sleep; } class activityentry { final int? divisionref; final string? divisionlabel; final datetime? startat; final datetime? endat; final int? duration; final map\<string, num>? metrics; } backgrdound delivery background delivery ensures that data updates are sent to your backend via webhooks, even when the application is in the background or closed ios important notes about background delivery on ios for most data types the most possible frequency of updates is 1 hour ios can update data more frequently for some data types, for example, vo2 max ios may throttle the frequency of updates for background delivery depending on the app's activity, battery state, etc background delivery is not possible while device is locked, so it will be executed only when the device is unlocked ios may stop background delivery if it detects that the app is not active for a long time the feature is available starting with ios 15 important the spikesdk, along with any other healthkit applications, cannot guarantee data synchronization on a fixed schedule the hourly sync interval serves as a guideline rather than a strict requirement enforced by ios consequently, the actual synchronization frequency may vary, occurring hourly, once per day, or during specific system defined events, such as the conclusion of sleep mode or when the device begins charging setup enable background delivery for app target open xcode with your ios project open the folder of your project in xcode select the project name in the left sidebar open signing & capabilities section select healthkit background delivery under healthkit section initialization at app startup for background delivery to work properly, you need to initialize the spikesdk at app startup appdelegate swift import spikesdk override func application( application uiapplication, didfinishlaunchingwithoptions launchoptions \[uiapplication launchoptionskey any]? = nil) > bool { spike configure() } android important notes about background delivery on android background delivery is scheduled to run every hour but ultimately android decides when the delivery will be executed android may throttle the frequency of updates for background delivery depending on the app's activity, battery state, etc android may stop background delivery if it detects that the app is not active for a long time there is a limit of queries that can be done in health connect and it is different for foreground and background reads, so please request only essential data to be delivered in background more information on ( health connect documentation ) important the spikesdk, along with any other applications, cannot guarantee data synchronization on a fixed schedule the hourly sync interval serves as a guideline rather than a strict requirement enforced by android consequently, the actual synchronization frequency may vary, occurring hourly, once per day, or during specific system defined events, such as the conclusion of sleep mode or when the device begins charging setup add the following permission to your androidmanifest xml \<uses permission android\ name="android permission health read health data in background" /> flutter specific add includebackgrounddelivery true when asking for permissions try { final request = await connection requesthealthpermissions( statistictypes \[statisticstype steps], includebackgrounddelivery true, ); } on spikeexception catch (e) { log("error $e"); } you can also ask for background delivery permission at the same time as other permissions now you can enable background delivery try { await connection enablebackgrounddelivery( statistictypes \[statisticstype steps], sleepconfigs \[ sleepconfig(includemetrictypes {metrictype heartrate}) ], ); } on spikeexception catch (e) { log("error $e"); } keep in mind that calling enablebackgrounddelivery will overwrite previous configuration so you have to call it with all the data types you want in one call to check current configuration call getbackgrounddeliveryconfig() method to stop background delivery call disablebackgrounddelivery() method