0
votes

I'm working with a Bluetooth peripheral that after connecting to it there is a ACK back and forth before it actually can send me the data that I need.

The flow is like this:

  1. Discover the peripheral
  2. Connect to the peripheral
  3. Discover services and characteristics
  4. Listen for updates on a specific characteristic
  5. Peripheral sends a special message to this characteristic
  6. The app then sends an ACK to the peripheral
  7. The peripheral sends me the data needed by the app

I have implemented the needed logic in the protocol method for State Preservation and Restoration centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any])

Question 1:

When the app is in the background and iOS decides to take over the Bluetooth communication (for resource reasons), how will iOS manage to do steps 5, 6 and 7?

Because if it can't then the peripheral won't be able to send the data that the app needs in step 7.

Question 2:

In the docs I read that iOS might start your app for a few seconds. Will the viewDidLoad method of my root ViewController be executed in that case? That's where I instantiate the CBCentralManager


Some of the many online resources that I've found:

Core Bluetooth Background Processing for iOS Apps

Zero to BLE on iOS – Part Three

1
I am not sure what you mean by question 1: your code is responsible for communicating with the peripheral in the appropriate sequence, even if it is in the background. 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 delegatePaulw11
@Paulw11 question 1 is based on the impression that iOS will not start my app, but will try to handle all the communication with the peripheral itself (since it had to kill my app for resource reasons).72lions
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
@Paulw11 you are correct! I refactored some of the code, moved it up inside AppDelegate and initial tests seem to give me the results that I expect. Will run it for a longer period of time to double check.72lions

1 Answers

0
votes

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