Android Oreo から、Oreo 以上のバージョンをtargetSdkVersion
にしているアプリケーションがForeground Serviceを起動するには、Context#startForegroundService()
によるサービスの起動とService#startForeground()
による通知の表示の両方を実行しなければならなくなりました。またContext#startForegroundService()
から5秒以内にService#startForeground()
を呼び出さないと、ANRとしてクラッシュレポートが作成されます。
この"Context#startForegroundService()
から5秒以内にService#startForeground()
を呼ぶ"というのが厄介で、ServiceがContext#startForegroundService()
で動き始めたら問答無用で5秒のカウントが始まるため、その5秒以内にService#stopSelf()
などでサービスを止めてもANRになります。
さらに、ANRのときに吐き出されるスタックトレース(実際には例外が飛んでアプリがクラッシュするのでクラッシュレポートも作られるはず)には、Service#startForeground()
を呼ばなかったこと以外の情報が皆無なので、ログ出力などツールの力を借りる必要があります。
ここでService
の起動にいくつかのパラメータが必要なパターンを考えてみます。Service
はActivity
と同様に自分で直接インスタンスをつくることはしないので、Intent
にパラメータを突っ込んで起動させます。このとき、パラメータの検証をService
の責務として、検証が通らないとき(≒Service
が期待するパラメータでないとき)にService#stopSelf()
で止めてしまうと、先程説明したとおりService#startForeground()
を呼ばなかったとしてクラッシュしてしまいます。
よって、Android O からはContext#startForegroundService()
でService
を起動させる側がService
にわたすパラメータの検証をしなければなりません。