Oleg Shanyuk
Oleg Shanyuk

Reputation: 1336

iOS - check if bluetooth is on without system alert popup to user

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?

Upvotes: 14

Views: 24301

Answers (6)

Hsm
Hsm

Reputation: 1540

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];
}

Upvotes: 3

Alex Zanfir
Alex Zanfir

Reputation: 573

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!

Upvotes: 9

Ant Avison
Ant Avison

Reputation: 178

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

Upvotes: 2

Rushabh
Rushabh

Reputation: 3203

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];

Upvotes: 3

Ali Abbas
Ali Abbas

Reputation: 4277

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 !

Upvotes: 21

Gato
Gato

Reputation: 79

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.

Upvotes: 1

Related Questions