Spike SDK Usage

Step 1 - Create Spike connection

To set up the Spike SDK create SpikeSDKV3 instance with your Spike application id, application user id and signature unique to each of your apllication users (more on generating signatures here):

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;
}