Bluetooth Low Energy (BLE) is essential for applications requiring device communication, like IoT or fitness trackers. Implementing BLE functionality on iOS, particularly continuous scanning in the background is challenging due to strict background execution policies. By handling BLE natively in iOS and exposing necessary methods to React Native, developers gain granular control over BLE operations while leveraging React Native for cross-platform development.
This blog outlines the process of achieving continuous BLE scanning in iOS, based on the native implementation provided in the BLEManager.swift file.
React Native BLE libraries often lack the flexibility and fine-grained control required for advanced use cases, such as:
Efficient background scanning and reconnection.
Custom BLE service and characteristic handling.
Robust handling of system-level events like app suspension or Bluetooth state changes.
By implementing BLE natively, you can optimise battery usage, manage background tasks effectively, and ensure compliance with iOS policies.
Update Info.plist
Enable background execution for Bluetooth by adding the following keys:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
</array>
The BLEManager.swift file provides a robust BLE manager class. Below are the highlights of its key functionalities:
a. Initializing BLE
The initializeBLE method initializes the CBCentralManager with background restoration capabilities:
@objc func initializeBLE() {
if centralManager == nil {
let options: [String: Any] = [
CBCentralManagerOptionShowPowerAlertKey: false,
CBCentralManagerOptionRestoreIdentifierKey: "com.yourapp.identifier"
]
centralManager = CBCentralManager(delegate: self, queue: nil, options: options)
}
}
b. Starting and Stopping Scans
BLE scanning is managed by startScanning and stopScanning methods. These methods scan for devices matching specific service UUIDs which is useful for background scanning and background working. The didDiscoverPeripheral method handles discovered devices and ensures continuous scanning by restarting the scan when the app is in the background
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any], rssi RSSI: NSNumber) {
DispatchQueue.main.async {
let appState = UIApplication.shared.applicationState
if appState == .background {
self.centralManager?.stopScan()
self.startScanning()
}
}
// Process the discovered device
let name = peripheral.name
}
@objc func startScanning() {
centralManager?.scanForPeripherals(withServices: [CBUUID(string: "your service UUID")],
options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
}
@objc func stopScanning() {
centralManager?.stopScan()
}
To integrate the native BLE functionality with React Native, the BLEManager.swift class extends RCTEventEmitter and exposes methods using the React Native bridge:
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(BLEManager, NSObject)
RCT_EXTERN_METHOD(InitializeBLE)
RCT_EXTERN_METHOD(startScanning)
RCT_EXTERN_METHOD(stopScanning)
@end
These methods can be invoked from React Native using NativeModules:
import { NativeModules } from 'react-native';
const { BLEManager } = NativeModules;
BLEManager.initializeBLE();
BLEManager.startScanning();
BLEManager.stopScanning();
Implementing continuous BLE scanning in iOS, especially in the background, requires a combination of native BLE handling and strategic optimizations. By restarting scanning upon discovering a device in the background, and scanning for particular service UUID as demonstrated in the didDiscoverPeripheral method and startScanning method, you can ensure uninterrupted BLE functionality.
This native-first approach provides robust BLE operations while seamlessly integrating with React Native, empowering developers to build efficient and feature-rich BLE-enabled applications.
Ready to transform your business with our technology solutions? Contact Us today to Leverage Our React Native Expertise.
0