Core Bluetooth State Preservation and Restoration Not Working, Can't relaunch app into background
CoreBluetooth
state restoration only applies to connection and peripheral events. Solely relying on scanning is not currently supported.
How to trigger Core Bluetooth state preservation and restoration
NB Thanks to user1785784 for sharing Apple's QA1962 - Conditions Under Which Bluetooth State Restoration Will Relaunch An App which describes new Bluetooth behaviour in iOS 11. This document should be considered the answer to this question, although I think it incorrectly claims that iOS 10 would relaunch an app that has been force quit. (I haven't tested that on an iOS 10 device, but it would have been a departure from iOS 9. Can anyone confirm?).
Killing the app manually (B) from the task switcher, ensures your app will not be launched automatically until the user explicitly opens it again.
C doesn't work either, I think only VOIP apps are launched automatically after restart, and then only after the device is unlocked.
I don't know any D.
I use A.
First, to implement Bluetooth State Restoration, make sure you've
- added
bluetooth-central
as aUIBackgroundModes
to your Info.plist - set a
CBCentralManagerOptionRestoreIdentifierKey
when initing yourCBCentralManager
- implemented the
-(void)centralManager:willRestoreState:
callback in yourCBCentralManager
delegate.
Then you're ready to test state restoration:
- get the app to some known state (say bluetooth powered on, some device connected/connecting)
- kill the app in Xcode
- watch the logs or set a launch breakpoint
- make a change in the bluetooth state, e.g. by
- toggling airline mode
- taking a bluetooth device out of range (to avoid walking, I put mine in a conductor/Faraday Cage/coffee pot)
- bring the device back into range
- interacting with device, e.g. by pressing a button/having a pulse
- watch your state restoration code be called
NB: application:didFinishLaunchingWithOptions:
will be called first, and you must immediately init your CBCentralManager
as described above. Then centralManager:willRestoreState:
will be called.
CoreBluetooth and State Preservation & Restoration when peripheral needs special ACK
These two comments from Paulw11 helped me understand what was going on:
No, that doesn’t happen. If you have a pending discovery, a pending “connect” or you have an active notify on a characteristic then iOS will relaunch your app so that it can handle the discovery, the connection or the notification. iOS can’t do this on your behalf; it doesn’t know what you want to do. – Paulw11
Having your Bluetooth object attached to a view controller is a bad idea if you want to perform operations in the background. I suggest a singleton or an object owned by your app delegate – Paulw11
First, I was under the wrong assumption that iOS will try to handle all bluetooth communication on behalf of my app when my app was in the background and iOS had to kill it. The reality is that iOS starts the app in background mode for a limited period of time so that you can run your restoration code.
Finally, having the logic in the viewDidLoad
of my ViewController was wrong. I have created a BluetoothManager
class and I instantiated it in the application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
method of my AppDelegate
Core Bluetooth - startScanningForPeripherals not working in background after app terminated and started in background
As Apple tech support mentioned, we determined the service UUID we were scanning for was NOT contained in the first advertising packet of the peripheral.
Once we updated the peripheral's firmware with this fix, scanning in the background after the app has been terminated by iOS works great.
Related Topics
Swift Dynamic Table Cell Height
Send Image Along with Other Parameters with Afnetworking
Could an iOS Application Read/Access Sms Text
Perform Action by Clicking on Some Word in Uitextview or Uilabel
Wkwebview and Uimenucontroller
Adjusting Uiview Height Inside Uistackview Control
Facebook Registration:The Operation Couldn't Be Completed (Com.Facebook.Sdk Error 2)
Swift: Change Status Bar Color for iOS 13
Image in Tableviewcell Swipe Action
Uiimagepickercontroller in Swift 3
The Bundle's Info.Plist Does Not Contain a Cfbundleversion Key or Its Value Is Not a String
How to Determine If a User Has an iOS App Installed
Programmatically Highlight Uibarbuttonitem
Get Sms Broadcast with Text Body Without Jailbreak But Private Frameworks in iOS
Nsdateformatter Datefromstring Always Returns Nil
iOS 10 - App Crashes to Access Photo Library or Device Camera via Uiimagepickercontroller