CLBeaconRegion, how to turn off warning: Turn On B

2019-02-18 12:47发布

问题:

We have a project that is using CoreLocation regions to monitor iBeacon region entering/exiting in the app background. CLBeaconRegion (CLRegion), CLBeacon, etc. CLLocationManager returns callbacks when a CLBeacon (iBeacon) region is entered. It is a light wrapper around a bluetoothManager underneath.

// various CLLocation delegate callback examples
- (void) locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region;
- (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region;

The problem we're having is that when a user does not have bluetooth turned on, the Iphone issues a system level warning on a regular basis to 'Turn On Bluetooth to Allow "APP_NAME" to Connect ot Accessories'. This happens a lot, I've got it 4 times this morning already as the app runs in the background. CLLocationManager may be attempting to monitor those CLBeaconRegion, but bluetooth is off so it can't do this.

Another post, mentions that CBCentralManager has a property, CBCentralManagerOptionShowPowerAlertKey, that allows disabling this warning.

iOS CoreBluetooth passively check if Bluetooth is enabled without prompting user to turn Bluetooth on

Unfortunately I've found no way to access underlying bluetooth, or any CBCentralManager reference to use this.

Is there any way to disable this warning for CLBeaconRegion monitoring?

回答1:

I worked out a solution that uses CoreBluetooth and CBCentralManager to detect, stop, and start bluetooth usage. Below is the majority of the code, plus an initial check to see if it is on before starting. It works to suppress the error prompt by guaranteeing beacons are not being used when bluetooth is off. If it is disabled, beacons are stopped. The warning thus goes away. We're unable to actually enable/disable bluetooth programmatically unfortunately.

// initialize in viewdidLoad, etc
_bluetoothManager =  [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey:@NO}];


// bluetooth manager state change
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    NSString *stateString = nil;
    switch(central.state)
    {
        case CBCentralManagerStateResetting: stateString = @"The connection with the system service was momentarily lost, update imminent."; break;
        case CBCentralManagerStateUnsupported: stateString = @"The platform doesn't support Bluetooth Low Energy."; break;
        case CBCentralManagerStateUnauthorized: stateString = @"The app is not authorized to use Bluetooth Low Energy."; break;
        case CBCentralManagerStatePoweredOff: stateString = @"Bluetooth is currently powered off."; break;
        case CBCentralManagerStatePoweredOn: stateString = @"Bluetooth is currently powered on and available to use."; break;
        default: stateString = @"State unknown, update imminent."; break;
    }

    if(_bluetoothState != CBCentralManagerStateUnknown && _bluetoothState != CBCentralManagerStatePoweredOn && central.state == CBCentralManagerStatePoweredOn){
         NSLog(@"BEACON_MANAGER: Bluetooth just enabled. Attempting to start beacon monitoring.");
        _forceRestartLM = YES; // make sure we force restart LMs on next update, since they're stopped currently and regions may not be updated to trigger it
        [self startBeaconMonitoring];
    }

    if(_bluetoothState != CBCentralManagerStateUnknown && _bluetoothState == CBCentralManagerStatePoweredOn && central.state != CBCentralManagerStatePoweredOn)    {
        NSLog(@"BEACON_MANAGER: Bluetooth just disabled. Attempting to stop beacon monitoring.");
        [self stopBeaconMonitoring];
    }
}