[Android Q] foreground serviceでの位置情報アクセス

## はじめに 

Android Q (API level 29)より、新しい位置情報パーミッション `ACCESS_BACKGROUND_LOCATION` が追加された。 が、ドキュメントを見ても、特に **フォアグラウンドサービス** における、動作の振る舞いがわかりにくかったので、調べてみた。

本記事は、 `Android Q beta 4` にて動作確認結果である。

## パーミッションについて

* `ACCESS_COARSE_LOCATION`,  `ACCESS_FINE_LOCATION` パーミッション： Android Qより前からあるパーミッション。   Android Qより前では、フォアグラウンド／バックグランドの区別はとくになく、位置情報が取得可能であった。 しかし、Android Qでは、フォアグラウンド時のみ 位置情報取得が可能になる。
* `ACCESS_BACKGROUND_LOCATION` パーミッション: Android Q (API level 29)で新たに追加されたパーミッション。 バックグランド時の位置情報取得が可能になる。 このパーミッションは `ACCESS_COARSE_LOCATION` or `ACCESS_FINE_LOCATION` と合わせて使う必要がある。

つまり、

* `ACCESS_COARSE_LOCATION` or `ACCESS_FINE_LOCATION` のみの場合は、フォアグラウンド時のみ位置情報が取得。 パーミッション要求ダイアログなどでは、 `Allow only while using the app` と表示される。
* (`ACCESS_COARSE_LOCATION` or `ACCESS_FINE_LOCATION`) and `ACCESS_BACKGROUND_LOCATION` のみの場合は、フォアグラウンド時もバックグランド時も位置情報取得が可能。 パーミッション要求ダイアログなどでは、 `Allow all the time`  と表示される。


さて、フォアグラウンド・サービスは、フォアグラウンド扱いなのか、バックグランド扱いなのか、バックグランドで位置情報を取得するかを調べてみる。



## `targetSdkVersion` 28以下 (Android Qより前）でビルドしたアプリケーションをAndorid Q デバイスで動作させる場合

* `ACCESS_BACKGROUND_LOCATION` は、request permissinに自動的に付与される。つまり、AndroidManifest.xml に、 次の指定は不要。 （SDKが `ACCESS_BACKGROUND_LOCATION` を知らないので、当然指定してもエラーになる） 
 
```
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
```

* `ACCESS_BACKGROUND_LOCATION` の実行時パーミッションリクエストは、  `ACCESS_COARSE_LOCATION `パーミッションもしくは、 `ACCESS_FINE_LOCATION` パーミッションのリクエスト時に、自動でなされる。 ので、コードの変更も不要。

* 結果として、パーミッションリクエストダイアログには、次の３つが表示される。
    * `Allow all the time`
    * `Allow only while using the app`
    * `Deny`

<img src="https://developer.android.com/preview/images/request-device-location.svg" width="20%">


* 上記パーミッションのうちの `Allow all the time` が選択された場合のみ、 Foreground ServiceはActivityが バックグランド時でも位置情報取得が可能になる。


## `targetSdkVersion` 29 (Android Q)でビルドしたアプリケーションをAndroid Q デバイスで動作させる場合


* `ACCESS_BACKGROUND_LOCATION` は不要。
* よって、 `ACCESS_BACKGROUND_LOCATION` のパーミッションリクエストも不要
* Foreground Serviceが、Locationデータが必要と設定するために、AndroidManifest.xml に、foregroundServiceType="location" の設定をする。

```xml:AndroidManifest.xml

<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" 
    ... />
</service>
```

* `ACCESS_BACKGROUND_LOCATION` パーミッションはないので、パーミッションリクエストダイアログには、次の２つが表示される。
    * `Allow only while using the app`
    * `Deny`
*  `Allow only while using the app`が選ばれた場合、フォアグラウンドサービスは、バックグランドでも位置情報取得が可能になる。


`ACCESS_BACKGROUND_LOCATION` を設定することで、  `targetSdkVersion` 28以下 (Android Qより前） と同様の設定も可能。


## 参考
* https://developer.android.com/preview/privacy/device-location?hl=ja
* https://developers-jp.googleblog.com/2019/04/giving-users-more-control-over-their.html


## 2020/06/12 Update

https://developer.android.com/training/location/permissions#foreground で、 フォアグラウンドサービスはForeground Location (つまりBackground Loaction ではない） ことが明記されている。  なので、調査は正しい。

```
Your app is running a foreground service. When a foreground service is running, the system raises user awareness by showing a persistent notification. Your app retains access when it's placed in the background, such as when the user presses the Home button on their device or turns their device's display off.
```