Playストアの「フォアグラウンド サービスの権限」に対応する

# いきなりFGSとか言われる

すっかり毎年恒例となった Play ストアの Android 最新版への対応(※これをやらないとそのアプリの更新ができなくなる)ですが、2024年も Android 14 への対応期限が 8/31 に迫ってきたので targetSdk を 33 から 34 にしてビルド＆実行してみたところ、下記のエラーが起きて全然動きませんでした。

```
android.app.MissingForegroundServiceTypeException: Starting FGS without a type  callerApp=ProcessRecord{435fc46 16794:jp.takke.cpustats.debug/u0a296} target
  at android.app.MissingForegroundServiceTypeException$1.createFromParcel(MissingForegroundServiceTypeException.java:53)
  at android.app.MissingForegroundServiceTypeException$1.createFromParcel(MissingForegroundServiceTypeException.java:49)
  at android.os.Parcel.readParcelableInternal(Parcel.java:5016)
  at android.os.Parcel.readParcelable(Parcel.java:4998)
  at android.os.Parcel.createExceptionOrNull(Parcel.java:3178)
  at android.os.Parcel.createException(Parcel.java:3167)
  at android.os.Parcel.readException(Parcel.java:3150)
  at android.os.Parcel.readException(Parcel.java:3092)
  at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6960)
  at android.app.Service.startForeground(Service.java:776)
  at jp.takke.cpustats.NotificationPresenter.doNotify(NotificationPresenter.kt:95)
  at jp.takke.cpustats.NotificationPresenter.updateNotifications(NotificationPresenter.kt:63)
  at jp.takke.cpustats.UsageUpdateService.execTask(UsageUpdateService.kt:293)
  at jp.takke.cpustats.UsageUpdateService.onStartCommand$lambda$0(UsageUpdateService.kt:222)
  at jp.takke.cpustats.UsageUpdateService.$r8$lambda$QjSqggJ0C5qeCl9detYR4r2hiz8(Unknown Source:0)
  at jp.takke.cpustats.UsageUpdateService$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
  at android.os.Handler.handleCallback(Handler.java:959)
  at android.os.Handler.dispatchMessage(Handler.java:100)
  at android.os.Looper.loopOnce(Looper.java:232)
  at android.os.Looper.loop(Looper.java:317)
  at android.app.ActivityThread.main(ActivityThread.java:8592)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
```

`Starting FGS without a type` ということで、FGS(フォアグラウンドサービス)を使うアプリには特別な権限と宣言が必要になったようですね。

公式情報：
- [Understanding foreground service and full\-screen intent requirements \- Play Console Help](https://support.google.com/googleplay/android-developer/answer/13392821)
- [フォアグラウンド サービスと全画面インテントの要件について \- Play Console ヘルプ](https://support.google.com/googleplay/android-developer/answer/13392821?hl=ja)




# フォアグラウンドサービスの権限を追加する

今回は CPU 使用率を通知エリアに表示する [CPU Stats](https://play.google.com/store/apps/details?id=jp.takke.cpustats&hl=ja) というアプリが対象です。ソースコードは [github](https://github.com/takke/cpustats) で公開しています。

アプリの実行時は上記のエラーが logcat に出ますが Android Studio でも下記のエラーが出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/6f045942-68e3-a332-e0f1-e49941c48689.png)

```
To call Service.startForeground(), the <service> element of manifest file must 
have the foregroundServiceType attribute specified More... (Ctrl+F1) 

Inspection info: For targetSdkVersion >= 34, to call Service.startForeground(), 
the <service> element in the manifest file must have the foregroundServiceType 
attribute specified.
```

`targetSdkVersion`が34以上の場合は、Manifestの `service` に `foregroundServiceType` 属性の記載が必要ということですね。

具体的には下記のように修正しました。`foregroundServiceType`に指定する値に応じて `uses-permission` も必要です。

```xml:AndroidManifest.xml
    <!-- ↓ FOREGROUND_SERVICE_DATA_SYNCを追加 -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

    <application>

        <!-- ↓ foregroundServiceType を追加 -->
        <service
            android:name=".UsageUpdateService"
            android:foregroundServiceType="dataSync"
            android:enabled="true"
            android:exported="false">
        </service>

    </application>
```

該当コミット：

https://github.com/takke/cpustats/commit/27effe89d79ce72ac9a0d823f53ff24f7b69dbc3

本アプリでは `android:foregroundServiceType` に `dataSync` を指定しましたが、使用する service の用途によっては `location` や `camera`、`mediaPlayback` などを選びます。
どれを指定するべきかは [フォアグラウンド サービスと全画面インテントの要件について \- Play Console ヘルプ](https://support.google.com/googleplay/android-developer/answer/13392821?hl=ja) に表で書いてありますがいまいち分かりにくい感じがします。

もしどれにも該当しないということであれば「その程度なら service 使うな」あるいは「そんなアプリは作るな」ということでしょうかね。強めの意思を感じます。

ちなみに拙作の [Lossless Video Cutter](https://play.google.com/store/apps/details?id=jp.takke.videocutter&hl=ja) というアプリではバックグラウンドで動画の変換処理を行うために `service` を使っていましたが(後述の動画提出も含めると)面倒だったので `WorkManager` に置き換える形で、Android 14(targetSdkVersion=34)に対応しました。

用途によっては`service`を`WorkManager`や`JobScheduler`に置き換える方法もあるのを忘れないようにしたいところです。

※ちなみに CPU Stats は最小で0.5秒おきにCPU使用率を検出する必要があるので `WorkManager` に置き換えることはできませんでした。


# Playストアで更新しようとすると動画を作れと言われる

無事に実行出来るようになり、aabを作ってストアに申請しようとすると「審査に送信」しようとする段階でエラーが出ます。赤帯でめちゃめちゃ怖いですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/790c401c-faf0-5433-1a83-b6dc30765d58.png)

「問題を表示」をクリックすると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/a851dba1-fe1e-e8b2-09fe-9878e63983fa.png)

```
フォアグラウンド サービスの権限の申告が不完全です

Android 14 で導入されたフォアグラウンド サービスの権限へのアクセスをリクエストするすべてのデベロッパーが、
この申告を完了するか、アプリのマニフェストからこれらの権限を削除する必要があります
```

などと言われますので、「申告を完了する」をクリックすると「フォアグラウンドサービスの権限」の申告画面が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/38a91f7f-3a2e-b99e-8b77-ee7471d7a7d3.png)

※どのチェックボックスを選んでも「動画リンク」を要求されます。

今回は「その他のタスク⇒その他」を選び、使用している状況を示す動画を作り、YouTubeにアップロードして下記のように記載しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/ec134f7b-3abe-4c0f-1368-9cd9b66d20c8.png)

提出した動画はこちら。Android Studio で実機で録画してちょっと説明文付けただけです。

https://youtube.com/shorts/6n1TbEIlOHE


# 審査にちょうど2日かかった

「こんな動画で大丈夫かな？」と思いつつ 7/16(火) 11:30 頃に申請、なかなか結果が出ないとやきもきしていましたが 7/18(木) 11:30 頃に審査が無事完了しました。
ちょうど48時間でした。
今年は例の「デベロッパー確認」もあるためか、Playストアの審査がいつもより長めな気がしますね。

以上です。お疲れさまでした。


さあ次は別アプリ(Data Stats)のFGS権限申請をしないと・・・。

# (7/19追記)DataStatsも1日で審査が完了しました
- Data Stats のFGS権限も 7/18 14:30頃に申請し、7/19 14:30頃に審査完了となりほぼ24時間で審査完了となりました。


# 参考
- [Play Console のフォアグラウンドサービスの権限を申告してみた \- たくさんの自由帳](https://takusan.negitoro.dev/posts/android_foreground_service_permission_play_console/)