Problems saving and restoring Bluetooth iOS kernel state

I have a question regarding state preservation and recovery for Core Bluetooth on iOS 7.

I can not get it to work correctly. I followed every pointer that Apple mentions in its documentation for basic bluetooth, as well as in the general documentation for saving state.

For example: Basic Bluetooth background image processing for iOS applications and here: Saving and restoring iOS status

I can get general state saving for working with the device (for controllers and viewing objects, etc.), but not for the bluetooth manager.

As far as I know, the checklist looks like this:

  • Choose save and restore when you select and initialize the central manager object by assigning a recovery identifier in the options dictionary for the CBCentralManagerOptionRestoreIdentifierKey key.

  • Restore any central manager objects after restarting the application. This is done in the application delegate when the application is called: doneFinishLaunchingWithOptions :. Here I have to look for the UIApplicationLaunchOptionsBluetoothCentralsKey in the parameter dictionary, and then restore the CBManager with this key. This is where everything goes wrong, because there are never identifiers for this key, and therefore I can’t restore it.

  • Implement the appropriate delegation method. I took this step too, but since the manager was never re-created, I never get this delegate responder.

The application works fine in the background, and I followed all the steps for this part.

Now, having said all this, I am not sure how to test this, and this may be part of this problem. The way I do it now is to press the home button on the iOS device (executive device) so that it puts the application in the background and returns to the main screen. By doing this, I can say that all regular stateful calls are received when viewing the log output. After that, I exit the application by clicking the stop button in Xcode to kill the background process. Now I will restart the application through Xcode, and again now I can see how the usual regular state-saving code is executed, and the state is restored in everything except the bluetooth manager.

If this is wrong, then please let me know. But overall, I'm very confused by this, as Core Bluetooth docs say that saving only happens when "your application is restarted by the system." What does it mean? I also read a post on the Apple Developers Forum that since the release of iOS 7, the OS will now never restart the application for any reason if the user kills the application manually, which I do.

Any help in this regard would be greatly appreciated!

/A

+6
source share
3 answers

When you press the Home button to send an application to a background image, it pauses and can process Bluetooth delegates and run in the background for 10 seconds, this function can be implemented by adding "bluetooth central in the background in info.plist" and Do not use state conservation and restoration.

If your application is completed iOS, due to lack of memory , it can no longer handle Bluetooth delegates. In this case, if you used State Preservation and Restoration, your application can be restarted in the background to restart, and also in just 10 seconds. After 10 seconds, it will move to a suspended state. Only in this situation can CBCentralManager willRestoreState be launched.

You can add code

[kill(getpid(), SIGKILL);] 

to the action of the button, when you press the button, your application will terminate iOS as if killed by memory pressure, and then willRestoreState will be called.

Good luck.

+6
source

First, note that maintaining the state of view controllers has nothing to do with restoring basic Bluetooth managers.

It is important . Recovery does not work for scans, static characteristics and, as a rule, any use cases that do not generate connection-related events.

Now steps:

  • Make sure the following is indicated in the application under test:
    • peripheral manager advertises
    • peripheral manager connected centers
    • central tries to connect to a peripheral device
    • central connected to some peripherals
  • Use this app to kill your app: https://github.com/ddaddy/BackgroundKill (kudos to ddaddy, give a star to the repo)
    • Switch to killer app
    • Start the kill process and wait until it is completed by the system.
    • Now your application is killed
  • Make some kind of connection event
    • (tested peripherals) subscribe to peripheral specifications
    • (Tested peripheral device) starts reading dynamic performance requests.
    • (Tested in the center) make the connection request successful
    • (Central tested) update signed peripheral features

Depending on what you want to check, consider the applicable items in the list. Use the registration in the tested application and follow the logs in the organizer to find out what happens with time.

+3
source

I managed to get this to work with scanning in the background (along with connecting and transmitting data). There is an important difference between how your application was terminated and if iOS saves and restores your primary Bluetooth manager.

The addition “Application communicates using CoreBluetooth” to “Required Backgrounds” in Info.plist covers most situations. Your central manager will continue to work in the background - either when the user presses the home button or locks the phone (or both). However, you will never get the delegate call "willRestoreState" in these scenarios, since your central manager is still being processed by your application (it is still in memory).

Saving and restoring only takes effect in one scenario - your application was interrupted by iOS due to memory limitations. The easiest way to get this to test the loading of three games with intensive memory, while your application is in the background. If you look at the device console, you are waiting for this message:

 "Apr 4 13:16:47 Michaels-iPhone SpringBoard[58] <Warning>: Application 'UIKitApplication:com.oculeve.TearBud[0x6df4]' was killed by jetsam." 

At the moment, iOS will take over the central manager. If it scans, it will continue to scan; if it connects to a peripheral device, it will continue to connect. If you get a call from the central manager delegate (didDiscoverPeripheral, didUpdateValueForCharacteristic), iOS will launch your application in the background again. At this point, you will receive an invitation from the willRestoreState delegate . At this point, your application will return to memory and will work as described above. Please note that you will need to do some recovery in willRestoreState if you were connected to the device. All of this is described in a video with Bluetooth support in WWDC 2013 format.

It seems that the kicker that restore / save does not work if you manually close the application from the system tray (by scrolling the application). I assume that Apple reasoned that in this case the user explicitly closes the application, and all Bluetooth communication should stop. This is also true when the user restarts his phone. I assume that this is due to the fact that rebooting is basically equal to scrolling up to close all applications in the system tray. If you get to this point, you can only reconnect after the user opens your application again.

Something that needs to be noted is that your application is in the system tray does not mean it in memory.

Why Apple doesn’t just tell you this, the documentation goes for me.

0
source

All Articles