We are developing an app where we want iPhone to iPhone communication via bluetooth. We are using the core bluetooth API. One iPhone acts as the peripheral and the other as the central. When both apps are on screen they successfully find each other and can connect. However when the peripheral is in background the central can't find it. To be clear the central is still in foreground. I have consulted this page: https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html and other resources. From my understanding the service UUID should be moved to the manufacturer data. This makes it difficult for non-iOS devices to detect the service but the documentation says that my central should be able to find the peripheral. I have added the required keys to the pList and am explicitly searching for the mentioned service UUID. When using a third party BLE Tool I'm able to find and communicate with the peripheral even when it is in background mode. I know that some option-keys will be ignored but from my understanding they should still find each other at least once. This was tested with two iOS 18 iPhones. Here is the code im using:
import UIKit
import CoreBluetooth
class ViewController: UIViewController {
private var centralManager: CBCentralManager!
private var peripheralManager: CBPeripheralManager!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func btnPeripheral(_ sender: Any) {
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}
@IBAction func btnCentral(_ sender: Any) {
print("central go")
centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
extension ViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
print("central state: \(central.state)")
switch central.state {
case .poweredOn:
print("central powered on")
centralManager.scanForPeripherals(withServices: [CBUUID(string:"db9acb1e-1ac4-4f70-b58c-3b3dcea84703")], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
default:
print("central not powered on")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Dicovered \(peripheral)")
}
}
extension ViewController: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
print("peripheral state: \(peripheral.state)")
if peripheral.state == .poweredOn {
print("powered on")
let uuid = CBUUID(string: "db9acb1e-1ac4-4f70-b58c-3b3dcea84703")
let service = CBMutableService(type: uuid, primary: true)
peripheralManager.add(service)
peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [uuid], CBAdvertisementDataLocalNameKey: "MyService"])
}
}
}