Mobile SDKs

SpikeSDK Android

current android(kotlin) sdk version 4 2 62 android package package can be found here ( api reference ) example app can be found here requirements android 9 0+ (level 28, p, pie) setup guide to add the sdk to your 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' } } } after that, add the following to your app's build gradle file in the dependencies block dependencies { // other dependencies implementation "com spikeapi sdk\ spike sdk 4 2 42" } 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 may lead to play store rejections \<! few examples of commonly used permissions > \<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 exercise"/> xml extensive permissions \<! extensive list of hc permissions, pick the ones required for your user flows > \<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> to handle android 14 you also need to add activity alias to your androidmanifest xml it is just a wrapper for the activity that requests permissions so no real activity is necessary \<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> spike sdk usage step 1 create spike connection to set up the spike sdk create spikeconnectionv3 instance with your spike application id, auth token and user id unique to each of your users // replace with your api credentials provided exclusively to you private const val app id = 1000 val spikeconnection = spikeconnectionapiv3 createconnection( applicationid = app id, signature = "xxxxx", enduserid = "user id", context = context ) step 2 ask user for permissions if you want to read data from android health connect, you have to ensure user gives your app permissions first, you have to check if health connect is available on users phone val hcavailability = spikeconnection checkhealthconnectavailability() where public enum class healthconnectavailabilitystatus(public val value string) { / the health connect sdk is unavailable on this device at the time this can be due to the device running a lower than required android version apps should hide any integration points to health connect in this case / not installed("not installed"), / the health connect sdk apis are currently unavailable, the provider is either not installed or needs to be updated apps may choose to redirect to package installers to find a suitable apk / update required("update required"), / the health connect sdk apis are available / installed("installed"), } if update is required, you can use spike helper to open play store for user to install health connect spikeconnection openhealthconnectinstallation() if health connect is installed, you can get permissions that are needed and a list of already provided permissions // hc integration has to be enabled in spikesdk connection before // using further methods for reading data or managing permissions spikeconnection enablehealthconnectintegration() val permissionmanager = spikeconnection gethealthconnectpermissionmanager() val requiredpermissions = permissionmanager getpermissionsforstatistics( statisticstypes = setof(statisticstype steps, statisticstype distance total) ) val grantedpermissions = permissionmanager getgrantedpermissions() if you have missing permissions you can ask android to present user with a modal asking user for permission to read the data example for compose val permissionlauncher = rememberlauncherforactivityresult( permissionmanager getrequestpermissionresultcontract(), onresult = { } ) please note that users might only grant partial permissions in such cases, it’s up to you to decide whether your app can function effectively with limited access the spikesdk itself will still operate even without full permissions; however, it may result in no data being returned in certain scenarios conversely, if your app has been granted additional permissions beyond the minimum required for specific data types, we may enhance certain entries by incorporating data sourced from other types (e g , identifying manually entered data) you can now use statisticsfilter(providers = listof(provider health connect)) to specifically retrieve data from health connect alternatively, you can omit the providers parameter entirely and allow spike to choose the most suitable data source based on your request 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 get daily statistics for steps and total distance from health connect val dailystatistics = spikeconnection getstatistics( types = setof(statisticstype steps, statisticstype distance total), from = localdate now() minusweeks(1) atstartofday(zoneid systemdefault()) toinstant(), to = instant now(), interval = statisticsinterval day, filter = statisticsfilter(providers = listof(provider health connect)) ) where enum class statisticstype(public val value string) { steps("steps"), distance total("distance total"), distance walking("distance walking"), distance cycling("distance cycling"), distance running("distance running"), calories burned total("calories burned total"), calories burned basal("calories burned basal"), calories burned active("calories burned active") } // interval statisticsinterval hour statisticsinterval day public data class statisticsfilter( val excludemanual boolean = false, val providers list\<provider>? = null ) // result public data class statistic( val start instant, val end instant, val duration int, val type statisticstype, val value double, val unit com spikeapi apiv3 datamodels unit, val rowcount int?, val recordids list\<uuid>? ) records get all records we have from garmin provider val records = spikeconnection getrecords( types = setof(metrictype steps total, metrictype calories burned total), from = localdate now() minusweeks(1) atstartofday(zoneid systemdefault()) toinstant(), to = instant now(), filter = statisticsfilter(providers = listof(provider garmin)) ) where public enum class metrictype(public val value string) { calories burned active("calories burned active"), calories burned basal("calories burned basal"), calories burned("calories burned"), calories intake("calories intake"), steps total("steps"), distance total("distance"), distance walking("distance walking"), distance cycling("distance cycling"), distance running("distance running"), distance wheelchair("distance wheelchair"), distance swimming("distance swimming"), } // result public data class record( val recordid uuid, val inputmethod inputmethod?, val startat instant, val endat instant?, val modifiedat instant, val duration int?, val provider provider?, val providersource providersource?, val issourceaggregated boolean?, val source recordsource?, val metrics map\<string, double>?, val activitytags list\<activitytag>?, val activitytype activitytype?, val sessions list\<activityentry>?, val laps list\<activityentry>?, val segments list\<activityentry>?, val splits list\<activityentry>?, val samples list\<activitysamples>?, val routepoints list\<activitysamples>? ) reading data statistics get daily statistics for steps and total distance from garmin val dailystatistics = spikeconnection getstatistics( types = setof(statisticstype steps, statisticstype distance total), from = localdate now() minusweeks(1) atstartofday(zoneid systemdefault()) toinstant(), to = instant now(), interval = statisticsinterval day, filter = statisticsfilter(providers = listof(provider garmin)) ) where // interval statisticsinterval hour statisticsinterval day // filter public data class statisticsfilter( val excludemanual boolean = false, val providers list\<provider>? = null ) records get all records we have from garmin provider val records = spikeconnection getrecords( types = setof(metrictype steps total, metrictype calories burned total), from = localdate now() minusweeks(1) atstartofday(zoneid systemdefault()) toinstant(), to = instant now(), filter = statisticsfilter(providers = listof(provider garmin)) ) where public enum class metrictype(public val value string) { calories burned active("calories burned active"), calories burned basal("calories burned basal"), calories burned("calories burned"), calories intake("calories intake"), steps total("steps"), distance total("distance"), distance walking("distance walking"), distance cycling("distance cycling"), distance running("distance running"), distance wheelchair("distance wheelchair"), distance swimming("distance swimming"), } // result public data class record( val recordid uuid, val inputmethod inputmethod?, val startat instant, val endat instant?, val modifiedat instant, val duration int?, val provider provider?, val providersource providersource?, val issourceaggregated boolean?, val source recordsource?, val metrics map\<string, double>?, val activitytags list\<activitytag>?, val activitytype activitytype?, val sessions list\<activityentry>?, val laps list\<activityentry>?, val segments list\<activityentry>?, val splits list\<activityentry>?, val samples list\<activitysamples>?, val routepoints list\<activitysamples>? ) 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 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" /> check if background delivery is possible with current health connect version val hcavailability = spikeconnection gethealthconnectpermissionmanager() isfeatureavailable(healthconnectfeature read health data in background) if not, you can ask user to update health connect to the latest version ask for background read permission val permissionmanager = spikeconnection gethealthconnectpermissionmanager() val requiredpermissions = permissionmanager getpermissions( // you can add other permissions as well statistics, sleep, etc includebackgrounddelivery = true ) val permissionlauncher = rememberlauncherforactivityresult( permissionmanager getrequestpermissionresultcontract(), onresult = { } ) permissionlauncher launch(requiredpermissions) you can also ask for background delivery permission in the same time as other permissions now you can enable background delivery connection enablebackgrounddelivery( backgrounddeliveryconfig( statisticstypes = setof(statisticstype steps) ) ) keep in mind that calling enablebackgrounddeliverywill overwrite previous configuration if you want to add more types, you have to call enablebackgrounddeliveryagain with updated configuration connection enablebackgrounddelivery( backgrounddeliveryconfig( statisticstypes = setof(statisticstype steps), activitytypes = setof(activitytype running, activitytype walking) ) ) to check current configuration call getbackgrounddeliveryconfig()method to stop background delivery call disablebackgrounddelivery()method reading logs by default spikesdk logs are sent to standard android logcat if for some reason you want to read them, you can use the following code (running it before you start using spikesdk) spikeconnectionapiv3 setlogcallback { level, message > when (level) { loglevel verbose > {} loglevel debug > if(buildconfig debug) { log d("spikesdk", message) } loglevel warning > log w("spikesdk", message) loglevel error > log e("spikesdk", message) } } if you are utilising background delivery, this code should be run in your application's oncreatemethod class myapplication application() { override fun oncreate() { super oncreate() spikeconnectionapiv3 setlogcallback { level, message > when (level) { loglevel verbose > {} loglevel debug > if(buildconfig debug) { log d("spikesdk", message) } loglevel warning > log w("spikesdk", message) loglevel error > log e("spikesdk", message) } } } } also application should be set in androidmanifest xml \<application android\ name=" myapplication" \>