Unable to Run iOS App for more than 30 to 40 seconds even the backgroundtask is integrated

We are integrating Auto-door unlock application for iOS. This app should start scanning for Beacons first, from didRangeBeacons in the region(), we get major & minor value, then we prepare a customized CBUUID Service using
Code Block
computedService = CBUUID(string: "\(major+minor)-xxxx-xxxx-xxxx-xxxxxxxxxxxx")

and then start scanning for BLE Peripheral
Code Block
centralManager.scanForPeripherals(withServices: [computedService], options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])


App Launches -->
Start Scanning for iBeacon Region with UUID(uuidString: "{Provided UUID}") only (Minor value will be different)

when
Code Block
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in the region: CLBeaconRegion)
 
callback is received,
we are extracting Major & Minor value from the detected beacon, preparing a Service UUID string based on this value

e.g. if the Major value is: 00 & Minor value is "11", concatenating this will be "0011" and adding this final value as a prefix of device service UUID e.g. "0011-xxxx-xxxx-xxxx-xxxxxxxxxxxx" to start scanning for BLE Peripheral.

So my BLECentralManager object would start scanning as

self?.bleCentralManager.scanForPeripherals(withServices: "0011-xxxx-xxxx-xxxx-xxxxxxxxxxxx", options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])

Once the BLE Peripheral is detected, the rest of the BLE Operations are performed on this peripheral (i.e. Making a connection, sending data to a specific characteristic, and at last Drop the connection).

This works well in foreground mode.

Now, To Run the same operation for "App Not running state / Killed State", I have added the Location manager's didEnterRegion & didExitRegion monitoring.

I am getting a callback when a user enters into the beacon range and sends a local notification too. During this, we have started beacon ranging and initiated background task as below:
Code Block
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        guard region is CLBeaconRegion else { return }
        self.showLocalNotification(title: "Thank you", body: "You're in my region now!")
        manager.startRangingBeacons(in: region as! CLBeaconRegion)
        self.extendBackgroundRunningTime()  
}
// Extending Background Execution Time
func extendBackgroundRunningTime() {
        if (self.backgroundTask != .invalid) {
            return
        }
        self.backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "DummyTask", expirationHandler: {           
UIApplication.shared.endBackgroundTask(self.backgroundTask)
            self.backgroundTask = .invalid
        })
        if threadStarted {
            print("Background task thread already started.")
        } else {
            threadStarted = true
            DispatchQueue.global(qos: .default).async {
                while (true) {
                    Thread.sleep(forTimeInterval: 1);
                }
            }
        }
}


When beacon ranging identifies the beacon detail, I need to get major, minor value, prepare a CBUUID string (as mentioned above), make a connection, and process door-open operation (for app killed state)

but I am not getting a callback in

Code Block
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)

within 30 seconds time. I have read that backgroundTask can extend app time for 3 minutes. But I am getting 30/40 seconds hardly during iBeacon Ranging and unable to scan the BLE peripheral

Can you please help me how can I achieve the behaviour for Background mode?
The ability to extend the background execution for 3 minutes was many iOS versions ago and is no longer true. 30 seconds is your current limit now.

Putting aside that how you are switching between the iBeacon and GATT protocols is out of spec by definition and could be riddled with issues down the road, and how this whole thing could be architected in a more efficient manner, 30 seconds should be enough to finish what you are trying to do.

Start by making sure that when in iBeacon mode the device is advertising to spec at 100ms, and when in GATT mode it is advertising at 20 ms intervals. That is the only way you can get away with a discovery/connect/disconnect cycle within 30 seconds.

Also keep in mind that your app's inability to perform Bluetooth operations in a killed state is by design, and by working around that limitation you are going against the wishes of the users, and the long term success of such workarounds can never be guaranteed.


So Technically, if I want to Unlock my Door whenever I am nearer to it using only CoreBluetooth technology, how can I achieve it if iBeacon and Background tasks are not a solution?

Using just a CoreBluetooth technology, can I make my app awake whenever I am approaching a door even if my BLE connection is not established?

For the current scenario, we only connect with BLE Peripheral when iBeacon distance is around 20cm. Then after the successful connection, we are writing few data to unlock the door and then drop the connection.


Unable to Run iOS App for more than 30 to 40 seconds even the backgroundtask is integrated
 
 
Q