"Turn" Core Bluetooth Framework II: Background processing

Source: Internet
Author: User

Original URL: http://southpeak.github.io/blog/2014/07/31/core-bluetoothkuang-jia-zhi-er-:hou-tai-chu-li/

When developing BLE-related applications, there are a lot of resource limitations when applying in the background, and you need to consider the application's background processing issues. By default, when the program is in the background or hangs, most normal core Bluetooth tasks are not available, either the central or the peripheral side. But we can state that our app supports core Bluetooth background execution mode to allow programs to wake up from the suspended state to handle Bluetooth-related events.

However, even if our application supports the core Bluetooth background execution mode on both ends, it cannot run all the time. In some cases, the system may shut down our app to free up memory, providing more memory space for the current foreground application. In IOS7 and later versions, Core Bluetooth supports saving state information for central and peripheral manager objects and recovering this information when the program starts. We can use this feature to support long-time tasks related to Bluetooth devices.

We will discuss these issues in detail below.

Applications that support only foreground operations (FOREGROUND-ONLY)

Most apps go into a suspended state for a short time after entering the background, unless we request some specific background tasks to be performed. When processing a pending state, our app cannot continue to perform Bluetooth related tasks.

On the central side, foreground-only applications cannot continue to scan and discover the peripheral device under the advertisement when it enters the background or hangs. On the peripheral side, it is not possible to advertise itself, and the central end will return an error for any access operation.

When the Foreground-only app hangs, all Bluetooth related events are put into a queue by the system, and when the app enters the foreground, these events are sent to our app. That is, when certain events occur, Core Bluetooth provides a way to prompt the user. Users can use these hints to decide whether to put the app in the foreground. In "One of the Core Bluetooth frameworks: Central and peripheral" we introduced the Connectperipheral:options: method, which we can set by the device options parameter when invoking this method:

    1. Cbconnectperipheraloptionnotifyonconnectionkey: When the app hangs, if a connection succeeds, use this key value if we want the system to display a hint for the specified peripheral.
    2. Cbconnectperipheraloptionnotifyondisconnectionkey: When the app hangs, this key value is used if we want the system to display a disconnect prompt for the specified peripheral if the connection is disconnected.
    3. Cbconnectperipheraloptionnotifyonnotificationkey: When the app is suspended, using that key value indicates that a prompt is displayed whenever a notification is received on a given peripheral side.
Core Bluetooth Background execution mode

We can set the core Bluetooth background execution mode in the Info.plist file to allow the app to perform some Bluetooth related tasks in the background. When the app declares this feature, the app wakes up to allow it to handle Bluetooth-related tasks. This feature is useful for applications that interact with BLE, which periodically sends data.

There are two core Bluetooth background execution modes, one for the central side operation and one for the peripheral end operation. If our application implements both ends of the function at the same time, it is necessary to declare both modes supported. We need to add the Uibackgroundmodes key to the Info.plist file while adding the following two values or one of them:

    1. Bluetooth-central (APP communicates using Corebluetooth)
    2. Bluetooth-peripheral (App shares data using Corebluetooth)
Bluetooth-central mode

If the Bluetooth-central value is set, our app will still be able to find and connect to the peripheral device while in the background, and find the appropriate data. In addition, the system wakes up our app when the Cbcentralmanagerdelegate or Cbperipheraldelegate proxy method is invoked, allowing the app to handle events such as establishing a connection or disconnecting, and so on.

While the app is in the background, we can do a lot of Bluetooth related tasks, but we need to keep in mind that the app is still different when scanning the peripheral device in front of the background. When our app scans the peripheral device in the background,

    1. Cbcentralmanagerscanoptionallowduplicateskey scan options are ignored, and multiple discovery events on the same peripheral side are aggregated into one discovery event.
    2. If multiple applications that scan the peripheral device are in the background, the time interval for the central device to scan ad data increases. As a result, it may take a long time to discover an ad's peripheral device.

These treatments are useful for minimizing the use of radios in iOS devices and for improving battery life.

Bluetooth-peripheral mode

If the Bluetooth-peripheral value is set, when our app is in the background, the app wakes up to handle read, write, and subscribe requests from the central side of the connection, and Core Bluetooth allows us to advertise in the background. Similar to the central side, it is important to note the difference between the front and rear stations. Especially when it comes to advertising, there are several differences:

    1. Cbadvertisementdatalocalnamekey Advertising key value will be ignored, the peripheral side of the local name will not be advertised
    2. The UUID of all services of the Cbadvertisementdataserviceuuidskey key is placed in a "overflow" area, and they can only be discovered by those network devices that display to scan them.
    3. If multiple apps are in a background ad, the time interval for peripheral devices to send ad packets becomes longer.
In the background CEO (long-term) task

Although it is recommended that background tasks be completed as soon as possible, some should still use core Bluetooth to perform a long task. This involves saving and resuming the state.

State preservation and recovery

Because state saving and recovery is built into the core Bluetooth, our program can choose this feature to let the system save the state of central and peripheral manager and continue to perform some Bluetooth related tasks, even if the program no longer runs at this time. When one of these tasks is completed, the system restarts the program in the background, and the program can revert to the previous state to handle the event. Core Bluetooth supports state saving and recovery on the central and peripheral side, and can support both.

On the central side, the system saves the state of the central Manager object when the program frees memory (if there are multiple central managers, we can choose which manager the system tracks). For a given Cbcentralmanager object, the system keeps track of the following information:

    1. Services scanned by Central Manager
    2. The central manager attempted or connected peripheral
    3. Features of the central Manager subscription

On the peripheral side, for a given Cbperipheralmanager object, the system tracks the following information:

    1. Data for Peripheral manager ads
    2. Services and features published by the peripheral manager to the device database
    3. Subscribe to the central side of the peripheral manager's attribute value

When the system restarts the program into the background, we can re-initialize the central and peripheral manager of our program and restore the status. We'll look at how to use state saving and recovery in more detail next.

Add state save and restore support

State save and restore in Core Bluetooth is an optional feature that requires program support to work. We can add support for this feature by following these steps:

    1. (Required steps) Optionally join state save and restore when assigning and initializing central or peripheral manager objects.
    2. (Required steps) reinitialize the central or peripheral manager object when the system restarts the program
    3. (necessary steps) to implement the appropriate recovery agent method
    4. (optional step) to update the central or peripheral manager initialization process
Selective join state preservation and recovery

To selectively join the state Save and Restore feature, provide a unique recovery identity when assigning and initializing central or peripheral manager. The recovery Identity is a note string used to let core Bluetooth and programs identify central or peripheral manager. The value of the string is only meaningful in your own code, but this string tells the core Bluetooth that we need to save the state of the object. Core Bluetooth saves only those objects that have a recovery identity.

For example, when implementing the central side, in order to selectively join the state Save and Restore feature, when initializing the Cbcentralmanager object, you can specify the initialization option Cbcentralmanageroptionrestoreidentifierkey, and provide a recovery ID, as shown in the following code:

centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionRestoreIdentifierKey: @"restoreIdentifier"}];

The implementation of the peripheral side is similar, except that we use the option Cbperipheralmanageroptionrestoreidentifierkey key.

Because a program can have more than one central or peripheral manager, you need to ensure that the recovery identity is unique so that the system can differentiate between these manager objects.

Reinitialize Central or peripheral manager objects

When the system restarts the program into the background, the first thing we need to do is to use the recovery identity to reinitialize the objects. If our application has only one central manager or peripheral manager, and the manager exists throughout the lifetime of the program, then we don't need to do more processing in the future. But if we have more than one manager, or if the manager is not in the entire life cycle of the program, we need to know which manager to reinitialize when the system restarts the application. We can access the list of manager objects by using the appropriate startup option key in the Application:didfinishlaunchingwithoptions: Method of the Program proxy object (this list is a program shutdown that is saved by the system for the program).

The following code shows that when the program restarts, we get the recovery identity for all central manager objects:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    // Override point for customization after application launch.    NSArray *centralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];    // TODO: ...    return YES;}

With this list of recovery identities, we can reinitialize the manager objects we need.

Implementing the appropriate recovery agent approach

After the central or peripheral manager objects are reinitialized, we restore them by synchronizing the state of those objects by using the state of the Bluetooth system. At this point, we need to implement some recovery agent methods. For the central manager, we implement the Centralmanager:willrestorestate: Proxy method; For the peripheral manager manager, we implement the Peripheralmanager: Willrestorestate: Proxy method.

For applications that opt-in to save and restore features, these methods are the first method that the program launches into the background to complete some Bluetooth-related tasks. For non-opt-in applications, Centralmanagerdidupdatestate: and Peripheralmanagerdidupdatestate: Proxy methods are called first.

In the two proxy methods above, the last parameter is a dictionary that contains information about the manager that was saved when the program was closed. As shown in the following code, we can use the Cbcentralmanagerrestoredstateperipheralskey key to get a list of all the peripheral devices that the central manager has connected or attempted to connect to:

- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)state{    NSArray *peripherals = state[CBCentralManagerRestoredStatePeripheralsKey];    // TODO: ...}

Once we get to this list, we can do the processing as needed.

Update initialization process

After implementing the previous three steps, we may want to update our manager's initialization process. Although this step is optional, it is useful if you want to confirm that the task is working correctly. For example, our program may be closed while parsing the data of the connected peripheral device. When the program uses this peripheral device for recovery operations, there is no way to know where the data is being processed. We need to make sure that the program continues to start at the point where the data operation stopped.

Again, as shown in the following code, when initializing a program operation in the Centralmanagerdidupdatestate: Proxy method, we can find out whether the specified service for the restored peripheral device has been successfully discovered:

NSUInteger serviceUUIDIndex = [peripheral.services indexOfObjectPassingTest:^BOOL(CBService *obj, NSUInteger index, BOOL *stop) {        return [obj.UUID isEqual:myServiceUUIDString];    }];    if (serviceUUIDIndex == NSNotFound) {       [peripheral discoverServices:@[myServiceUUIDString]];       ...}    

As described in the preceding example, if the system closes the app when the program completes the search service, it calls the Discoverservices: method to parse the recovered peripheral data at the point at which it was closed. If the program successfully searches for the service, we can confirm whether the search has the correct attributes. By updating the initialization process, we can ensure that the correct method is called at the correct time.

Summary

Although we may need to declare that the app supports the core Bluetooth background execution mode to accomplish a specific task, it is always prudent to consider performing background operations. Because too many Bluetooth-related tasks require the use of an iOS device's built-in radio, and the use of the radio affects the life of the battery, minimizing the tasks performed in the background. Any app that wakes up by a Bluetooth-related task should process the task as soon as possible and re-suspend it when it finishes.

Here are some basic guidelines:

    1. The app should be session-based and provide an interface to allow users to decide when to start and end the distribution of Bluetooth-related events.
    2. Once awakened, an app has about 10s of time to complete the task. Ideally, the app should complete the task as soon as possible and re-suspend it. The system can limit or even kill background tasks that take too long to execute.
    3. When an app is awakened, it should not perform trivial operations.

"Turn" Core Bluetooth Framework II: Background processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.