【Swift/iOS】iBeacon(ビーコン)とは?受信側(セントラル)の実装方法

【Swift/iOS】iBeacon(ビーコン)とは?受信側(セントラル)の実装方法

この記事からわかること

  • SwiftBeacon(ビーコン)を実装する方法
  • ビーコンの種類
  • iBeaconとは?
  • 受信側(セントラル)のiOSアプリの開発方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

Beacon(ビーコン)とは?

Beacon(ビーコン)」とはBluetooth Low Energy (BLE)を使用して位置情報や通知などをスマートフォンや他のデバイスに送信できる小型のデバイスです。BLEを使用した機器のため通信範囲は数メートルから数十メートル程度で比較的短い距離で使用される想定で扱われます。

BLEを利用して一定間隔で情報を発信し、受信できるアプリなどが通信距離圏内に入った際に情報をキャッチし、任意の処理を行わせるといったことが可能になります。

身近で使用されている例としては店舗にビーコンを設置し、店内を歩く顧客に対して特定のプロモーション情報を送信したり、博物館で特定の展示物の前に立ったときにその展示物に関する情報を提供するなどとして使用されているようです。

Beaconの種類

Beaconという言葉自体は「のろし」という意味を持っており、ここでは「BLE通信を使用した情報発信デバイスや技術」のことを指しています。代表的なBeaconの種類を紹介しておきます。

Webビーコン

Webページなどのアクセス解析を行うためのビーコン。具体的には縦横1ビット程度の小さなサイズの画像で、視認はできないがアクセスするたびに情報を専用サーバーに送信するプログラムを実行する。例:Google Analyticsなど

Apple iBeacon

公式リファレンス:iBeacon

Appleが開発したBeacon規格。iOSだけでなくAndroid端末などでも利用可能。こちらがデファクトスタンダード。

Google Eddystone

Googleが開発したBeacon規格。AndroidだけでなくiOS端末などでも利用可能。

SwiftでBeaconアプリを開発する

SwiftでBeaconアプリを開発するには発信用(ペリフェラル)と受信用(セントラル)どちらを開発するかをまず決めます。ほとんどの場合が受信用の開発になると思いますが、テストしたい場合に専用機器が用意できない場合などはSwiftで発信側も開発することでテストが容易に行えるようになります。

おすすめ記事:BLE(Bluetooth Low Energy)とは?セントラルやペリフェラルの意味と用語集

iBeaconでは発信する情報に以下の情報が含まれます。実装段階で必要になるので用意しておきます。

受信用(セントラル)の実装

公式リファレンス:Turning an iOS device into an iBeacon device

Beacon受信用(セントラル)側を実装するにはCoreLocationを使用して実装できます。

実装の流れ

  1. 位置情報許可の追加
  2. CLBeaconRegion/CLBeaconIdentityConstraintインスタンスを生成
  3. CLLocationManagerクラスのセットアップと位置情報の使用許可
  4. モニタリングを開始
  5. アプリ起動時にBeaconを開始

発信用(ペリフェラル)の実装方法は以下の記事を参考にしてください。

1.位置情報許可の追加

Beaconを受信する側のアプリを実装するには位置情報の使用を許可しもらう必要があります。「info.plist」に以下の2つを追加し、使用する理由を記載しておきます。

2.CLBeaconRegion/CLBeaconIdentityConstraintインスタンスを生成

CLBeaconRegionCLBeaconIdentityConstraintインスタンスを生成します。それぞれの引数に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.モニタリングを開始

CLBeaconRegionCLBeaconIdentityConstraintを使用してモニタリングを開始します。これで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にあげていますので参考にしてください。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index