14

This code allows to determine current bluetooth status:

CBCentralManager* testBluetooth = [[CBCentralManager alloc] initWithDelegate:nil queue: nil];


switch ([testBluetooth state]) {....}

But, when [[CBCentralManager alloc] init...] happens, system popups an alert to user, if bluetooth is off.

Is there any way to check bluetooth status without disturbing my users?

Oleg Shanyuk
  • 1,296
  • 2
  • 15
  • 26

6 Answers6

21

I got the following response from an apple developer : In iOS7, the CBCentralManagerOptionShowPowerAlertKey option lets you disable this alert.

If you havea a CBCentralManager when you initialise it, you can use the method initWithDelegate:queue:options

Example:

In my .h file i have a CBCentralManager * manager

In .m file :

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], CBCentralManagerOptionShowPowerAlertKey, nil];

_manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];

[_manager scanForPeripheralsWithServices:nil options:nil];

With this code the warning no longer appears, I hope that helps !

Ali Abbas
  • 4,247
  • 1
  • 22
  • 40
  • The options for peripheral scanning are: CBCentralManagerScanOptionAllowDuplicatesKey; CBCentralManagerScanOptionSolicitedServiceUUIDsKey; [link](https://developer.apple.com/library/ios/documentation/CoreBluetooth/Reference/CBCentralManager_Class/translated_content/CBCentralManager.html#//apple_ref/doc/constant_group/Peripheral_Scanning_Options) So sending the options dictionary you're sending doesn't make a difference in scanForPeripheralWithServices. Just need it in the initialization – shim Feb 18 '14 at 04:43
  • @shim You are right, I shouldn't add the options to the scanForPeripheralsWithServices – Ali Abbas Oct 20 '15 at 07:05
9

In swift you can do write these two lines in your app delegate inside the func: didFinishLaunchingWithOptions launchOptions

    self.bCentralManger = CBCentralManager(delegate: self, queue: dispatch_get_main_queue(), options: [CBCentralManagerOptionShowPowerAlertKey: false])
    self.bCentralManger.scanForPeripheralsWithServices(nil, options: nil)

where your bCentralManger should be declared as :

private var bCentralManger: CBCentralManager!

Alex Zanfir
  • 573
  • 4
  • 13
3

I have used below code to disable alert for iOS 8 and above version

self.bluetoothManager = [[CBCentralManager alloc]
                                      initWithDelegate:self 
                                      queue:dispatch_get_main_queue() 
                                      options:@{CBCentralManagerOptionShowPowerAlertKey: @(NO)}];

[self.bluetoothManager scanForPeripheralsWithServices:nil options:nil];
Rushabh
  • 3,208
  • 5
  • 28
  • 51
3

By combining on BadPirate's and Anas' answer, you can get the bluetooth state without show system alert.

#import <CoreBluetooth/CoreBluetooth.h>

@interface ShopVC () <CBCentralManagerDelegate>

@property (nonatomic, strong) CBCentralManager *bluetoothManager;

@end

@implementation ShopVC

- (void)viewDidLoad {
    [super viewDidLoad];

    if(!self.bluetoothManager)
    {
        NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey: @NO};
        self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
    }
}

#pragma mark - CBCentralManagerDelegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    NSString *stateString = nil;
    switch(self.bluetoothManager.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;
    }
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Bluetooth state"
                                                    message:stateString
                                                   delegate:nil
                                          cancelButtonTitle:@"ok" otherButtonTitles: nil];
    [alert show];
}
Community
  • 1
  • 1
Hsm
  • 1,510
  • 17
  • 16
2

I've only tested this on iOS 9 so maybe someone could test this one older OS devices.

We do everything normally except one thing, instead of settings the CBCentralManager Delegate in viewDidLoad we leave this until the moment we need it, in the example case below I call this once my WKWebView has finished loading, and because each page of my web view potentially requires the use of Bluetooth I put this in WKWebView didFinishNavigation.

Swift

var managerBLE: CBCentralManager?

func bluetoothStatus() {
    managerBLE = CBCentralManager(delegate: self, queue: nil, options: nil)
}

func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
    bluetoothStatus()
}

func centralManagerDidUpdateState(central: CBCentralManager) {
    switch managerBLE!.state
    {
    case CBCentralManagerState.PoweredOff:
        print("Powered Off")
    case CBCentralManagerState.PoweredOn:
        print("Powered On")
    case CBCentralManagerState.Unsupported:
        print("Unsupported")
    case CBCentralManagerState.Resetting:
        print("Resetting")
        fallthrough
    case CBCentralManagerState.Unauthorized:
        print("Unauthorized")
    case CBCentralManagerState.Unknown:
        print("Unknown")
    default:
        break;
    }
}

The moment that delegate is set within bluetoothStatus() you will see the state change fire.

The notification to turn on Bluetooth only seems to want to be called right at the initial load of your app, doing it this way mean you just get what you want from the centralManagerDidUpdateState

Ant Avison
  • 178
  • 1
  • 10
  • Also I'm aware that this approach may have bearing on energy consumption because we are setting and resetting delegates so it maybe worth thinking about removing the CBCentralManager Delegate before we re set it again each time we call the function? – Ant Avison Feb 24 '16 at 13:33
1

There is currently no way to disable this alert when your application is run on a iOS device which supports Bluetooth LE and where Bluetooth is disabled. It would be an enhancement request to provide a means to disable the alert. So the more requests Apple gets about this enhancement, the better.

Gato
  • 79
  • 1
  • 5