Skip to content
CARP Docs
Ask AISystemLightDark
On this page

Installation

Add carp_movisens_package to a CAMS app and configure Bluetooth on Android and iOS.

Copy MarkdownOpen inOpen in GitHubView as MarkdownOpen in Scira AIOpen in ChatGPTOpen in ClaudeOpen in Cursor

Setting up the Movisens package takes four steps on top of the CARP Mobile Sensing (CAMS) setup:

  1. Add the packages

    flutter pub add carp_core carp_mobile_sensing carp_movisens_package

    The package needs CAMS, so complete Installation for CAMS first.

    The package brings in the movisens_flutter and flutter_blue_plus plugins. They talk to the sensor directly over Bluetooth Low Energy (BLE), so there is no Movisens SDK to install.

  2. Configure Android

    flutter_blue_plus declares no permissions, so that each app chooses its own. Add these entries to android/app/src/main/AndroidManifest.xml, directly above the <application> element:

    android/app/src/main/AndroidManifest.xml
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
    
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    The permissions serve these purposes:

    PermissionAndroid versionsPurpose
    BLUETOOTH_SCAN12 or laterFind the sensor. The neverForLocation flag tells Android that the app does not derive location from scans.
    BLUETOOTH_CONNECT12 or laterConnect to the sensor.
    BLUETOOTH, BLUETOOTH_ADMIN11 and lowerUse Bluetooth before Android 12.
    ACCESS_FINE_LOCATION11 and lowerGet scan results before Android 12.
    ACCESS_COARSE_LOCATIONAllPass the location check that CAMS makes before it connects a Bluetooth device, on every Android version.

    Keep android:maxSdkVersion="30" on ACCESS_FINE_LOCATION. If the app also declares it for Android 12 or later, the participant must allow precise location. With approximate location only, permission_handler reports the location permission as denied, and CAMS does not connect.

    The uses-feature entry tells Google Play that the app uses BLE but does not require it. Set android:required="true" to offer the app only to phones with BLE.

    flutter_blue_plus needs minSdk 21 or later, which is lower than CAMS needs, so android/app/build.gradle.kts needs no change.

  3. Configure iOS

    Add the Bluetooth usage description and the bluetooth-central background mode to ios/Runner/Info.plist, inside the top-level <dict>:

    ios/Runner/Info.plist
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>The study connects to your Movisens sensor to record your activity.</string>
    <key>UIBackgroundModes</key>
    <array>
      <string>bluetooth-central</string>
    </array>

    iOS shows the text in its Bluetooth permission dialog the first time the app uses Bluetooth. It terminates an app that uses Bluetooth without the key.

    The bluetooth-central mode lets iOS deliver data from the sensor while the app is in the background. In Xcode, it is Uses Bluetooth LE accessories under Signing & Capabilities → Background Modes. If UIBackgroundModes already exists, add bluetooth-central to its array.

    The package needs no other keys and works with the CAMS minimum of iOS 15.0.

    Note

    With CocoaPods, permission_handler reports the Bluetooth permission as denied without asking, unless ios/Podfile defines PERMISSION_BLUETOOTH=1. CAMS does not check this permission on iOS, so the macro is optional.

  4. Register the sampling package

    Register the package in main(), before you configure SmartPhoneClientManager:

    import 'package:carp_core/carp_core.dart' hide Smartphone;
    import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';
    import 'package:carp_movisens_package/carp_movisens_package.dart';
    
    void main() {
      CarpMobileSensing.ensureInitialized();
      SamplingPackageRegistry().register(MovisensSamplingPackage());
      // ... the rest of your app
    }

    Call CarpMobileSensing.ensureInitialized() before register(): registering a sampling package before CAMS is initialized throws a null check error.

    Registering MovisensSamplingPackage makes the six measure types, the MovisensDevice configuration and its device manager known to CAMS. CAMS can then read protocols that contain the sensor, including protocols created with CAMS 1.x. configure() restores the studies saved on the phone, so the package must be registered before it runs.

    Registering also adds heart rate and step count transformers to the Open mHealth (OMH) format of CAMS. For the Fast Healthcare Interoperability Resources (FHIR) format, it adds a heart rate transformer.

Troubleshooting

The analyzer reports that Smartphone is ambiguous

Hide Smartphone when you import carp_core. Both carp_core and carp_mobile_sensing define the class, and CAMS apps use the one in carp_mobile_sensing:

import 'package:carp_core/carp_core.dart' hide Smartphone;
The status changes to disconnected right after connect() on Android

Check that the manifest declares ACCESS_COARSE_LOCATION without android:maxSdkVersion, and call requestPermissions() on the device manager before connect(). The log shows the message "has not the permissions required to connect".

If the app declares ACCESS_FINE_LOCATION for Android 12 or later, the participant must allow precise location, not approximate location.

The sensor is not found on Android 11 or lower

Ask the participant to turn on location in the phone's settings. On Android 11 or lower, flutter_blue_plus scans only while location is on, and otherwise it reports "Location services are required for Bluetooth scan". Android 12 and later do not need it.

Scans fail in release builds on Android

Keep the classes of flutter_blue_plus in release builds. Add this line to android/app/proguard-rules.pro:

android/app/proguard-rules.pro
-keep class com.lib.flutter_blue_plus.* { *; }

Without it, scans in release builds fail with PlatformException(startScan, Field androidScanMode_ ... not found.

Version solving fails on flutter_blue_plus

If another package in your app requires flutter_blue_plus 2.x, use a version of that package that works with 1.x. movisens_flutter requires flutter_blue_plus ^1.29.1, so flutter pub get cannot resolve the dependencies otherwise.

Next step

Quickstart

Build an app that prints tap markers and skin temperature.

Quick links

Page · DocumentationCARP DocumentationPage · DocumentationIntroductionPage · DocumentationQuickstartPage · DocumentationTerminologyPage · DocumentationArchitecture