【Swift/iOS】iBeacon(ビーコン)とは?受信側(セントラル)の実装方法
この記事からわかること
- SwiftでBeacon(ビーコン)を実装する方法
- ビーコンの種類
- iBeaconとは?
- 受信側(セントラル)のiOSアプリの開発方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- watchOS:10.0
- Swift:5.9
- macOS:Sonoma 14.1
Beacon(ビーコン)とは?
「Beacon(ビーコン)」とはBluetooth Low Energy (BLE)を使用して位置情報や通知などをスマートフォンや他のデバイスに送信できる小型のデバイスです。BLEを使用した機器のため通信範囲は数メートルから数十メートル程度で比較的短い距離で使用される想定で扱われます。
BLEを利用して一定間隔で情報を発信し、受信できるアプリなどが通信距離圏内に入った際に情報をキャッチし、任意の処理を行わせるといったことが可能になります。
身近で使用されている例としては店舗にビーコンを設置し、店内を歩く顧客に対して特定のプロモーション情報を送信したり、博物館で特定の展示物の前に立ったときにその展示物に関する情報を提供するなどとして使用されているようです。
Beaconの種類
Beaconという言葉自体は「のろし」という意味を持っており、ここでは「BLE通信を使用した情報発信デバイスや技術」のことを指しています。代表的なBeaconの種類を紹介しておきます。
- Webビーコン
- Apple iBeacon
- Google Eddystone
Webビーコン
Webページなどのアクセス解析を行うためのビーコン。具体的には縦横1ビット程度の小さなサイズの画像で、視認はできないがアクセスするたびに情報を専用サーバーに送信するプログラムを実行する。例:Google Analyticsなど
Apple iBeacon
Appleが開発したBeacon規格。iOSだけでなくAndroid端末などでも利用可能。こちらがデファクトスタンダード。
Google Eddystone
Googleが開発したBeacon規格。AndroidだけでなくiOS端末などでも利用可能。
SwiftでBeaconアプリを開発する
SwiftでBeaconアプリを開発するには発信用(ペリフェラル)と受信用(セントラル)どちらを開発するかをまず決めます。ほとんどの場合が受信用の開発になると思いますが、テストしたい場合に専用機器が用意できない場合などはSwiftで発信側も開発することでテストが容易に行えるようになります。
おすすめ記事:BLE(Bluetooth Low Energy)とは?セントラルやペリフェラルの意味と用語集
iBeaconでは発信する情報に以下の情報が含まれます。実装段階で必要になるので用意しておきます。
- UUID(16バイト):サービス識別子
- MAJOR(2バイト):任意の識別子(例:店舗内のセクション番号など)
- MINOR(2バイト):任意の識別子(例:店舗内のセクション内の棚番号など)
- RSSI(1バイト):デバイスとの距離(正確には信号の強さ)
受信用(セントラル)の実装
公式リファレンス:Turning an iOS device into an iBeacon device
Beacon受信用(セントラル)側を実装するにはCoreLocation
を使用して実装できます。
実装の流れ
- 位置情報許可の追加
- CLBeaconRegion/CLBeaconIdentityConstraintインスタンスを生成
- CLLocationManagerクラスのセットアップと位置情報の使用許可
- モニタリングを開始
- アプリ起動時にBeaconを開始
発信用(ペリフェラル)の実装方法は以下の記事を参考にしてください。
1.位置情報許可の追加
Beaconを受信する側のアプリを実装するには位置情報の使用を許可しもらう必要があります。「info.plist」に以下の2つを追加し、使用する理由を記載しておきます。
- NSLocationAlwaysUsageDescription:位置情報を常に観測
- NSLocationWhenInUseUsageDescription:位置情報を使用中だけ観測
2.CLBeaconRegion/CLBeaconIdentityConstraintインスタンスを生成
CLBeaconRegion
とCLBeaconIdentityConstraint
インスタンスを生成します。それぞれの引数にUUIDなどを渡します。
static let PROXIMITY_UUID = UUID(uuidString: "00000000-0000-1111-1111-111111111111")!
static let BEACON_ID = "BEACON"
/// CLBeaconRegionを生成
private func createBeaconRegion() -> CLBeaconRegion {
return CLBeaconRegion(
uuid: BeaconCentralManager.PROXIMITY_UUID,
identifier: BeaconCentralManager.BEACON_ID
)
}
/// CLBeaconIdentityConstraintを生成
private func createBeaconIdentityConstraint() -> CLBeaconIdentityConstraint {
return CLBeaconIdentityConstraint(
uuid: BeaconCentralManager.PROXIMITY_UUID
)
}
3.CLLocationManagerクラスのセットアップと位置情報の使用許可
位置情報やビーコンのモニタリング、範囲測定を行うためのCLLocationManagerクラスをインスタンス化します。
public func startMonitoring() {
// CLLocationManagerの初期化とデリゲートの設定
locationManager = CLLocationManager()
locationManager.delegate = self
// 位置情報の使用許可を要求
locationManager.requestWhenInUseAuthorization()
// 後述 〜〜〜〜〜〜
}
管理クラスはCLLocationManagerDelegate
に準拠させておきます。
extension BeaconCentralManager: CLLocationManagerDelegate {
// Beacon領域内に入ったことを検知したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("Beacon領域に入りました。")
}
// Beacon領域内から出たことを検知したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("Beacon領域から出ました。")
}
// Beacon情報を取得したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didRange beacons: [CLBeacon], satisfying beaconIdentityConstraint: CLBeaconIdentityConstraint) {
if let nearestBeacon = beacons.first {
switch nearestBeacon.proximity {
case .immediate:
print("非常に近い距離にBeaconが検出されました。")
case .near:
print("近い距離にBeaconが検出されました。")
case .far:
print("遠い距離にBeaconが検出されました。")
default:
print("Beaconの距離を検出できません。")
}
}
for beacon in beacons {
print("UUID: \(beacon.uuid)")
print("Major: \(beacon.major)")
print("Minor: \(beacon.minor)")
print("Proximity: \(beacon.proximity)")
}
}
// 許可の状態が変更されたときに呼ばれるデリゲートメソッド
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse {
// Beaconのモニタリングを開始
locationManager.startMonitoring(for: beaconRegion)
locationManager.startRangingBeacons(satisfying: beaconIdentityConstraint)
}
}
}
4.モニタリングを開始
CLBeaconRegion
とCLBeaconIdentityConstraint
を使用してモニタリングを開始します。これでBeaconを検知したら受信できるようになります。
public func startMonitoring() {
// 〜〜〜〜〜〜
// Beacon領域の設定
beaconRegion = createBeaconRegion()
// Beacon識別制約の設定
beaconIdentityConstraint = createBeaconIdentityConstraint()
// Beaconのモニタリングを開始
locationManager.startMonitoring(for: beaconRegion)
locationManager.startRangingBeacons(satisfying: beaconIdentityConstraint)
}
5.アプリ起動時にBeaconを開始
最後に任意のタイミング(今回はアプリ起動時)でモニタリングを開始すればデータを受信する端末として動作するiOSアプリが完成です。
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// セントラル(Beacon受信側)
let beaconCentralManager = BeaconCentralManager.shared
beaconCentralManager.startMonitoring()
return true
}
}
6.全体のコード
class BeaconCentralManager: NSObject {
static let shared = BeaconCentralManager()
// CLLocationManagerインスタンスを作成
var locationManager: CLLocationManager!
private var beaconRegion : CLBeaconRegion!
private var beaconIdentityConstraint : CLBeaconIdentityConstraint!
// 受信するBeaconのUUID、メジャー、マイナーを指定
static let PROXIMITY_UUID = UUID(uuidString: "00000000-0000-1111-1111-111111111111")!
static let BEACON_ID = "BEACON"
/// CLBeaconRegionを生成
private func createBeaconRegion() -> CLBeaconRegion {
return CLBeaconRegion(
uuid: BeaconCentralManager.PROXIMITY_UUID,
identifier: BeaconCentralManager.BEACON_ID
)
}
/// CLBeaconIdentityConstraintを生成
private func createBeaconIdentityConstraint() -> CLBeaconIdentityConstraint {
return CLBeaconIdentityConstraint(
uuid: BeaconCentralManager.PROXIMITY_UUID
)
}
public func startMonitoring() {
// CLLocationManagerの初期化とデリゲートの設定
locationManager = CLLocationManager()
locationManager.delegate = self
// 位置情報の使用許可を要求
locationManager.requestWhenInUseAuthorization()
// Beacon領域の設定
beaconRegion = createBeaconRegion()
// Beacon識別制約の設定
beaconIdentityConstraint = createBeaconIdentityConstraint()
// Beaconのモニタリングを開始
locationManager.startMonitoring(for: beaconRegion)
locationManager.startRangingBeacons(satisfying: beaconIdentityConstraint)
}
}
extension BeaconCentralManager: CLLocationManagerDelegate {
// Beacon領域内に入ったことを検知したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("Beacon領域に入りました。")
}
// Beacon領域内から出たことを検知したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("Beacon領域から出ました。")
}
// Beacon情報を取得したときに呼ばれるデリゲートメソッド
func locationManager(_ manager: CLLocationManager, didRange beacons: [CLBeacon], satisfying beaconIdentityConstraint: CLBeaconIdentityConstraint) {
if let nearestBeacon = beacons.first {
switch nearestBeacon.proximity {
case .immediate:
print("非常に近い距離にBeaconが検出されました。")
case .near:
print("近い距離にBeaconが検出されました。")
case .far:
print("遠い距離にBeaconが検出されました。")
default:
print("Beaconの距離を検出できません。")
}
}
for beacon in beacons {
print("UUID: \(beacon.uuid)")
print("Major: \(beacon.major)")
print("Minor: \(beacon.minor)")
print("Proximity: \(beacon.proximity)")
}
}
// 許可の状態が変更されたときに呼ばれるデリゲートメソッド
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse {
// Beaconのモニタリングを開始
locationManager.startMonitoring(for: beaconRegion)
locationManager.startRangingBeacons(satisfying: beaconIdentityConstraint)
}
}
}
このデモプロジェクトはGitHubにあげていますので参考にしてください。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。