Skip to content
CARP Docs
Ask AISystemLightDark
On this page

Installation

Add carp_connectivity_package to a CAMS app and configure Android and iOS.

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

The package needs the CARP Mobile Sensing (CAMS) setup plus the permissions of the measures you collect:

MeasureAndroid permissionsiOS keys and capabilities
CONNECTIVITYNoneNone
WIFIACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATIONNSLocationWhenInUseUsageDescription, the Access Wi-Fi Information capability
BLUETOOTHBLUETOOTH_SCAN, BLUETOOTH_CONNECT; on Android 11 and lower also BLUETOOTH, BLUETOOTH_ADMIN and ACCESS_FINE_LOCATIONNSBluetoothAlwaysUsageDescription
BEACONBLUETOOTH_SCAN, ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION; on Android 11 and lower also BLUETOOTH and BLUETOOTH_ADMINNSBluetoothAlwaysUsageDescription, NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription

Set up the package in four steps:

  1. Add the packages

    flutter pub add carp_core carp_mobile_sensing carp_connectivity_package

    The package runs on CAMS, so complete the CAMS setup in Installation first.

    Note

    By default, an app resolves flutter_blue_plus 2.x, which needs a commercial license for commercial use. When the app is built for Android, version 2.x also tries to send license telemetry. To keep the BSD-licensed 1.x, add it with a version constraint:

    flutter pub add 'flutter_blue_plus:^1.36.8'
  2. Configure Android

    Add the permissions that your measures need, as listed in the table above, to android/app/src/main/AndroidManifest.xml. With all four measures, the manifest has these entries:

    android/app/src/main/AndroidManifest.xml
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
        <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
        <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-feature android:name="android.hardware.bluetooth_le" android:required="false" />
    
        <!-- ... the rest of your manifest -->
    </manifest>

    Each entry has this purpose:

    EntryWhy
    ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATIONAndroid returns the Wi-Fi name and access point address only to apps with precise location, and beacon scanning needs precise location. On Android 11 and lower, flutter_blue_plus also needs it to scan. Android asks for both permissions in one dialog.
    ACCESS_BACKGROUND_LOCATIONCAMS asks for location all the time for BEACON and starts the measure only when it is granted.
    BLUETOOTH_SCANBluetooth scanning on Android 12 or later. CAMS asks for it for BLUETOOTH and BEACON.
    BLUETOOTH_CONNECTflutter_blue_plus needs it to scan on Android 12 or later, because it reads device names, and asks for it when a scan starts.
    BLUETOOTH, BLUETOOTH_ADMINBluetooth scanning on Android 11 and lower. The Android Beacon Library, which dchs_flutter_beacon uses, adds both to the merged manifest too.
    bluetooth_le featureTells Google Play that the app uses Bluetooth Low Energy but also installs on phones without it.

    The plugins add ACCESS_NETWORK_STATE and ACCESS_WIFI_STATE to the merged manifest themselves. The Android Beacon Library also adds ACCESS_COARSE_LOCATION, FOREGROUND_SERVICE_LOCATION and RECEIVE_BOOT_COMPLETED, even when the app does not collect BEACON.

    If the app does not collect BEACON, you can add android:usesPermissionFlags="neverForLocation" to BLUETOOTH_SCAN to declare that the app does not derive location from Bluetooth scans. Leave the flag off for BEACON: with it, Android filters some beacons out of the scan results, as Android's Bluetooth permissions guide explains.

  3. Configure iOS

    Add the usage descriptions to ios/Runner/Info.plist. NSBluetoothAlwaysUsageDescription is for BLUETOOTH and BEACON, NSLocationWhenInUseUsageDescription for WIFI and BEACON, and NSLocationAlwaysAndWhenInUseUsageDescription for BEACON:

    ios/Runner/Info.plist
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>This app scans for nearby Bluetooth devices and beacons for a research study.</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>This app uses your location to read the Wi-Fi network name and detect nearby beacons.</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>This app detects nearby beacons in the background for a research study.</string>

    To read the Wi-Fi name and access point address, select Runner → Signing & Capabilities in Xcode, click + Capability and add Access Wi-Fi Information. A Personal Team, the free team of an Apple account, cannot add this capability.

    Xcode adds the entitlement to ios/Runner/Runner.entitlements:

    ios/Runner/Runner.entitlements
    <key>com.apple.developer.networking.wifi-info</key>
    <true/>

    CAMS asks for the iOS permissions through permission_handler, which compiles in only the permissions that the app turns on. How you turn them on depends on how Flutter builds the iOS plugins: with Swift Package Manager, the default from Flutter 3.44, or with CocoaPods:

    Swift Package ManagerCocoaPods

    permission_handler turns on the permissions whose usage descriptions are in Info.plist, so no other change is needed. After you change the keys, delete Xcode's derived data once so that Xcode reads them again:

    rm -rf ~/Library/Developer/Xcode/DerivedData

    Turn on the Bluetooth and location permissions in the post_install block of ios/Podfile. Keep any other permissions that your app uses in the same list:

    ios/Podfile
    post_install do |installer|
      installer.pods_project.targets.each do |target|
        flutter_additional_ios_build_settings(target)
        target.build_configurations.each do |config|
          config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
            '$(inherited)',
            'PERMISSION_BLUETOOTH=1',
            'PERMISSION_LOCATION=1',
          ]
        end
      end
    end
  4. Register the sampling package

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

    import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';
    import 'package:carp_connectivity_package/connectivity.dart';
    
    void main() async {
      CarpMobileSensing.ensureInitialized();
      SamplingPackageRegistry().register(ConnectivitySamplingPackage());
    
      await SmartPhoneClientManager().configure();
      // ... the rest of your app
    }

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

    Registering makes the four measure types and their data and configuration classes known to CAMS. It also adds the Wi-Fi and Bluetooth name hashing to the default privacy schema. configure() restores the studies saved on the phone and needs these classes to read them.

Troubleshooting

Bluetooth measurements hold errors

Check that Bluetooth is on and that the participant granted the Bluetooth permissions. On Android 11 and lower, also check that precise location is granted and Location Services are on. Each failed scan window records an error whose message starts with Error scanning for bluetooth - .

Wi-Fi measurements have no network name

Ask for location access in the app: CAMS does not ask for it on behalf of WIFI. See Location permission.

On Android, the participant must also allow precise location, and Location Services must be on. On iOS, the app also needs the Access Wi-Fi Information capability.

Next step

Quickstart

Build an app that collects all four measures and prints them.

Quick links

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