Handling iOS 13 Bluetooth Permissions
Need to access CoreBluetooth? Ask the user first
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, applications could access Bluetooth without the user’s knowledge. 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. Developers could take advantage of this and track things like location data.
Starting iOS 13, if your application uses any of the Core Bluetooth APIs it requires the user’s permission. And off course, they can change it from settings!
If you’ve upgraded your device to iOS 13, I’m sure you’d have seen the above prompt plenty of times!
It brings to light the number of applications that had been using bluetooth so far.
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. Accessing Core Bluetooth without the usage descriptions would lead to a runtime crash.
For backward support for older iOS versions, NSBluetoothPeripheralUsageDescription
needs to be defined as well.
API changes
CBManagerAuthorisation
is a newly added property is iOS 13. It’s used to determine the authorization status of Bluetooth permission.
The authorization
property can have any of the following states:
allowedAlways
restricted
notDetermined
denied
In the next section, we’ll be discussing the various steps you need to follow in order to integrate CoreBluetooth into your application.
Implementation
import CoreBluetooth
in order to use the Core Bluetooth Framework in your codebase.
For using the Core Bluetooth functionalities, we need to implement CBPeripheralDelegate
and CBCentralManagerDelegate
protocols.
Initialize the Bluetooth Manager
CBCentralManager
is responsible for scanning and connecting to devices. Once the connection is done, the CBPeripheral
takes charge of the proceedings.
var centralManager: CBCentralManager? | |
var peripheral: CBPeripheral? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
centralManager = CBCentralManager(delegate: self, queue: nil) | |
} |
Right when the CentralManager
is initialized, the centralManagerDidUpdateState(_central: CBCentralManager)
delegate method is triggered to check the state of the Bluetooth connection.
If the bluetooth is turned off, CBCentralManager can’t be instantiated and the system will automatically throw a dialog prompt asking you to enable it.
We can check the user authorization status using the 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 leverage its delegate method to get notified of the characteristics of peripheral devices.
We can also do stuff such as passing data using the writeValue
function on the peripheral instance. The positive thing is that the user is aware!
Conclusion
Apple strives to provide transparency and improve user experience by bumping up Bluetooth security through the new iOS 13 permissions.