開発部のなーさんです。
普段はWEB系の開発をしている私が「家庭で使える」をテーマに突如はじめた、Beaconを使ったスマホアプリ作成チャレンジブログ、第2回は、自宅Wi-Fiお知らせアプリのベースとなるiOSのCoreLocationを使ったiBeacon探索機能の作成を行っていきます。
下記は2018年10月現在の情報で執筆しています。
文中、画像中で使用されている商標等はそれぞれの企業、団体に帰属します。
コンセプト実証用のソースコードのため簡略化等された箇所があります。
前回のまとめ
前回は作成のための準備や情報の整理をしました。
自宅Wi-Fiお知らせアプリ開発【第一回】 準備編
つくるアプリ: 自宅Wi-Fiお知らせアプリ
アプリの機能: 帰宅したらBeacon(BLEAD-B)に反応して、スマホを自宅Wi-Fiに接続するかを聞いてくれるアプリ
今回開発に使用した環境を記載します。
●ハードウェア
iMac2017(macOS 10.14)
iPad Air2 (iOS12.0.1)SIMなし
BLEAD-B 1台
Wi-Fiルータ 1台
●ソフトウェア
Xcode 10.0 + Swift4.2
Apple developer Programアカウント ※HotSpotの許可をONにするために必須です。
CoreLocation.framework
作成にあたって、iBeacon探索の機能について整理したいと思います。
このアプリではiOSでiBeaconの探索や検知を手軽に行えるCoreLocation.frameworkを利用します。しかし、GPSなどの屋外位置測位も扱うフレームワークなので機能がたくさんあります。そこで今回使うクラスやメソッドなどをリスト化しました。
おおよその処理の流れです。
- 探索したいiBeaconの情報を設定したRegionを生成します。
- 生成したRegionの探索(Monitoring)を開始します。
- Regionの探索条件に合ったiBeaconが最初に検知されたとき、Regionの検知が発生します。
- レンジング(Ranging)を開始します。
見つかったiBeaconの情報が連続的に通知されるようになります。Regionに合ったiBeaconが追加で見つかっても、新たにRegionの検知は発生しません。 - Regionの探索条件に合ったiBeaconが全て検知されなくなったら、レンジングを終了します。
- 無駄な探索(Monitoring)を防ぐために、必要に応じて探索を終了してください。
インポート
import CoreLocation
クラス
名前 | 機能 |
CLLocationManager | iBeaconを含めた位置情報の探索・検知をまとめて制御 |
CLLocationManagerDelegate | CLLocationManagerのデリゲート |
CLBeaconRegion | 探索したいiBeaconの情報を設定したRegion 親クラスはCLRegionクラス |
CLBeacon | 検知されたBeaconの情報を格納 取得できる情報は下記の通り
|
CLRegionState | 検出中のRegionの現在の状態(3種類)を格納
|
CLBeaconMajorValue | Major値 |
CLBeaconMinorValue | Minor値 |
なおUUIDはNSUUID?型、Region名はString型で定義します。
メソッド – CLLocationManager
名前 | 機能 |
[クラスメソッド] authorizationStatus() | 取得:アプリに位置情報利用の許可があるか |
[クラスメソッド] isMonitoringAvailable() | 取得:デバイスの探索に対応しているか |
[クラスメソッド] locationServicesEnabled() | 取得:OS設定画面の位置情報がオンであるか |
[クラスメソッド] isRangingAvailable() | 取得:デバイスがレンジングに対応しているか |
requestAlwaysAuthorization() | アプリが位置情報を使うことの許可を求めるダイアログを出すリクエスト(authorizationStatus()が.notDeterminedのとき、つまり初回起動時のみ有効) この他にrequestWhenInUseAuthorization()というリクエストもある |
requestState() | didDetermineStateデリゲートを明示的に呼び出す |
startMonitoring() | Regionの探索を開始 |
stopMonitoring() | Regionの探索を停止 |
startRangingBeacons() | 検知したRegion内のiBeaconのレンジングを開始 |
stopRangingBeacons() | 検知したRegion内のiBeaconのレンジングを停止 |
rangedRegions.contains() | 引数に指定したRegionが今レンジングされているか |
デリゲート – CLLocationManagerDelegate
名前 | 機能 |
didChangeAuthorization | 契機:アプリへの位置情報の許可状況が変化したとき 使い方:許可がある場合はRegion探索開始 |
didStartMonitoringFor | 契機:Regionの探索が開始されたとき 使い方:既にinsideしているRegionがないかを確認するために、CLLocationManager#requestState()を実行する |
didEnterRegion | ※今回は使わないことにしました 契機:Regionの探索条件に合ったiBeaconが最初に検知されたとき 使い方:検知したRegion内のiBeaconのレンジング処理を開始する契機にできる |
didExitRegion | ※今回は使わないことにしました 契機:Regionの探索条件に合ったiBeaconが全て検知されなくなったとき使い方:検知したRegion内のiBeaconのレンジング処理を終了する契機にできる |
didDetermineState | 契機:didEnterRegion、didExitRegionが発生したとき、CLLocationManager#requestState()が実行されたとき 使い方:Regionの状態(inside/outside/unknown)で処理をわけたいときに使う 検知したRegion内のiBeaconのレンジングを開始・停止する契機にできる |
didRangeBeacons | 契機:レンジング中にiBeacon情報が到着したとき 使い方:iBeaconの情報を取得して、内容に応じた処理をする |
rangingBeaconsDidFailFor | 契機:レンジング中にエラーが発生したとき 使い方:エラー内容に応じた処理をする |
プロパティ – CLLocationManager
名前 | 機能 |
desiredAccuracy | Beacon情報の通知頻度の指定 |
delegate | デリゲート先の指定 |
allowsBackgroundLocationUpdates | バックグラウンド状態でも位置情報を更新 |
showsBackgroundLocationIndicator | 位置情報がAlways Useかつバックグラウンド状態のときにユーザーに位置情報の使用を明示 |
プロパティ – CLBeaconRegion
名前 | 機能 |
notifyEntryStateOnDisplay | 画面が点灯したときやデバイスが常にRegion内にあるときに通知する |
notifyOnEntry | RegionのEnterをデリゲートする |
notifyOnExit | RegionのExitをデリゲートする |
CoreLocation.frameworkなどの設定
iBeacon探索に関係する部分のプロジェクトの設定を再掲します。
使用するCapabilities
オンにする項目 | 用途 |
Background Modes – Location updates | アプリがバックグラウンド状態でもBeaconを検知できるようにする許可 |
Info.plistの追加項目
CoreLocationを使う際の許可ダイアログに表示する文言を追加します。文言は適当に書いたものなので、ちゃんとしたものに変更してください。
追加する項目 | 設定値 |
Privacy – Location Always and When In Use Usage Description | App needs this permission. |
Privacy – Location When In Use Usage Description | App needs this permission. |
アプリの状態の違いによるiBeaconの挙動
アプリの状態にはおおよそ下記の3つがあります。今回のアプリは、普段はフォアグラウンドにいるような使い方はしないので、1日の多くはバックグラウンド状態か終了状態でしょう。そこでバックグラウンド時の挙動を見てみました。
- フォアグラウンド状態
- バックグラウンド状態
- 終了(キル)された状態
iBeaconの検知は、フォアグラウンド状態であれば、Regionに含まれる複数台のBeaconそれぞれについてEnter/Exitが発生するのに対して、バックグラウンド状態ではRegionごとに1度の発生となるようです(キル状態では試していません)。複数台のBeaconを使うときは注意してください。
バックグラウンド時の挙動について試してみたところ、なーさんの環境では下記のようになりました。
- Region中の最初のBeacon 1台がEnterした瞬間から約10秒間didRangeBeaconsで検知
- この時間内に他のBeaconがEnterすれば、そのBeaconもdidRangeBeaconsで検知
- 追加でBeaconが検知されても、10秒間から延長されない
- 10秒以降は、新規Beaconを検知してもdidRangeBeaconsが発行されない(内部的に検知はしていると思われます)
例えば、Beaconの電波を止めたのになかなかRegionがExitしないと思ったら、他のBeaconがいた、などの状況確認がフォアグラウンド状態よりもやりづらいように思いました。
次回の予定
なんと今回、CoreLocationの説明のみでコーディングに辿りつきませんでした。
次回こそはBeacon探索・検知機能のコーディングをはじめていきたいと思います。
以上、ご質問・ご指摘等ありましたら、弊社までお気軽にお問い合わせください。
自宅Wi-Fiお知らせアプリ開発【第三回】 Beacon 探索機能編 その2
自宅Wi-Fiお知らせアプリ開発【第四回】 Wi-Fiお知らせ機能編