iOS蓝牙开发之iBeacon篇(一)


高山有崖, 林木有枝。忧来无方, 人莫之知。
——曹丕《善哉行》

什么是iBeacon

如果只是需要iPhone模拟iBeacon的demo代码,可以点击下载,不需要往下看了😂

  • 你曾经想过用手机在一个大型建筑物中为自己定位吗,比如购物中心,或者博物馆。
  • 当然,GPS可以让你得知自己身处哪一座建筑物里。但是如果想要在这些钢筋混凝土堆砌而成的建筑中获得精确的GPS信号,只能祝你好运了。你所需要的是内置在建筑物中一些设备,(通过它们)让手机获取确定你的位置。
  • iBeacon是Apple公司开发的一种近场通讯协议,于2013年的WWDC开发者大会推出。当你的手持设备靠近一个Beacon基站时,设备就能够感应到Beacon信号,范围可以从几毫米到50米。因为是一种定位技术,苹果将iBeacon相关的接口放到了CoreLocation.framework。
  • 其工作方式是: 配备有低功耗蓝牙(BLE)通信功能的设备(iBeacon)使用BLE技术向周围发送自己特有的UUID,使用iBeacon的App接收到该UUID的应用软件会根据该UUID采取一些行动。

iBeacon的应用场景

  • 当使用者走进某个博物馆时,会扫描到一个 beacon。这个 beacon 有三个标志符
    • proximityUUID 是一个整个博物馆统一的值,可以用来标识这个博物馆
    • major 值用来标识特定的展馆,比如唐代展馆,汉代展馆等等
    • minor 值标识了特定的一个位置的 beacon,例如定位到使用者正在唐代展馆的唐三彩展品的位置。
  • 这时博物馆的 app 会被系统唤醒,app 可以运行一个比较短的时间。在这段时间内,app 可以根据 beacon 的属性查询到使用者的地理位置(通过查询服务器或者本地数据)
    • 例如在唐代展馆的唐三彩展品位置,之后就可以通过一个 local notification 推送这件展品的简介。用户可以点击这次 local notification 来查看更详细的信息,这样一次导览行为就完成了。

可以充当iBeacon的iOS的设备

  • iPhone4s 或者 之后的iPhone设备
  • 第三代iPad或者 之后iPad设备
  • iPad mini 或者 之后iPad mini设备
  • 第五代iPod touch 或者之后iPod touch设备
  • iMac 或者 MacBookPro

iBeacon监听方式

  • Monitoring:低功耗监听,用来判断设备进出ibeacon围栏,支持后台或app进程杀掉后监听。
  • Ranging:大功率监听,监听当前设备所在区域内的ibeacon信息,包括rssi,距离,不支持后台监听。
  • 基于这两个特性,我们在使用时就分为前台和后台两个场景来实现ibeacon的检测。

iBeacon监听

  • 你的设备当然不会自动监测iBeacon的,所以首先你得告知它。CLBeaconRegion类代表一个iBeacon。
  • iBeacon与Core Location关联在一起看上去有点奇怪,因为它就是一个蓝牙设备而已,但是也可以这么认为,那就是iBeacon提供小范围定位功能,而GPS提供的是大范围定位功能。
  • CLBeaconRegion参数介绍
参数 必要字段 作用
identifier 标识字符串
proximityUUID 一级标识(eg.标识公司)
major 二级标识(eg.标识店铺)
minor 三级标识(eg.标识位置)

手机模拟iBeacon

  • 当想让iOS设备充当iBeacon时,你还需要引入Core Bluetooth框架,但只想检测iBeacon设备,你只需要Core Location就行了。

初始化

  • 初始化配置一个iBeacon的参数
    • beaconUUID 是一个128位的值,可以使用uuidgen生成,但是生成的某些值不可用,推荐使用我提供的这个
    • 初始化一个蓝牙外设管理者,
1
2
3
4
5
6
7
8
9
10
11
12
13
private let beaconIdentity = "kitty"
private let beaconUUID = "B0702880-A295-A8AB-F734-031A98A512DE"
private let beaconMajorValue = UInt16(2)
private let beaconMinorValue = UInt16(7)

private var peripheraManager: CBPeripheralManager?

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

peripheraManager = CBPeripheralManager(delegate: self, queue: .main)
}

监听蓝牙状态改变

  • 在inof.plist文件配置Privacy - Bluetooth Peripheral Usage Description请求蓝牙授权
  • 遵守CBPeripheralManagerDelegate协议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
extension ViewController: CBPeripheralManagerDelegate
{
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {

switch peripheral.state {
case .unknown:
print("蓝牙未知的")
case .resetting:
print("蓝牙重置中")
case .unsupported:
print("蓝牙不支持")
case .unauthorized:
print("蓝牙未验证")
case .poweredOff:
print("蓝牙未启动")
case .poweredOn:
print("蓝牙可用")
beaconAdvertising()
}
}
}

配置模拟iBeacon广播数据

1
2
3
4
5
6
7
8
9
10
11
func beaconAdvertising() {

guard let uuid = UUID(uuidString: beaconUUID) else {
return
}
let region = CLBeaconRegion(proximityUUID: uuid, major: beaconMajorValue, minor: beaconMinorValue, identifier: beaconIdentity)
let regionData = region.peripheralData(withMeasuredPower: nil)
let regionAdvertising = regionData as? [String : Any]
peripheraManager?.startAdvertising(regionAdvertising)
print("开始模拟Beacon广播数据\(regionData)")
}

监听是否广播成功

1
2
3
4
5
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
print("正在模拟Beacon广播数据: \(peripheral.isAdvertising) --- 错误信息: \(String(error?.localizedDescription ?? ""))")
stateLbl.text = "正在模拟Beacon广播数据: \n\(peripheral.isAdvertising) \n错误信息: \n\(String(error?.localizedDescription ?? ""))"
stateLbl.textAlignment = .center
}

参考

官方文档
维基百科
iOS 中 iBeacon 开发

要不要鼓励一下😘