iOS 7 Core Bluetooth Peripheral running in backgro

2019-03-09 13:10发布

What I want is for my iOS device to be advertising a Bluetooth LE service all the time, even when the app isn't running, so that I can have another iOS device scan for it and find it. I have followed Apple's backgrounding instructions here:

https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/PerformingCommonPeripheralRoleTasks/PerformingCommonPeripheralRoleTasks.html#//apple_ref/doc/uid/TP40013257-CH4-SW1.

I can get it to advertise in the foreground ok and sometimes in the background but it doesn't stay advertising all the time. If you have it setup to run in the background, shouldn't it start advertising even after a device restart, just like background location services automatically start working after a restart? Are their limitations to the backgrounding that are not listed (or hard to find) in Apple's docs? Does anyone have an example of a Core Bluetooth Peripheral advertising correctly in the background?

Thanks...

2条回答
淡お忘
2楼-- · 2019-03-09 13:21

Background advertisement is possible if you add the bluetooth-peripheral backgrounding mode to the app's plist. Once you do that, your app will continue to receive the callbacks even if backgrounded.

The advertisement is a tricky beast as Apple implemented several optimizations to reduce the power consumption and these reduce the quality of the advertisement as soon as the app is backgrounded. Namely: the rate is reduced severely, the advertised services are not included and the local name is not included either. Once the app comes back to foreground, these restrictions are invalidated.

In the general case, this kind of backgrounded operation requires the app to be running. With iOS 7 the restoration process has been implemented that allows the OS to act on the app's behalf while it is terminated and restore the app when some transmission or other operation is imminent. This requires you to add the restoration key to the initialization options of the CBPeripheralManager/CBCentralManager. Starting your application once is still required but after that, iOS will continue to act as the BLE facade towards the centrals/peripherals.

UPDATE: I ran a loop on the Apple bluetooth-dev list as well with this question and found that Core Bluetooth managers were declared to be not able to restore after reboot. This is not described in any documentation but probably was mentioned in the WWDC videos. We should file a bug and replicate it to raise Apple's awareness.

查看更多
做自己的国王
3楼-- · 2019-03-09 13:41

The implementation can be founded here: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/PerformingCommonPeripheralRoleTasks/PerformingCommonPeripheralRoleTasks.html#//apple_ref/doc/uid/TP40013257-CH4-SW5

Its very simply actually.

<CBPeripheralManagerDelegate>

@property (strong, nonatomic) CBPeripheralManager *peripheralManager;

...

- (NSDictionary*) advertiseNotBeacon {
    CBUUID *myCustomServiceUUID = [CBUUID UUIDWithString:@"MY_UUID"];

    CBMutableCharacteristic *myCharacteristic = [[CBMutableCharacteristic alloc] initWithType:myCustomServiceUUID
                                                                                   properties:CBCharacteristicPropertyRead | CBCharacteristicPropertyNotify
                                                                                        value:nil permissions:CBAttributePermissionsReadable];

    CBMutableService *myService = [[CBMutableService alloc] initWithType:myCustomServiceUUID primary:YES];
    myService.characteristics = @[myCharacteristic];

    self.peripheralManager.delegate = self;
    [self.peripheralManager addService:myService];

    return @{CBAdvertisementDataServiceUUIDsKey : @[myService.UUID],
             CBAdvertisementDataLocalNameKey: @"MY_NAME"
             };
}

...

[self.peripheralManager startAdvertising:[self advertiseNotBeacon]];

Doing this, you will start advertising a peripheral service.

Now, if you want to keep the service running in background, read the documentation in this link: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html#//apple_ref/doc/uid/TP40013257-CH7-SW1

Quick steps: Open info.plist Add a new par key/value

Required background modes
      App shares data using CoreBluetooth

Apple says to ctrl + click on any key/value and add a add the following, but exactly the same as explained before.

UIBackgroundModes
      bluetooth-peripheral 

Dont forgot about the limitations of running the service in background:

  • The CBCentralManagerScanOptionAllowDuplicatesKey scan option key is ignored, and multiple discoveries of an advertising peripheral are coalesced into a single discovery event. If all apps that are scanning for peripherals are in the background, the interval at which your central device scans for advertising packets increases. As a result, it may take longer to discover an advertising peripheral.
  • These changes help minimize radio usage and improve the battery life on your iOS device.
查看更多
登录 后发表回答