question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

iOS: Not scanning in background

See original GitHub issue

My 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

  1. Enable bluetooth and wi-fi on iPad

  2. Run App1 in debug mode

  3. Press button “Search device”.

  4. 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:closed
  • Created 4 years ago
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
kjersbrycommented, Aug 12, 2019

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

0reactions
kjersbrycommented, May 18, 2020

Take this answer with a pinch of salt as I’m not too sure about this, sorry: I think scanning works. Since App.OnSleep() is apparently terminated after a few seconds, calling the scan function directly from there will probably not work. So right now I’m using Xamarin.Forms.MessagingCenter to send a start-scan message from App.OnSleep(), and the receiver of the message starts the scan. That seems to work as long as scanning is starting very quickly after App.OnSleep() is called, that is, before the app is terminated by the system again. As mentioned it does still not discover the device at every try, but I rather think that’s the advertising and scanning intervals that don’t match since it works sometimes. Cancelling the scan with ScanTimeout or CancellationTokenSource.CancelAfter() does still not work in background mode.

Do you have a sample of how you made this work? We’re running into a similar issue with background scanning not working on iOS, and I’m curious how you’ve implemented it with MessagingCenter.

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Background scanning not working wi…
I trying to connect peripheral using UUID in the background, It's working only when i interact with advertising beacon first time at foreground...
Read more >
Background scanning not working without having last ...
iOS looks for advertising packets only in background [Passive] mode and not the response packets Searching further bought me to this link.
Read more >
iOS — Scan and Connect to a BLE peripheral in the ...
The Apple documentation states that applications are allowed to scan while backgrounded but the scan must specify the service types. Passing nil ...
Read more >
iOS: Not scanning in background · Issue #371
My app is supposed to scan for and connect to specific devices in the background. It works well on Android, but on iOS...
Read more >
Background scanning for advertisements in iOS apps
In short, iOS allows only limited scanning windows for "backgrounded" apps, and having a particularly long ad interval may cause the iPhone/iPad to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found