Reputation: 441
I have an application in Swift 4 that communicates with other apps like itself via Bluetooth LE. It passes all tests and works on a "fresh" iPhone. What I mean by "fresh" is that it has been reset in the last day and hasn't had too many other interactions with other classic Bluetooth devices. I say too many because I can't really quantify it. Some iPhones will work immediately after connecting to classic Bluetooth devices (cars, headphones, etc.) and others won't. Some don't even show this behavior at all. The fix is easy: just restart the iPhone. This seems to happen on iPhone SE and beyond (can't test earlier). However, it never happens with iPads.
My question is this: is there a way to programmatically reset the Bluetooth radio or the BLE stack in iOS? I can't seem to troubleshoot this. Nothing shows up in the logs or the debugger. When this occurs the device simply waits for Bluetooth connections while a "fresh" device sitting next to it will make the connection. I've attempted set my peripheralManager to nil to reset it, no luck. I also tried to set the UUID to something else temporarily, again no luck.
Any thoughts?
// BLE Constructor
override init() {
// Super
super.init()
// Initialize Location Manager
globalLocationManager.delegate = self
globalLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
globalLocationManager.requestAlwaysAuthorization()
// Start Updating Location
globalLocationManager.startUpdatingLocation()
// Log
AppDelegate.log( "Initializing Bluetooth LE Peripheral Manager" )
// Initialize Peripheral Manager
let options: Dictionary<String, AnyObject> = [ CBPeripheralManagerOptionShowPowerAlertKey: true as AnyObject ]
peripheralManager = CBPeripheralManager( delegate: self, queue: nil, options: options ) // nil Queue == Main Queue
// Initialize Packet Counters
counter = 0
}
// Start Advertising
func startAdvertising() {
// Evaluate Advertising State
if peripheralManager.isAdvertising == false {
// Start Advertising
AppDelegate.log( "Starting Advertisements" )
// Reset Simulation
resetSimulation()
let advertisementData = [
CBAdvertisementDataLocalNameKey: "TEST" as AnyObject,
CBAdvertisementDataServiceUUIDsKey: [cbUUID]
] as [String : AnyObject]
peripheralManager.startAdvertising( advertisementData )
}
}
Upvotes: 3
Views: 1740
Reputation: 158
Unfortunately there is no way to restart bluetooth programmatically. iPhones are very heavy on caching bluetooth data to preserve battery therefore if a change occurs to services or charectaristics that a BLE device was offering, the phone will not pick them up unless you restart your bluetooth or even the phone manual. I hope apple will give developers more control in the future.
Upvotes: 4