Unexpected CoreBluetooth background suspension without active location updates

I am implementing BLE scanning and connection using CoreBluetooth in a Flutter application with native iOS Swift code.

BLE scanning and connection work correctly in the foreground and for a short time after the app is sent to the background. However, after some time in the background, BLE scanning stops and the device is no longer discovered. The app appears to be suspended by iOS.

Key Observation: When location services are actively in use (navigation arrow visible in the iOS status bar), BLE scanning and reconnection work reliably in the background. When location services are not actively running, BLE scanning stops in the background even though the app has “Always Allow” location permission. Expected Result BLE scanning and connection should continue to function in the background using the Bluetooth LE background mode, without relying on active location updates. Actual Result BLE scanning starts successfully App enters background After some time, scanning stops Device is no longer discovered BLE works again only if location services are actively running BLE Connection Behavior One-time scan connects successfully to a BLE medical device App is sent to background Existing connection does not disconnect However, new scans or reconnections fail once the app is suspended Relevant Native iOS Code (AppDelegate) import Flutter import UIKit import CoreBluetooth

@main @objc class AppDelegate: FlutterAppDelegate {

private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {

    GeneratedPluginRegistrant.register(with: self)

    if let identifiers =
        launchOptions?[UIApplication.LaunchOptionsKey.bluetoothCentrals] as? [String] {
        print("App relaunched for BLE state restoration: \(identifiers)")
    }

    NotificationCenter.default.addObserver(
        self,
        selector: #selector(appDidEnterBackground),
        name: UIApplication.didEnterBackgroundNotification,
        object: nil
    )

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

@objc private func appDidEnterBackground() {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        self.endBackgroundTask()
    }
}

private func endBackgroundTask() {
    if backgroundTaskID != .invalid {
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

}

Questions for DTS: Is it expected behavior that CoreBluetooth background scanning effectively stops once the app is suspended, even when the Bluetooth LE background mode is enabled? Why does BLE background scanning appear to work reliably only when location services are actively running? Is iOS internally associating BLE background execution with active location updates?

For continuous BLE reconnection (medical device use case), is the recommended approach to rely solely on CoreBluetooth state restoration instead of continuous background scanning? Is it considered best practice to avoid long-running BLE scans in the background and instead wait for system-delivered BLE events?

Additional Notes Issue is reproducible on real devices Not using private APIs or unsupported background execution methods Objective is to follow Apple-recommended, App Store–compliant behavior

Unexpected CoreBluetooth background suspension without active location updates
 
 
Q