Skip to content

Configure Health

To use this package, import it into your app together with the carp_mobile_sensing package:

import 'package:carp_core/carp_core.dart';
import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';
import 'package:carp_health_package/health_package.dart';
import 'package:health/health.dart';

Before creating a study and running it, register this package in the SamplingPackageRegistry.

SamplingPackageRegistry().register(HealthSamplingPackage());

Now we can define a study protocol with a health device:

// Create a study protocol
StudyProtocol protocol = StudyProtocol(
ownerId: 'owner@dtu.dk',
name: 'Health Sensing Example',
);
// Define which devices are used for data collection.
// First add this smartphone.
final phone = Smartphone();
protocol.addPrimaryDevice(phone);
// Create and add a health service (device)
final healthService = HealthService();
protocol.addConnectedDevice(healthService, phone);

There are two ways to use the health package in a CAMS protocol:

  • Defining a App Task where the user is asked to collect his/her own health data
  • Defining a Background Sensing Task, where health data is collected in the background

Defining an app task to collect health data is done using the HealthAppTask task, like this:

// Create a health app task for the user to collect his own health data once per day
protocol.addTaskControl(
PeriodicTrigger(period: Duration(hours: 24)),
HealthAppTask(
title: "Press here to collect your physical health data",
description:
"This will collect your weight, exercise time, steps, and sleep "
"time from the Health database on the phone.",
types: [
HealthDataType.WEIGHT,
HealthDataType.STEPS,
HealthDataType.BASAL_ENERGY_BURNED,
HealthDataType.SLEEP_SESSION,
],
),
phone,
);

In this case, a user task will be added to the task list once per day and when the user clicks (start) this user task, the health data types specified in the list of types are collected. Once data collection is done, the user task is marked as done in the task list.

Background sampling of health data can be configured by a measure in the protocol. This measure is created using the factory method HealthSamplingPackage.getHealthMeasure() that takes a list of of HealthDataType types.

// Automatically collect the set of health data every hour.
//
// Note that the [HealthSamplingConfiguration] is a [HistoricSamplingConfiguration]
// which samples data back in time until last time, data was sampled.
protocol.addTaskControl(
PeriodicTrigger(period: Duration(minutes: 60)),
BackgroundTask(
measures: [
HealthSamplingPackage.getHealthMeasure([
HealthDataType.STEPS,
HealthDataType.BASAL_ENERGY_BURNED,
HealthDataType.WEIGHT,
HealthDataType.SLEEP_SESSION,
]),
],
),
healthService,
);

Background sensing of health data is done by the HealthService specified in the protocol above.

One way to ensure that health data is collected while the app is in foreground, is to add the collection of health measures to an App Task (e.g., a survey):

protocol.addTaskControl(
RecurrentScheduledTrigger(
type: RecurrentType.daily,
time: TimeOfDay(hour: 13),
),
RPAppTask(
type: SurveyUserTask.SURVEY_TYPE,
name: 'WHO-5 Survey',
rpTask: who5Task,
measures: [
Measure(type: SensorSamplingPackage.AMBIENT_LIGHT),
HealthSamplingPackage.getHealthMeasure([
HealthDataType.HEART_RATE,
HealthDataType.STEPS,
])
]),
phone);

In this case, ambient light, heart rate and steps are collected as part of the user filling in a WHO-5 survey.

Another option is to use a AppLifecycleTrigger which triggers data sampling when the app resumes, i.e., comes to the foreground.

// Automatically collect the set of health data when the app resumes, i.e. comes
// to the foreground.
//
// Note that the [HealthSamplingConfiguration] is a [HistoricSamplingConfiguration]
// which samples data back in time until last time, data was sampled.
protocol.addTaskControl(
AppLifecycleTrigger({AppLifecycleState.resumed}),
BackgroundTask(
measures: [
HealthSamplingPackage.getHealthMeasure([
HealthDataType.STEPS,
HealthDataType.BASAL_ENERGY_BURNED,
HealthDataType.WEIGHT,
HealthDataType.SLEEP_SESSION,
]),
],
),
healthService,
);

The health measures are one-time measures, which implies that health data is collected when the measure is triggered. In the examples above, this happens either when the user clicks the user task or periodically (once per hour). Configuration of what data to collect is done via the HealthSamplingConfiguration which is used to override the default configuration (default is to collect nothing). The getHealthMeasure() factory method is a convenient way to create a Measure with the correct HealthSamplingConfiguration.

The HealthSamplingConfiguration can be configured to collect a set of HealthDataType data, like:

  • BODY_FAT_PERCENTAGE,
  • HEIGHT,
  • WEIGHT,
  • BODY_MASS_INDEX,
  • WAIST_CIRCUMFERENCE,
  • STEPS,
  • …

See the HealthDataType documentation for a complete list.

A HealthSamplingConfiguration is a HistoricSamplingConfiguration. This means that when triggered, the task and measure will try to collect data back to the last time data was collected. Hence, this measure is suited for configuration using some trigger that collects data on a regular basis, like the PeriodicTrigger used above.

See the example.dart file for a full example of how to set up a CAMS study protocol for this sampling package.