iBeacon 是蘋果公司在 iOS 7 中新推出的一種近場定位技術,可以感知一個附近的 iBeacon 信標的存在。
當一個 iBeacon 兼容設備進入/退出一個 iBeacon 信標標識的區域時,iOS 和支持 iBeacon 的 app 就能得知這一信息,從而對用戶發出相應的通知。
典型的應用場景例如博物館實時推送附近展品的相關信息,商場內即時通知客戶折扣信息等。蘋果在 Apple Store 中也部署了 iBeacon 來推送優惠、活動信息。
iBeacon 基于低功耗藍牙技術(Bluetooth Low Energy, BLE)這一開放標準,因此也繼承了 BLE 的一些特點。
范圍廣
相比于 NFC 的數厘米的識別范圍,iBeacon 的識別范圍可以達到數十米,并且能夠估計距離的遠近。
兼容性
iBeacon 是基于 BLE 做的一個簡單封裝,因此大部分支持 BLE 的設備都可以兼容。 例如可以使用一個普通的藍牙芯片作為信標,使用 Android 設備檢測信標的存在。
低能耗
不少 beacon 實現宣稱可以不依賴外部能源獨立運行兩年。
我們以一個連鎖商場的例子來講解 iBeacon 的一個流程。在一個連鎖商場中,店家需要在商場中的不同地方推送不同的優惠信息,比如服裝和家居柜臺推送的消息就很有可能不同。
當消費者走進某個商場時,會掃描到一個 beacon。這個 beacon 有三個標志符,proximityUUID
是一個整個公司(所有連鎖商場)統一的值,可以用來標識這個公司,major
值用來標識特定的連鎖商場,比如消費者正在走進的商場,minor
值標識了特定的一個位置的 beacon,例如定位到消費者正在門口。
這時商場的 app 會被系統喚醒,app 可以運行一個比較短的時間。在這段時間內,app 可以根據 beacon 的屬性查詢到用戶的地理位置(通過查詢服務器或者本地數據),例如在化妝品專柜,之后就可以通過一個 local notification 推送化妝品的促銷信息。用戶可以點擊這次 local notification 來查看更詳細的信息,這樣一次促銷行為就完成了。
閑話少說,我們來看下 iBeacon 具體怎么使用:
iBeacon 本質上來說是一個位置(區域)信息,所以 Apple 把 iBeacon 功能集成在了 Core Location 里面。
iBeacon 信標在 Core Location 中表現為一個 CLBeacon
,它圈定的范圍則表現為 CLBeaconRegion
,這是一個 CLRegion
的子類。
CLBeaconRegion
主要用三個屬性來標識一個 iBeacon,proximityUUID
、major
和 minor
。
proximityUUID
是一個 NSUUID
,用來標識公司,每個公司、組織使用的 iBeacon 應該擁有同樣的 proximityUUID
。
major
用來識別一組相關聯的 beacon,例如在連鎖超市的場景中,每個分店的 beacon 應該擁有同樣的 major
。
minor
則用來區分某個特定的 beacon。
這些屬性如果不指定(即 nil),匹配的時候就會忽略這個屬性。例如只指定 proximityUUID
的 CLBeaconRegion
可以匹配某公司的所有 beacons。
Apple 在 iOS 4 中增加了地理圍欄 API,可以用來在設備進入/退出某個地理區域時獲得通知,這些 API 包括 -startMonitoringForRegion:
、-locationManager:didEnterRegion:
、-locationManager:didExitRegion:
等。 CLBeaconRegion
作為 CLRegion
的子類也可以復用這些 API,這種檢測 iBeacon 的方式叫做 monitoring。
使用這種方法可以在程序在后臺運行時檢測 iBeacon,但是只能同時檢測 20 個 region,也不能推測設備與 beacon 的距離。
除了使用地理圍欄 API 的方式,Apple 還在 iOS 7 中新增加了 iBeacon 專用的檢測方式,也就是 ranging。
通過 CLLocationManager
的 -startRangingBeaconsInRegion:
方法可以開始檢測特定的 iBeacon。
當檢測到 beacon 的時候,CLLocationManager
的 delegate 方法 -locationManager:didRangeBeacons:inRegion:
會被調用,通知調用者現在被檢測到的 beacons。 這個方法會返回一個 CLBeacon
的數組,根據 CLBeacon
的 proximity
屬性就可以判斷設備和 beacon 之間的距離。
proximity
屬性有四個可能的值,unknown、immediate、near 和 far。 另外 CLBeacon
還有 accuracy
和 rssi
兩個屬性能提供更詳細的距離數據。
我們可以使用 Core Bluetooth 框架來廣播特定的 payload 來讓 iOS 設備成為一個 iBeacon。 這個 payload 可以由 CLBeaconRegion
的 -peripheralDataWithMeasuredPower:
方法來獲取。
之后交給 CBPeripheralManager
廣播出去就可以了。
需要注意的是,廣播 iBeacon 信息的時候 app 必須在前臺運行。
iBeacon 的 API 并不十分復雜,但他的行為比較難弄清楚,特別是當應用運行在后臺時,檢測到 beacon 的時間延遲會讓開發者難以推測。在做了一些實驗和合理的推測后,我們得出了一些結論:
notifyEntryStateOnDisplay=YES
的 beacon,iOS 會在屏幕點亮的時候(鎖屏狀態下按下 home 鍵,或者因為收到推送點亮等)進行一次掃描。