carp_mobile_sensing 0.6.4

  • Readme
  • Changelog
  • Example
  • Installing
  • 76

CARP Mobile Sensing Framework in Flutter #

This library contains the software architecture for the CARP sensing framework implemented in Flutter. Supports cross-platform (iOS and Android) sensing.

pub package

For Flutter plugins for other CARP products, see CARP Mobile Sensing in Flutter.

Usage #

To use this plugin, add carp_mobile_sensing as a dependency in your pubspec.yaml file.

Android Integration #

Add the following to your app's manifest.xml file located in android/app/src/main:

<manifest xmlns:android=""

    <!-- The following permissions are used for CARP Mobile Sensing -->
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


NOTE: Version 0.5.0 is migrated to AndroidX. This should not result in any functional changes, but it requires any Android apps using this plugin to also migrate if they're using the original support library. See Flutter AndroidX compatibility

Documentation #

The Dart API doc describes the different libraries and classes.

The wiki contains detailed documentation on the CARP Mobile Sensing Framework, including the domain model, its built-in probes, and how to extend it.

Below is a few simple / minimum examples (a better description is available on the wiki).

Examples #

In the following example, a study is created "by hand", i.e. you specify each trigger, task and measure in the study.

// Import package
import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';

void example() async {
  // Create a study using a File Backend
  Study study = Study("1234", "",
      name: "An example study",
      dataEndPoint: FileDataEndPoint()
        ..bufferSize = 500 * 1000 = true
        ..encrypt = false);

  // add sensor collection from accelerometer and gyroscope
  // careful - these sensors generate a lot of data!
      DelayedTrigger(delay: 1000), // delay sampling for one second
      Task('Sensor Task')
          MeasureType(NameSpace.CARP, SensorSamplingPackage.ACCELEROMETER),
          frequency: 10 * 1000, // sample every 10 secs
          duration: 2, // for 2 ms
          MeasureType(NameSpace.CARP, SensorSamplingPackage.GYROSCOPE),
          frequency: 20 * 1000, // sample every 20 secs
          duration: 2, // for 2 ms

      PeriodicTrigger(period: 24 * 60 * 60 * 1000), // trigger sampling once pr. day
      Task('Task collecting a list of all installed apps')
        ..addMeasure(Measure(MeasureType(NameSpace.CARP, AppsSamplingPackage.APPS))));

  // creating measure variable to be used later
  PeriodicMeasure lightMeasure = PeriodicMeasure(
    MeasureType(NameSpace.CARP, SensorSamplingPackage.LIGHT),
    name: "Ambient Light",
    frequency: 11 * 1000,
    duration: 700,
  study.addTriggerTask(ImmediateTrigger(), Task('Light')..addMeasure(lightMeasure));

  // Create a Study Controller that can manage this study, initialize it, and start it.
  StudyController controller = StudyController(study);

  // await initialization before starting
  await controller.initialize();

  // listening on all data events from the study;

  // listen on only CARP events => datum.format.namepace == NameSpace.CARP).forEach(print);

  // listen on LIGHT events only => == SensorSamplingPackage.LIGHT).forEach(print);

  // map events to JSON and then print => datum.toJson()).forEach(print);

  // listening on a specific probe registered in the ProbeRegistry
  // this is equivalent to the statement above

  // subscribe to events
  StreamSubscription<Datum> subscription = datum) {
    // do something w. the datum, e.g. print the json
    print(JsonEncoder.withIndent(' ').convert(datum));

  // sampling can be paused and resumed

  // pause / resume specific probe(s)

  // adapt measures on the go - calling hasChanged() force a restart of
  // the probe, which will load the new measure
    ..frequency = 12 * 1000
    ..duration = 500

  // disabling a measure will pause the probe
    ..enabled = false

  // once the sampling has to stop, e.g. in a Flutter dispose() methods, call stop.
  // note that once a sampling has stopped, it cannot be restarted.

However, you can se up a study quite simple, by using sampling schemas. Below is an example of how to add measure to the study by using measures from the common sampling schema.

 // adding a set of specific measures from the `common` sampling schema to one overall task
       ..measures = SamplingSchema.common().getMeasureList(
         namespace: NameSpace.CARP,
         types: [

There is a very simple example app app which shows how a study can be created with different tasks and measures. This app just prints the sensing data to a console screen on the phone.

However, the CARP Mobile Sensing App provides a MUCH better example of how to use the package in a Flutter BLoC architecture, including good documentation of how to do this.

Features and bugs #

Please read about existing issues and file new feature requests and bug reports at the issue tracker.

License #

This software is copyright (c) 2020 Copenhagen Center for Health Technology (CACHET) at the Technical University of Denmark (DTU). This software is made available 'as-is' in a MIT license.

0.6.4 #

  • Support 1.0.0 version of stable dependencies. (dart_lsc)

0.6.3 #

0.6.2 #

  • intensive test of data upload to CARP and Firebase on both Android and iOS
  • support for retry in upload of data to CARP
  • handling that a study id can only be an integer in the CARP web services

0.6.1 #

  • Thorough testing on iOS.
  • Better handling of probes not available on iOS via the initialize method.
  • Centralized concept for handling permissions.

0.6.0 - Trigger Model & Data Manager events #

  • Extension of Study domain model to include support for Trigger, which manages the temporal triggering of data sampling. See the documentation on how to defined a study with triggers.
  • Adjustment of runtime environment to reflect the new study model

    • Addition of a TriggerExecutor
    • Update to Executors, i.e. StudyExecutor, TaskExecutor and Probe
  • The data manager model has been updated

    • A DataManager now expose a stream of state events as defined in DataManagerEventTypes
    • A DataManager now has a type which is a string as defined in DataEndPointTypes
    • These changes are also implemented for the file and CARP data managers.
  • Minor refactoring

    • Apps and AppUsage are no longer periodic measure, but one-off measures. Hence, use the new trigger model to sample installed apps and their usage e.g. on a daily basis.
    • The BluetoothDatum now lists all devices found in a scan.
    • The pedometer now works as a simple step stream which sense and report each step taken.
    • datastore library have been renamed to data_managers.

0.5.1 #

  • Update of readme file.

0.5.0 - AndroidX Compatibility #

  • Breaking change. This version has been migrated from the deprecated Android Support Library to AndroidX. This should not result in any functional changes, but it requires any Android app using this plugin to also migrate if they're using the original support library.
  • Fixed error in PedometerProbe

0.4.0 - Data Transformers and Privacy Support #

  • support for data transformers
    • OMH Geolocation
    • OMH PhysicalActivity
  • support for privacy schema
    • added support for hashing bluetooth names in the bluetooth package
  • upgrade to json_serializable v.2

0.3.10 #

  • minor change to the StreamProbe API - now non-static streams can be used by implementing the get stream method.
  • update of the relevant sampling packages using StreamProbe

0.3.8+9 #

  • update and rename of CARPDataPoint to DataPoint to reflect new CARP API.
  • moved CARP web service specific data model to CARPDataPoint to the carp_webservices package.

0.3.5+6+7 #

  • rename of packages folder to sampling_packages (seems like Dart Pub don't like folders called packages)
  • rename of core folder to domain

0.3.3 #

  • update to new versions of CACHET Flutter Plugins
  • rename of probes folder to packages
  • upgrade and test on Flutter v. 1.3.4 Dart v. 2.2.1

0.3.2 - Sampling Packages #

  • support for dividing probes into separate sampling packages
  • included in carp_mobile_sensing are
    • device (device, screen, memory, battery)
    • sensors (sensors, light, pedometer)
    • connectivity (connectivity, bluetooth)
    • apps (installed apps, app usage)
  • implementation of the following external probe packages:
    • communication (sms & call log)
    • context (location, activity, weather)
    • audio (noise, audio recording)
    • movisens (Movisens Move/ECG devices)

0.3.1 #

  • small updates to the data format incl. documentation on the wiki.
  • fixed error in the stop method.

0.3.0 - Domain Model update #

  • major updates to the domain model as a core library
    • Measure now have a configuration
  • simplification to probe implementations
  • all probes now uses the Dart Stream API and supports a reactive programming model
  • all probes adjusted to a stream model
  • implementation of SamplingSchema architecture
  • support for power-aware sampling using different sampling schemas

0.2.6 #

  • fixed small bug in weater probe.

0.2.5 #

  • small bug fixes in connectivity datum model (to work w. `carp_firebase_backend).
  • weather probe added.

0.2.4 #

  • error in light probe fixed.
  • noise probe added.
  • using the carp_core domain model

0.2.3 #

  • fixed error in readme file.

0.2.2 #

  • phone_log probe added
  • audio probe added
  • activity probe added
  • improvement to readme file on manifest.xml and Info.plist.

0.2.1 #

  • re-organization of github location and outline
  • improvements to FileDataManager to avoid race conditions
  • improved API documentation

0.2.0 #

  • refactor of organization of classes into libraries
  • complete API documentation

0.1.1 #

  • small improvements incl. documentation

0.1.0 #

  • removal of all remote backend code to separate packages

0.0.1 #

  • Initial version by Jakob E. Bardram
  • Transferring the old implementation to this carp.sensing-flutter framework
  • General refactor and clean-up


 * Copyright 2018 Copenhagen Center for Health Technology (CACHET) at the
 * Technical University of Denmark (DTU).
 * Use of this source code is governed by a MIT-style license that can be
 * found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';

void main() => runApp(new CARPMobileSensingApp());

class CARPMobileSensingApp extends StatelessWidget {
  // This widget is the root of your application.
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'CARP Mobile Sensing Demo',
      theme: new ThemeData(
      home: new ConsolePage(title: 'CARP Mobile Sensing Demo'),

class ConsolePage extends StatefulWidget {
  ConsolePage({Key key, this.title}) : super(key: key);

  final String title;

  Console createState() => new Console();

class Console extends State<ConsolePage> {
  String _log = "";
  Sensing sensing;

  void log(String msg) {
    setState(() {
      _log += "$msg\n";

  void clearLog() {
    setState(() {
      _log += "";

  void restart() {
    log("-------------------------------------\nSensing restarted...");

  void initState() {
    sensing = new Sensing(this);

  void dispose() {

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      body: new SingleChildScrollView(
        child: StreamBuilder(
          builder: (context, AsyncSnapshot<Datum> snapshot) {
            if (snapshot.hasData) {
              _log += "${}\n";
              return Text(_log);
            } else if (snapshot.hasError) {
              return Text(snapshot.error.toString());
            return Center(child: CircularProgressIndicator());
      floatingActionButton: new FloatingActionButton(
        onPressed: restart,
        tooltip: 'Restart study & probes',
        child: new Icon(Icons.cached),

/// This class implements sensing incl. setting up a [Study] with [Task]s and [Measure]s.
/// This example is useful for creating a Business Logical Object (BLOC) in a Flutter app.
/// See e.g. the CARP Mobile Sensing App.
class Sensing {
  Study study;
  Console console;
  StudyController controller;

  Sensing(this.console) {
    //DataManagerRegistry.register(DataEndPointType.PRINT, new ConsoleDataManager());
    //DataManagerRegistry.register(DataEndPointType.FILE, new FileDataManager());

  /// (Re)start sensing.
  void start() async {
    console.log("Setting up study...");

    // create the study
    study = Study("2", '',
            name: 'A default / common study',
            dataEndPoint: FileDataEndPoint()
              ..bufferSize = 500 * 1000
     = true
              ..encrypt = false)
                ..measures = SamplingSchema.debug().getMeasureList(
                  namespace: NameSpace.CARP,
                  types: [
//      ..addTriggerTask(ImmediateTrigger(),
//          Task()..measures = SamplingSchema.common(namespace: NameSpace.CARP).measures.values.toList())

    console.log("Setting up '${}'...");

    // print the study to the console

    // Create a Study Controller that can manage this study, initialize it, and start it.
    controller = StudyController(study);
    await controller.initialize();
    console.log("Sensing started ...");

    // listening on all probe events from the study;

    // listening on a specific probe

  /// Stop sensing.
  void stop() async {
    study = null;
    console.log("Sensing stopped ...");

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  carp_mobile_sensing: ^0.6.4

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Fix lib/domain/serialization.dart. (-0.50 points)

Analysis of lib/domain/serialization.dart reported 1 hint:

line 16 col 10: Name non-constant identifiers using lowerCamelCase.

Fix lib/domain/transformers.dart. (-0.50 points)

Analysis of lib/domain/transformers.dart reported 1 hint:

line 19 col 28: Name non-constant identifiers using lowerCamelCase.

Fix lib/runtime/probes.dart. (-0.50 points)

Analysis of lib/runtime/probes.dart reported 1 hint:

line 567 col 16: This function has a return type of 'Future

Fix additional 24 files with analysis or formatting issues. (-0.50 points)

Additional issues in the following files:

  • lib/runtime/sampling_package.dart (1 hint)
  • lib/data_managers/local/file_data_manager.dart (Run flutter format to format lib/data_managers/local/file_data_manager.dart.)
  • lib/domain/datapoint.dart (Run flutter format to format lib/domain/datapoint.dart.)
  • lib/domain/datum.dart (Run flutter format to format lib/domain/datum.dart.)
  • lib/domain/device_info.dart (Run flutter format to format lib/domain/device_info.dart.)
  • lib/domain/measures.dart (Run flutter format to format lib/domain/measures.dart.)
  • lib/domain/sampling_schema.dart (Run flutter format to format lib/domain/sampling_schema.dart.)
  • lib/domain/study.dart (Run flutter format to format lib/domain/study.dart.)
  • lib/domain/tasks.dart (Run flutter format to format lib/domain/tasks.dart.)
  • lib/domain/triggers.dart (Run flutter format to format lib/domain/triggers.dart.)
  • lib/runtime/data_manager.dart (Run flutter format to format lib/runtime/data_manager.dart.)
  • lib/runtime/executors.dart (Run flutter format to format lib/runtime/executors.dart.)
  • lib/runtime/study_controller.dart (Run flutter format to format lib/runtime/study_controller.dart.)
  • lib/sampling_packages/apps/app_probes.dart (Run flutter format to format lib/sampling_packages/apps/app_probes.dart.)
  • lib/sampling_packages/apps/apps.dart (Run flutter format to format lib/sampling_packages/apps/apps.dart.)
  • lib/sampling_packages/apps/apps_datum.dart (Run flutter format to format lib/sampling_packages/apps/apps_datum.dart.)
  • lib/sampling_packages/device/device_datum.dart (Run flutter format to format lib/sampling_packages/device/device_datum.dart.)
  • lib/sampling_packages/device/device_package.dart (Run flutter format to format lib/sampling_packages/device/device_package.dart.)
  • lib/sampling_packages/device/device_probes.dart (Run flutter format to format lib/sampling_packages/device/device_probes.dart.)
  • lib/sampling_packages/sensors/light_probe.dart (Run flutter format to format lib/sampling_packages/sensors/light_probe.dart.)
  • lib/sampling_packages/sensors/pedometer_probe.dart (Run flutter format to format lib/sampling_packages/sensors/pedometer_probe.dart.)
  • lib/sampling_packages/sensors/sensor_datum.dart (Run flutter format to format lib/sampling_packages/sensors/sensor_datum.dart.)
  • lib/sampling_packages/sensors/sensor_package.dart (Run flutter format to format lib/sampling_packages/sensors/sensor_package.dart.)
  • lib/sampling_packages/sensors/sensor_probes.dart (Run flutter format to format lib/sampling_packages/sensors/sensor_probes.dart.)

Maintenance issues and suggestions

Support latest dependencies. (-20 points)

The version constraint in pubspec.yaml does not support the latest published versions for 2 dependencies (permission_handler, stats).


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
app_usage ^0.1.0 0.1.0
archive ^2.0.4 2.0.13
async ^2.0.8 2.4.1
battery >=0.3.0 <2.0.0 0.3.1+9
device_apps ^1.0.8 1.0.9
device_info ^0.4.0 0.4.2+1
flutter 0.0.0
json_annotation ^3.0.0 3.0.1
light ^0.1.0 0.1.1
path_provider ^1.2.0 1.6.5
pedometer ^1.0.0 1.0.0
permission_handler ^4.2.0 4.4.0+hotfix.2 5.0.0+hotfix.2
screen_state ^0.1.0 0.1.1
sensors ^0.4.0 0.4.1+10
stats ^0.2.0 0.2.0+3 1.0.0
system_info ^0.1.0 0.1.2
uuid ^2.0.0 2.0.4
Transitive dependencies
args 1.6.0
charcode 1.1.3
collection 1.14.11 1.14.12
convert 2.1.1
crypto 2.1.4
file_utils 0.1.4
globbing 0.3.0
meta 1.1.8
path 1.6.4
path_provider_macos 0.0.4
path_provider_platform_interface 1.0.1
permission_handler_platform_interface 1.0.0 2.0.0
platform 2.2.1
plugin_platform_interface 1.0.2
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
build_runner any
json_serializable ^3.0.0
test any