Michael Hendrick Michael Hendrick - 24 days ago 26
iOS Question

iBeacons Broken in iOS 10.0.2?

How's everyone doing with iBeacons on iOS 10.0.2 so far? I hope better than me! :-)

Update: Hardware used for testing was two iPhones. The iPhone 5S(A1533) and the iPhone 7(A1778)

A swift 2.x version of the code below could be used on an iPhone to advertise a simple iBeacon on iOS versions 9.x; today, the same code - updated for swift 3 and running on iOS 10.0.2 - doesn't appear to advertise at all.

I've cut code down to a very simple helper class and a viewcontroller that I think should adequately demonstrate the problem. Note that the storyboard has just one button connected to start/stop iBeacon advertising.

I've run the app on an iPhone 5 and an iPhone 7 with iOS 10.0.2. To test I created a custom scanner (sniffing for the specific proximity UUID,) and when that didn't work I tried more generic iBeacon detecting apps, like Estimote and LightBlue.

Sigh - nothing sees the iBeacon.

Thoughts? The developer forums at Apple mention problems reported with iBeacons in 10.x, but none as simple as this as far as I can tell.

Thanks a bunch...

- - - iBeaconConfiguration.swift - - - - - -

import Foundation

class iBeaconConfiguration
{
static let uuid = UUID(uuidString: "F34A1A1F-500F-48FB-AFAA-9584D641D7B1")!

private init() {}
}

- - - ViewController.swift - - - - - -

import UIKit
import CoreLocation
import CoreBluetooth

class ViewController: UIViewController, CBPeripheralManagerDelegate
{

@IBOutlet weak var btnAction: UIButton!

let UUID: UUID = iBeaconConfiguration.uuid

var beaconRegion: CLBeaconRegion!

var dataDictionary = NSDictionary()

var bluetoothPeripheralManager: CBPeripheralManager!

var isBroadcasting = false

override func viewDidLoad() {
super.viewDidLoad()

bluetoothPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}


@IBAction func switchBroadcastingState(_ sender: AnyObject)
{

if !isBroadcasting {
if bluetoothPeripheralManager.state == CBManagerState.poweredOn {

let major: CLBeaconMajorValue = 123
let minor: CLBeaconMinorValue = 456

beaconRegion = CLBeaconRegion(proximityUUID: UUID, major: major, minor: minor, identifier: "com.rdz.bcast")

dataDictionary = beaconRegion.peripheralData(withMeasuredPower: nil)

bluetoothPeripheralManager.startAdvertising(dataDictionary as? [String : Any])

btnAction.setTitle("Stop", for: UIControlState.normal)

isBroadcasting = true
}
}
else {
bluetoothPeripheralManager.stopAdvertising()

btnAction.setTitle("Start", for: UIControlState.normal)

isBroadcasting = false
}
}

func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {

print ("peripheralManagerDidStartAdvertising()")

if error != nil
{
print(error)
}
}

func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
print ("peripheralManager(...didReceiveRead)")
}

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
var statusMessage = ""

switch peripheral.state {
case CBManagerState.poweredOn:
statusMessage = "Bluetooth Status: Turned On"

case CBManagerState.poweredOff:
if isBroadcasting {
switchBroadcastingState(self)
}
statusMessage = "Bluetooth Status: Turned Off"

case CBManagerState.resetting:
statusMessage = "Bluetooth Status: Resetting"

case CBManagerState.unauthorized:
statusMessage = "Bluetooth Status: Not Authorized"

case CBManagerState.unsupported:
statusMessage = "Bluetooth Status: Not Supported"

default:
statusMessage = "Bluetooth Status: Unknown"
}

print("Bluetooth Status: \(statusMessage)")
}
}
- - - END - - - - -


(Apologies for any code format mistakes.)

Answer

Lots of people report trouble with bluetooth on iOS 10, but the trouble isn't universal.

Testing with 10.0.2 (14A456) on an iPod Touch 6th Generation model mkh22ll/a, I can successfully scan for beacons and transmit iBeacon using the Locate app for iOS. This is written in Objective C, but uses the same APIs as you are showing. You might try this same app on the problematic device and see if you still have trouble.

Testing another app that is written in Swift 3 on the same device (the app both transmits and receives iBeacon packets), I have verified that it successfully receives iBeacon packets and sends them, too.

The bottom line is that iBeacon transmission and detection on iOS 10 works fine on some devices.

I suspect that bluetooth problems with iOS 10 only happen with certain iPhone hardware models (and perhaps only on certain specific devices of these models) that have somewhat different bluetooth hardware chipsets.

A few things that may help troubleshoot:

  1. Turn bluetooth off and back on.
  2. Reboot your device. (Lame suggestion, I know.)
  3. Try super simple operations like scanning for other nearby bluetooth devices in Settings, and see if you can see other devices like your Mac or bluetooth speakers. If this simple bluetooth task doesn't work, there is no way iBeacon will work.
  4. Test with the Locate app described above. This may eliminate a coding issue.

Please do update the question with your hardware device.

Comments