iOS: Not scanning in background
See original GitHub issueMy app is supposed to scan for and connect to specific devices in the background. It works well on Android, but on iOS it doesn´t behave as expected - the device is not found, and StartScanningForDevicesAsync()
does not return after the ScanTimeout (60 secs) has elapsed.
Everything works when the app is running in the foreground. Connecting in the background also works: If I let it scan and find the device in the foreground and then exit the app, it will connect successfully in the background. Only scanning is not working in the background.
I have added the bluetooth-central key to UIBackgroundModes in info.plist, and I am using a service UUID filter with one UUID in StartScanningForDevicesAsync()
.
I´m a bit stuck, any help is greatly appreciated!
Here´s a repo with a simple app that has the relevant functionality (that is, the connection part is not included here): https://github.com/kjersbry/sampleBLE/tree/master/App1/App1 (service UUID is hardcoded as “46a970e0-0d5f-11e2-8b5e-0002a5d5c51b”)
Steps to reproduce
-
Enable bluetooth and wi-fi on iPad
-
Run App1 in debug mode
-
Press button “Search device”.
-
Within 5 seconds (before application outputs “done sleeping”), lock screen or press home button to exit app
Expected behavior
The app should execute StartScanningForDevicesAsync()
in the background 5 seconds after the Search button is pressed, and either discover the device or reach the scan timeout elapsed statements in StartScanningForDevicesAsync()
after 60 seconds.
Expected output = output when running in foreground:
019-08-06 14:52:24.493 SensorHub.iOS[572:1795357] done sleeping
Thread started: <Thread Pool> #7
Thread started: <Thread Pool> #8
2019-08-06 14:52:24.524 SensorHub.iOS[572:1795380] Starting scan for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
8/6/2019 2:52:24 PM: Adapter: Waiting for state: PoweredOn
8/6/2019 2:52:24 PM: Adapter: Starting a scan for devices.
8/6/2019 2:52:24 PM: Adapter: Scanning for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
Thread started: #9
8/6/2019 2:52:25 PM: DiscoveredPeripheral: Nonin3230_XXXX, Id: XXXXXX
2019-08-06 14:52:25.356 SensorHub.iOS[572:1795357] Discovered periperhal. Name: "Nonin3230_XXXX "
8/6/2019 2:52:25 PM: Adapter: Stopping the scan for devices.
8/6/2019 2:52:25 PM: Adapter: Scan was cancelled.
2019-08-06 14:52:25.367 SensorHub.iOS[572:1795398] Scan has finished for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
Actual behavior
The app starts executing StartScanningForDevicesAsync()
in the background 5 seconds after the Search button is pressed, but after the application output from Trace.Message("Adapter: Scanning for " + serviceCbuuids.First());
in StartScanningForDevicesNativeAsync()
I don´t get any output (except from Thread started ...
etc)
Output when doing as specified in “Steps to reproduce”:
2019-08-06 14:47:03.154 SensorHub.iOS[570:1794598] done sleeping
2019-08-06 14:47:03.173 SensorHub.iOS[570:1794704] Starting scan for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
8/6/2019 2:47:03 PM: Adapter: Waiting for state: PoweredOn
8/6/2019 2:47:03 PM: Adapter: Starting a scan for devices.
8/6/2019 2:47:03 PM: Adapter: Scanning for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
… then no more output from the plugin
If I then wait for more than 60 seconds (=letting the scan time out) and then open the app again, I immediately get this output:
8/6/2019 2:49:29 PM: Adapter: Scan timeout has elapsed.
Thread started: <Thread Pool> #15
8/6/2019 2:49:29 PM: Adapter: Stopping the scan for devices.
2019-08-06 14:49:29.989 SensorHub.iOS[570:1795019] Scan has finished for 46a970e0-0d5f-11e2-8b5e-0002a5d5c51b
2019-08-06 14:49:29.990 SensorHub.iOS[570:1795019] ConnectionResult: DEVICE_NOT_FOUND
Crashlog
none
Configuration
Version of the Plugin: 2.0.1.
Platform: iOS 12.4.
Device: iPad 6th gen
Issue Analytics
- State:
- Created 4 years ago
- Comments:10 (2 by maintainers)
Top GitHub Comments
Thank you for the tip, but it doesn’t seem to change the behaviour. However, I’m not sure if I did “step 2. reinstantiate your central manager” correctly. In AppDelegate.FinishedLaunching, I tried calling UseRestorationIdentifier(“SameKeyAsBefore”) and then setting the IBluetoothLE property to CrossBluetoothLE.Current again. But I’m not sure if this really affects _centralManager…
Edit: I tried starting the scan when App.OnSleep() is called, then it discovered the device a couple of times in background mode, but not at all attempts. I think the advertising interval of the peripheral vs the background mode scan interval is also a part of the problem. However, it does still not cancel on the taskcancellation in background mode, my guess is that the cancellation is not an event that wakes the app up to background mode
Sorry, I was working on this during a summer internship, so I don’t have access to the code anymore. But I remember it being pretty straight-forward with the messaging center: put the subscriber in the module where you want to start the scan, and let it start the scan when it receives a message.