如何在iPhone程序中以编程方式获取蓝牙状态(开/关)

43

我希望通过编程获取iPhone/iPod蓝牙的状态,即它是否打开或关闭。 是否可以使用一些Apple API或第三方API实现。

7个回答

50
我想分享一些与Sam的答案相关的研究成果,您可以在不使用私有API的情况下实现,但需要注意以下几点:
  • 仅适用于iOS 5.0及以上版本
  • 仅适用于支持蓝牙LE规范的设备(iPhone 4S+、第五代iPod+、第三代iPad+)
  • 仅分配该类会导致应用程序请求用户使用蓝牙堆栈的权限(可能不是期望的),如果他们拒绝,您将只看到CBCentralManagerStateUnauthorized iOS7+修订:上述删除线现在可以被防止,请参见下面的评论,指向此答案,其中解释了您可以将CoreBluetooth的CBCentralManagerOptionShowPowerAlertKey选项设置为NO以防止权限提示。
  • 检索蓝牙状态是异步的,并且是连续的。您需要设置一个委托来获取状态更改,因为检查新分配的蓝牙管理器的状态将返回CBCentralManagerStateUnknown
这种方法似乎可以实时更新蓝牙堆栈状态。在包含CoreBluetooth框架后,
#import <CoreBluetooth/CoreBluetooth.h>

使用以下内容很容易执行这些测试:

- (void)detectBluetooth
{
    if(!self.bluetoothManager)
    {
        // Put on main queue so we can call UIAlertView from delegate callbacks.
        self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
    }
    [self centralManagerDidUpdateState:self.bluetoothManager]; // Show initial state
}

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

2
你提到了这一点,但为了保持一致性:请声明属性 @property (nonatomic, strong) CBCentralManager* bluetoothManager; 并设置你的类符合协议 CBCentralManagerDelegate - Yevhen Dubinin
1
这对我没用。有人让它对他们起作用了吗?iOS7+ - esreli
2
您可以使用CBCentralManager上的指定初始化器避免警告消息,请查看此答案:https://dev59.com/KWQn5IYBdhLWcg3w_LTx#19367494。 - bompf
这种方法被苹果接受了吗?还是他们会拒绝使用它的应用程序? - LS_
1
@Signo - 对于苹果设备没有问题,尽管有一些报告称它已经无法工作了。 - BadPirate
@BadPirate,现在确实仍然有效。人们很可能立即读取状态(它将始终返回(int)0),而不是等待委托回调。 - Albert Renshaw

25
为了禁用默认的警报消息,您只需要在实例化CBPeripheralManager时通过选项字典进行传递:
SWIFT在iOS8+上进行测试
import CoreBluetooth

//Define class variable in your VC/AppDelegate
var bluetoothPeripheralManager: CBPeripheralManager?

 //On viewDidLoad/didFinishLaunchingWithOptions
let options = [CBCentralManagerOptionShowPowerAlertKey:0] //<-this is the magic bit!
bluetoothPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: options)

显然,您还需要按照上面概述的方式实现CKManagerDelegate代理方法peripheralManagerDidUpdateState:

func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager!) {

    var statusMessage = ""

    switch peripheral.state {
    case .poweredOn:
        statusMessage = "Bluetooth Status: Turned On"

    case .poweredOff:
        statusMessage = "Bluetooth Status: Turned Off"

    case .resetting:
        statusMessage = "Bluetooth Status: Resetting"

    case .unauthorized:
        statusMessage = "Bluetooth Status: Not Authorized"

    case .unsupported:
        statusMessage = "Bluetooth Status: Not Supported"

    case .unknown:
        statusMessage = "Bluetooth Status: Unknown"
    }

    print(statusMessage)

    if peripheral.state == .poweredOff {
        //TODO: Update this property in an App Manager class
    }
}

如何在Swift中添加属性CBPeripheralManager。它显示找不到类型“CBPeripheralManager”的初始化器。 - Legolas
@Aravind.A 在你的源代码文件顶部添加 import CoreBluetooth - Awesomeness
1
这段代码非常适合用于静默检查蓝牙状态(开/关等)。 - Maksim
这个在后台工作还是只有当应用程序在屏幕上时才能工作? - NickG

13

这篇答案已经从原来的Objective-C更新到了Swift 4.0。

假设您已经创建了一个蓝牙管理器,并将委托分配给ViewController类。

import CoreBluetooth

extension ViewController : CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            print("powered on")
        case .poweredOff:
            print("powered off")
        case .resetting:
            print("resetting")
        case .unauthorized:
            print("unauthorized")
        case .unsupported:
            print("unsupported")
        case .unknown:
            print("unknown")
        }
    }
}

6

BadPirate的回答有些更新,使用iOS7版本,你可以通过给定一个拥有键为"CBCentralManagerOptionShowPowerAlertKey"且设置为0的NSDictionary来让中央管理器不显示弹出警告。

self.cbManager = [[CBCentralManager alloc] initWithDelegate:self
                                                          queue:nil
                                                        options:
                      [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0]
                                                  forKey:CBCentralManagerOptionShowPowerAlertKey]];

2

iOS 5及以上版本可以使用CoreBluetooth实现。你可以使用的类是CBCentralManager,它有一个属性"state",您可以检查它来查看蓝牙是否打开。(枚举CBCentralManagerState包含您要检查的值)。


这仅适用于具有BT LE的设备,即iPhone 4S+,iPad 3+。 - domsom

1
一旦您设置好了 CBCentralManager,您可以从 delegate method 或直接使用 CBCentralManager::stateCBCentralManager::authorization。请保留HTML标签。
import CoreBluetooth

class Manager {
    let centralManager = CBCentralManager(delegate: self, queue: nil)

    var isBTTurnedOn: Bool {
        return centralManager.state == .poweredOn
    }

    var isAuthorized: Bool {
        if #available(iOS 13.0, *) {
            return centralManager.authorization == .allowedAlways
        } else {
            return true
        }
    }
}

0

这个解决方案有点老了,在苹果引入核心蓝牙之前。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.


        Class BluetoothManager = objc_getClass( "BluetoothManager" ) ;
        id btCont = [BluetoothManager sharedInstance] ;
        [self performSelector:@selector(status:) withObject:btCont afterDelay:1.0f] ;

        return YES ;
    }


    - (void)status:(id)btCont
    {
        BOOL currentState = [btCont enabled] ;
        //check the value of currentState 

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接