Skip to content

Install and Configure

This guide shows how to install carp_mobile_sensing and configure a Flutter app on Android and iOS.

Install Package

Add CAMS dependencies to pubspec.yaml and fetch packages.

Configure Android

Configure permissions, services, and Gradle settings.

Configure iOS

Add Info.plist keys and AppDelegate notification setup.

Validate Setup

Build and verify permissions on physical devices.

Add dependencies in pubspec.yaml:

environment:
sdk: ">=3.10.0 <4.0.0"
flutter: ">=3.38.1"
dependencies:
flutter:
sdk: flutter
carp_serializable: ^latest
carp_core: ^latest
carp_mobile_sensing: ^latest

Then run:

Terminal window
flutter pub get
  1. Add required permissions

    Include permissions for activity recognition, notifications, foreground execution, and battery behavior.

  2. Configure plugin services/receivers

    Add both flutter_background and flutter_local_notifications declarations in <application>.

  3. Enable desugaring in Gradle

    Add isCoreLibraryDesugaringEnabled = true and the desugar dependency in android/app/build.gradle.kts.

Add permissions for:

  • activity recognition
  • notifications (including scheduled notifications)
  • foreground/background execution
  • foreground service types used by flutter_background
android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application ...>
</manifest>

Inside <application>, declare both plugin services:

android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application ...>
...
<service
android:name="de.julianassmann.flutter_background.IsolateHolderService"
android:exported="false"
android:foregroundServiceType="dataSync|specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Collection of data while app is in background."/>
</service>
</application>
</manifest>
android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application ...>
...
<service
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
android:exported="false"
android:stopWithTask="false"/>
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
</application>
</manifest>

In android/app/build.gradle.kts, enable desugaring and add dependency (required by local notifications):

android/app/build.gradle.kts
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}

Both the flutter_local_notification and the flutter_background plugins use the ic_launcher.png as the icon for notifications. Hence, this icon should be added as a drawable resource to the the Android head project in the android/app/src/main/res/drawable/ folder. You typically copy the /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png icon.

  1. Add Info.plist permissions

    Add motion permission for step tracking and optional file-sharing keys.

  2. Configure notifications in AppDelegate

    Register flutter_local_notifications callback and keep plugin registration.

Add motion permission for step tracking:

ios/Runner/Info.plist
<plist version="1.0">
<dict>
...
<key>NSMotionUsageDescription</key>
<string>This application tracks your steps</string>
</dict>
</plist>

Optional (used in example to expose files in Finder):

ios/Runner/Info.plist
<plist version="1.0">
<dict>
...
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
</dict>
</plist>

For flutter_local_notifications, add plugin registrant callback:

import flutter_local_notifications
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}

Then keep:

GeneratedPluginRegistrant.register(with: self)
  1. Refresh and resolve dependencies

    Terminal window
    flutter clean
    flutter pub get
  2. Build on each platform

    Terminal window
    flutter run -d android
    flutter run -d ios
  3. Verify runtime permissions

    Grant notification and motion/activity permissions on device and confirm background behavior.