SDK

Bluetooth Low-Energy Beacons

Bluetooth Low-Energy (BLE) Beacons complement GPS-based geofencing by allowing highly precise, proximity-based experiences — such as detecting when a user enters a store, approaches a product area, or interacts with a specific in-store device.

By enabling beacon detection, the Actito SDK can trigger campaigns, update user profiles, or log proximity events whenever the device detects a configured beacon region. Beacon-based triggers can operate both in the foreground and background, depending on device capabilities and permissions.

While this feature works out of the box on iOS using CLLocationManager, it requires additional development on Android.

Requesting Permissions

Beacon scanning requires additional permissions, particularly on Android 12 (API level 31) and above. To supports beacon detection, request the Bluetooth Scan permission :

void _onEnableLocationUpdatesClicked() async {
  try {
    final hasFullCapabilities = await _ensureForegroundLocationPermission() &&
        await _ensureBackgroundLocationPermission() &&
        await _ensureBluetoothScanPermission();

    // Calling enableLocationUpdates() will evaluate the given permissions, if any, and enable the available capabilities.
    await ActitoGeo.enableLocationUpdates();
  } catch (error) {
    // Handle the platform error.
  }
}

Future<bool> _ensureBluetoothScanPermission() async {
  if (await Permission.bluetoothScan.isGranted) return true;

  if (await Permission.bluetoothScan.isPermanentlyDenied) {
    // TODO: Show some informational UI, educating the user to change the permission via the Settings app.
    await openAppSettings();
    return false;
  }

  if (await Permission.bluetoothScan.shouldShowRequestRationale) {
    await showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: const Text('Sample'),
            content: const Text('We need access to bluetooth scan in order to show relevant content.'),
            actions: [
              TextButton(
                onPressed: () async {
                  if (await Permission.bluetoothScan.request().isGranted) {
                    _onEnableLocationUpdatesClicked();
                  }
                },
                child: const Text('Ok'),
              ),
            ],
          );
        });

    return false;
  }

  return await Permission.bluetoothScan.request().isGranted;
}

The snippet above uses the permission_handler plugin to handle the bridge into native permissions. You can use any other plugin or implement the bridge yourself. The focus of the snippet is guiding you on the necessary permissions and recommended upgrade path.

Automatic Behaviour

Once permissions are granted and location updates are enabled, the Actito SDK automatically manages beacon scanning alongside standard geofencing.

When active, the SDK will:

  • Continuously scan for BLE beacons defined in your Actito dashboard.
  • Trigger campaigns or notifications when entering or exiting beacon regions.

This makes the Beacons module a fully managed extension of the Location Services module — no additional code is required beyond enabling location updates.

Beacon Scanning with a Foreground Service

On Android Oreo (API 26) and higher, background BLE scans are subject to strict system limits. While the first beacon detection occurs quickly, subsequent detections — such as leaving a beacon’s range — may take up to 15 minutes when the app is running in the background. This limitation is imposed by Android itself, and there is no way to bypass it while remaining in background mode.

To improve beacon detection responsiveness, you can opt into foreground scanning, which runs as a foreground service. Foreground services are always active and display a persistent notification to the user.

Enable this feature by adding the following metadata entry to your app’s AndroidManifest.xml:

<meta-data
    android:name="com.actito.geo.beacons.foreground_service_enabled"
    android:value="true" />