Bluetoothと位置情報サービスの権限設定のヒント

iBeaconアプリは周囲のビーコンを検出するためにアクティブなBluetooth接続を必要とします。Bluetoothがないと、アプリは特定の位置関連機能をトリガーするタイミングを知ることができません。iPhoneでのBluetooth設定と権限の管理は、時に複雑になることがあります。権限を正しくリクエストし、電話の状態を適切な順序で確認しないと、開発やテストがより困難になりがちです。以下は、プロセスの各ステップを適切に処理する方法です。

1 — デバイスはBluetooth Low Energy (BLE) に対応していますか?

iBeaconはBLE周波数で動作するため、デバイスがBLEに対応していることが重要です。BLEはiPhone 4S以降、iPad miniやAir、iPad 3rdおよび4th世代のデバイスで利用可能です。BLE対応を確認する必要がない場合もありますが、アプリをBluetooth Low Energyを必要とするように設定することができます。

<key>UIRequiredDeviceCapabilities</key>
<array>
    <string>bluetooth-le</string>
</array>

UIRequiredDeviceCapabilities 配列に bluetooth-le キーを追加することで、非BLE対応デバイスのアプリのダウンロードを制限できます。アプリがiBeacon技術に依存しているため、BLE対応デバイスのみにダウンロードを制限しました。一部のアプリがiBeacon技術に依存していない場合、BLE対応を確認することが絶対に必要です。

let opts = [CBCentralManagerOptionShowPowerAlertKey: false]let manager = CBCentralManager(delegate: self, 
                               queue: nil, 
                               options: opts)func centralManagerDidUpdateState(_ central: CBCentralManager) {
    if central.state != .unsupported {
        //device supports BLE
    }
}

中央マネージャーが作成されると、centralManagerDidUpdateState: がそのデリゲートに呼び出されます。中央マネージャーの状態が .unsupported でない限り、デバイスで BLE がサポートされ、使用可能です。CBCentralManagerOptionShowPowerAlertKey の値に 0 を設定すると、ユーザーにアラートが表示されることはありません。アラートの表示や Bluetooth の権限リクエストについては後で説明します。BLE が利用可能であることが確認できたら、ステップ 2 に進むか、チェックが失敗した場合はビーコン関連の UI 機能を無効化または非表示にしてください。

2 — アプリが位置情報サービスにアクセスする権限を持っているか?

if CLLocationManager.authorizationStatus() == .NotDetermined {
    //位置情報アクセスが許可されていない
}

位置情報サービスの認可ステータスを確認するのは一行のコードです。.NotDetermined は、アプリが権限をリクエストしていない場合のステータスです。位置情報のアクセスには「常に」と「使用中のみ」の2つのレベルがあり、権限を取得するにはユーザーからのアクセス許可をリクエストする必要があります。

let manager = CLLocationManager()
manager.delegate = selfmanager.requestAlwaysAuthorization()
//または
manager.requestWhenInUseAuthorization()

正常に機能するには、これらのアクセスレベルのいずれもアプリの Info.plist ファイルに権限の説明が必要です。

<key>NSLocationWhenInUseUsageDescription</key>
<string>...Detailed reason...</string><key>NSLocationAlwaysUsageDescription</key>
<string>...Detailed reason...</string>

iOS 8 以降はこれらの説明が必要です。説明が Info.plist に存在しない場合、アプリはユーザーに位置情報サービスへのアクセスを促すことができません。アプリが開いていないときやバックグラウンドにあるときに iBeacon イベントを通知されるためには、「常に」アクセスをリクエストする必要があります。

アプリが開いているときだけ iBeacon の監視が必要な場合は、「使用中のみ」アクセスをリクエストします。「常に」アクセスは一部のユーザーを怖がらせる可能性があります。ユーザーはその影響を理解せずにアクセスを拒否するかもしれません。その場合、設定に移動して再度アクセスを有効にする必要があります。これを簡単にするためには、以下のコードを使用してユーザーをアプリの設定ページに直接移動させることができます。

if let url = URL(string: UIApplicationOpenSettingsURLString){
    UIApplication.shared.open(settingsURL, options:[:])
}

https://miro.medium.com/v2/resize:fit:700/1*I1D4dtWN1hVXvOhmKu22MQ.jpeg

ユーザーが権限リクエストの準備をする方法

アプリを離れてアクションを実行させるのは決して良いアイデアではありません。権限の拒否を避けるためには、Info.plist に記載する説明を非常に詳細にすることが重要です。アプリがどのように位置情報データを使用し、その必要性について詳しく説明してください。アプリ内に権限の必要性を説明する画面を用意することがさらに良いです。この画面はリクエストの「バッファー」ダイアログとして機能します。ユーザーが自分で権限リクエストをトリガーできるようにする手段を提供します。ユーザーがリクエストを開始することで、システムリクエストの表示に驚くことはなく、リクエストを許可する決定を既にしているでしょう。

「バッファー」ダイアログに拒否オプションを提供することで、不必要な拒否を避けるのに役立ちます。拒否オプションがあれば、権限を許可する準備ができていないユーザーにシステムレベルのリクエストを表示せずに済みます。アプリ内から再度リクエストをトリガーできる手段を提供することで、位置情報アクセスを許可する準備ができているユーザーのみにシステムレベルの権限ダイアログが表示されます。

3 — 位置情報サービスがオンになっているか?

switch CLLocationManager.authorizationStatus() {
    case .AuthorizedAlways, .AuthorizedWhenInUse:
        // locations services are on
    case .NotDetermined:
        // still need to request access
    case .Restricted, .Denied:
        // locations services off or denied

アプリがアクセスをリクエストした後、位置情報サービスがオンかどうかを確認できます。位置情報サービスがオフの場合、ユーザーが手動で設定に移動してグローバルな位置情報サービスのスイッチを切り替える必要があります。先に言及した設定 URL コードを使って、ユーザーを直接設定アプリに移動させることができます。iOS 7 以前では、このコードは機能しません。iOS 7 以下の場合は、画面ごとの「指示」を含むダイアログをポップアップさせ、ユーザーがグローバル位置情報サービススイッチを見つける手助けをするのが最善です。

4 — Bluetooth がオンになっているか?

let opts = [CBCentralManagerOptionShowPowerAlertKey: true]let manager = CBCentralManager(delegate: self, 
                               queue: nil, 
                               options: opts)

これはかなり直感的です。Bluetooth がオンでないと、電話は iBeacons を検出できません。Bluetooth がオフの場合、このコードはユーザーに Bluetooth をオンにするよう促すダイアログを表示します。アプリが開いていない場合、問題があることをユーザーに通知する方法はありません。ここで GPS が役立ちます。GPS を統合したアプリは、Bluetooth がオフで位置情報サービスの権限が許可されているユーザーにも対応できます。ユーザーが iBeacon を囲む広い領域に入ると、アプリは GPS 通知を受け取り、Bluetooth がオフの場合はロック画面に通知を送信できます。