質問: Androidアプリ開発初心者です。 今回初めてServiceを使ってバックグラウンド処理を行うアプリを作成しようとしています。 いくつかのドキュメントを参照したところ、ServiceをstartService()によって起動した場合、Serviceは明示的にstopService()もしくはstopSelf()で停止するまで終了しない、と記載されていたので、Applicationを終了してもServiceは動作し続けるものと理解しました。 ところが、ActivityからstartService()でServiceを起動した後、そのActivityが動作しているアプリケーションをRecentAppのリストから削除すると、Service が停止している様に見えます。 ただこの時ServiceのonDestroy()は呼ばれていません。 (ホームボタンでアプリがバックグラウンドに行っただけであれば確かにServiceは生きています) これは正しい挙動なのでしょうか? 確かに考えてみると、Serviceは呼び出し元のアプリケーションプロセス上で動いているので、Recentから消すことでアプリケーションのプロセスが消滅してしまえば存続できるはずはない気がします。 だとするとServiceのライフタイムは実質Activityの終了と同等(onDestroy()まで)なのではないかと思えてしまえます。 しかも、Serviceが終了するまえに onDestroy() が呼ばれないので終了処理を行うことができません。 ActivityのonDestroy()では、必ずstopService()するようにすべきなのでしょうか。 初歩的な質問で恐縮ですが、よろしくお願いいたします。
回答: 正しい挙動になります。 `Service` についてよく誤解されることではありますが、あくまで「画面を持たないアプリケーションのコンポーネントのひとつ」であって、アプリケーションとは無関係に動くバックグラウンド処理ではありません。 OS がリソースを必要とすれば(他のアプリケーションが何らかの重い処理を行うなど)、いつでも `Service` は強制終了されます。 `startService()` によって起動されたサービスを必ず `stopService()` もしくは `stopSelf()` で停止させる必要があるということが強調されるのは、サービスが常駐し、永続的に動作するからではなく、**適切に終了処理を書かないと OS のリソースを無駄遣いする可能性がある** ためです。 > > Serviceは呼び出し元のアプリケーションプロセス上で動いている > > > これはデフォルトの挙動で、マニフェストによって動作するプロセスを変更することができます。 > > Serviceのライフタイムは実質Activityの終了と同等 > > > `Application` と `Activity` と `Service` は異なる生存期間を持ちます。 `Activity` は「画面を持つアプリケーションのコンポーネント」であり、その有用性はユーザーと対話をしている間(`onResume()`~`onPause()`)にあります。ユーザーとの対話が終われば破棄されやすくなります。 `Service` は「画面を持たないアプリケーションのコンポーネント」であり、`startService()` で開始された場合には、`Service` 自身が処理を完了したときに `stopSelf()` を呼び出すか、`Service` を呼び出したコンポーネントが処理を中断させるために、`stopService()` を呼び出すまで生存します。 `Application` は全てのコンポーネントを統括する存在です。「設定>アプリケーション>強制停止」で`Application` プロセスがキルされると、その子コンポーネントである `Activity` や `Service` は同時に終了します。 また、「最近使ったアプリ」から `Activity` をスワイプすると、その `Activity` が起動した通常の `Service` も終了します。 これらは `Activity` と `Service` の生存期間が等しいことを意味しているわけではないです。 > > ActivityのonDestroy()では、必ずstopService()するようにすべきなのでしょうか。 > > > これについては、実際にどのような動作を期待しているのかによりますが...。 `startService()` で動作させたい `Service` の処理は、`Activity` が終了されたかどうかを関与しないものとなるはずです。この疑問が出るということは、そもそも `Service` である必要がないか、または「バインドされたサービス」の方がより適切である可能性が高いです。 **参考になりそうなリソース** * Service のリファレンス(What is a Service? に簡潔な説明があります) * サービス * バインドされたサービス