Core Bluetooth Permissions in iOS 13

Core Bluetooth framework is an abstraction layer that provides developers access to BLE hardware. Apple introduced quite a few changes for the better during WWDC 2019. Besides fast transfer and power-efficient connections, much emphasis has been given to user privacy.

Until iOS 12, apps could use Bluetooth services in the background without user’s attention. This could be done for good reasons, such as connecting to Chromecast or wireless headsets.

But this had it’s own pitfalls and created a hole in the user’s privacy since developers could abuse the system and do stuff like location tracking.

Hence with iOS 13, if you’re application accesses any Core Bluetooth APIs it requires user authorization.
The permission dialogs would now be shown on apps build with older SDKs as well.

Privacy Permissions And Usage Descriptions

Starting iOS 13, it’s mandatory for developers to specify the Privacy Usage Description for Bluetooth by including NSBluetoothAlwaysUsageDescription in their info.plist file. Otherwise accessing any Core Bluetooth APIs would lead to a crash.

For backward support for older iOS versions, NSBluetoothPeripheralUsageDescription needs to be defined.

API changes

CBManagerAuthorisation Property has been added to check whether the user has authorized the CoreBluetooth Permission.

The authorization property can have any of the following states:

  • notDetermined
  • restricted
  • denied
  • allowedAlways

In the next section, we’ll be discussing the various steps you need to follow in order to integrate CoreBluetooth in your application.

Implementation

import CoreBluetooth

For using the Core Bluetooth functionalities, we need to conform our ViewController class to CBPeripheralDelegate and CBCentralManagerDelegate protocols.

Instantiating the Bluetooth Manager

CBCentralManager is responsible for scanning and connecting to devices. Once the connection is done, CBPeripheral takes in charge of

var centralManager: CBCentralManager?
var peripheral: CBPeripheral?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        centralManager = CBCentralManager(delegate: self, queue: nil)
        
    }   

Right when the CentralManager is initialised, the centralManagerDidUpdateState(_central: CBCentralManager) delegate method is called to check the state of bluetooth. We can check the user authorization status from central.state.authorization property.

func centralManagerDidUpdateState(_ central: CBCentralManager) {
           switch central.state {
           case .unauthorized:
               switch central.authorization {
               case .allowedAlways:
               case .denied:
               case .restricted:
               case .notDetermined:
               }
           case .unknown:
           case .unsupported:
           case .poweredOn:
               self.centralManager?.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey:true])
           case .poweredOff:
           case .resetting:
           @unknown default:
           }
       }

Scanning of devices is only possible when the state changes to poweredOn

Note: Core Bluetooth scans for BLE devices only.

Connecting To Scanned Devices

Once a BLE device is discovered it shows up in the below method:

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

        self.peripheral = peripheral
        self.peripheral?.delegate = self
        
        centralManager?.connect(peripheral, options: nil)
        centralManager?.stopScan()
    }

We can then access the Bluetooth Device name from the peripheral.name property.
From here the CBPeripheralDelegate takes control. We can do various stuff such as passing data using the writeValue function on the peripheral instance. The positive thing is that the user is aware!

iOS 13 strives to provide transparency and improve user experience through such features.
That’s it for this one. I hope you enjoyed.

Leave a Reply

Your email address will not be published. Required fields are marked *