🔨

iOS13以降の位置情報の利用許可について

2021/07/08に公開

iOS13 以降の位置情報の利用許可ついて必要なものや何を実行するとどのような結果が返るのかなどをまとめてみました。

位置情報を利用する上で必要な準備

  • Info.plist で NSLocationWhenInUseUsageDescription or NSLocationAlwaysAndWhenInUseUsageDescription のどちらかもしくは両方を追加します。
  • NSLocationWhenInUseUsageDescription はアプリがフォアグラウンドで実行されていて、位置情報にアクセスする場合に指定します。
  • NSLocationAlwaysAndWhenInUseUsageDescription はアプリがバックグラウンドで実行されていて、位置情報にアクセスする場合に指定します。

位置情報の利用許可のステータス

CLAuthorizationStatus

定義 意味
0 notDetermined 未選択/未定義
1 restricted ペアレンタルコントロールなどの影響で制限中
2 denied 利用拒否
3 authorizedAlways 常に利用許可
4 authorizedWhenInUse 使用中のみ利用許可

設定アプリから確認できる位置情報の利用許可のステータス一覧

定義 備考
なし 「許可しない」を選択(CLAuthorizationStatus==denied)
次回確認 「1度だけ許可」を選択など(CLAuthorizationStatus==notDetermined)*
このAppの使用中のみ許可 「Appの使用中は許可」を選択(CLAuthorizationStatus==authorizedWhenInUse)
常に 「”常に許可”に変更」を選択((CLAuthorizationStatus==authorizedAlways

*位置情報の利用許可のアラートで「1度だけ許可」を選択するとアプリ起動中は一時的に authorizedWhenInUse のステータス状態になり、位置情報が利用できます(設定アプリの表示では「次回確認」)。ただし、アプリを終了させると notDetermined のステータスになります。

位置情報の利用許可のアラートについて

locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()

上記どちらかの呼び出しでアプリ使用中の位置情報の利用許可のアラートが表示できます。利用許可のステータスに変更があった場合は以下メソッドが呼ばれます。

locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus)

requestAlwaysAuthorization を使用する場合は Info.plist で NSLocationAlwaysAndWhenInUseUsageDescription が必須です。requestWhenInUseAuthorization を使用する場合は Info.plist で NSLocationWhenInUseUsageDescription が必須です。

iOS 13 以降ではどちらの呼び出しでも以下の画面(アプリ使用中のみ許可するかどうか)が表示されます。説明文言も NSLocationWhenInUseUsageDescription で指定した文言が表示されます。また、これらはステータスが notDetermined の時しか表示されないので注意が必要です。

requestWhenInUseAuthorization で上記画面を呼び出した場合に「Appの使用中は許可」を選択すると authorizedWhenInUse が返り、設定アプリの表示も「このAppの使用中のみ許可」になります。

requestAlwaysAuthorization で呼び出した場合に「Appの使用中は許可」を選択するとステータスは authorizedAlways が返りますが、設定アプリの表示では「このAppの使用中のみ許可」になっています。コード上の位置情報の利用許可のステータスは authorizedAlways ですが、設定アプリ上では「このAppの使用中のみ許可」と一致しません。これらが初めて一致するのは OS からアプリ使用していない時でも位置情報を利用するかのアラート(以下画面)が自動的に表示され、「”常に許可”に変更」を選択した場合になります。

よって、requestAlwaysAuthorization で「Appの使用中は許可」を選択したときのステータス authorizedAlways は一時的なものであり、以下のアラートで「”常に許可”に変更」を選択して初めて確定されるもののようです。逆に「”使用中のみ許可”のままにする」を選択するとステータスは authorizedWhenInUse になり、設定アプリの表示も「このAppの使用中のみ許可」になります。

表示・返り値まとめ

利用許可要求メソッド 利用可否の選択 返るCLAuthorizationStatusの値 設定アプリでの表示
requestAlwaysAuthorization 「Appの使用中は許可」 authorizedAlways 「このAppの使用中のみ許可」
requestAlwaysAuthorization 「一度だけ許可」 authorizedWhenInUse → notDetermined * 「次回確認」
requestAlwaysAuthorization 「許可しない」 denied 「なし」
requestWhenInUseAuthorization 「Appの使用中は許可」 authorizedWhenInUse 「このAppの使用中のみ許可」
requestWhenInUseAuthorization 「一度だけ許可」 authorizedWhenInUse → notDetermined * 「次回確認」
requestWhenInUseAuthorization 「許可しない」 denied 「なし」

* 「一度だけ許可」を選択した場合はアプリを終了しない限りは authorizedWhenInUse のステータスになり、アプリを終了すると notDetermined のステータスになります。

アプリを使用していない時の位置情報の利用許可のアラート(「”使用中のみ許可”のままにする」か「”常に許可”に変更」を選択)のアラートを強制的に表示させる方法

上述したようにコード上での位置情報の利用許可のステータスと設定アプリ上でのステータスの表示が微妙に一致しない場合が存在します。設定アプリの表示を「常に」に変更する・させるためには主に以下の手順になると思われます。

  1. requestAlwaysAuthorization で「Appの使用中は許可」を選択してもらい、アプリ使用していない時でも利用するか確認するアラートが自動的に表示され、「”常に許可”に変更」を選択してもらう
  2. 設定アプリから該当アプリの位置情報に利用許可の設定を「常に」に変更してもらう

1.の方は通常のフローですが、アプリを使用していない時の位置情報の利用許可のアラートがいつ表示されるのか不明であり、表示タイミングを制御できません。2.の方はユーザに明示させることで変更してもらうことは可能ですが、設定アプリを一度開かないといけないです。

通常であれば、「常に」に変更させるために自動的に表示されるアプリを使用していない時の位置情報の利用許可のアラートが必要です。これを強制的に表示させる方法を紹介します。具体的には以下手順で強制的に表示可能でした。

  1. requestWhenInUseAuthorization でアプリ使用中の位置情報の利用許可のアラートを表示
  2. 「Appの使用中は許可」を選択してもらう(CLAuthorizationStatus が authorizedWhenInUse に変更される)
  3. requestAlwaysAuthorization でアプリを使用していないの時の位置情報の利用許可のアラートを表示
  4. 「”常に許可”に変更」を選択してもらう(CLAuthorizationStatus が authorizedAlways に変更される)

まず、requestWhenInUseAuthorization で「Appの使用中は許可」が選択されるとステータスは authorizedWhenInUse になります。その状態で requestAlwaysAuthorization を呼び出すとアプリを使用していない時の位置情報の利用許可のアラートが表示されます。ただし、requestWhenInUseAuthorization で「一度だけ許可」を選択し、ステータスが authorizedWhenInUse の状態で requestAlwaysAuthorization を呼び出してもアプリを使用していない時の位置情報の利用許可のアラートは表示されないので注意して下さい。

なぜ、この手順で通常フローで自動的に表示されるはずのアプリを使用していない時の位置情報の利用許可のアラートが表示されるかは詳しく調べていないので今のところ不明です...。ただ、通常フローで2段階(使用中→常に)で位置情報の許可をユーザに確認していることと同様なことを行っているため、実現できていると考えます。なお、動作確認は iOS 13.7 と iOS 14.4 で確認しました。

サンプルコード

参考

https://qiita.com/gaussbeam/items/96612baed85edb8f7c6d
https://qiita.com/YujiHamada3/items/3d750c336ecfb51677d0
https://support.fanship.jp/hc/ja/articles/360046873654-位置情報の許諾ダイアログについてまとめ-iOS13-Android10-

Discussion