自分用です。
間違ってるかもしれないので、下記を直接見てね。
英語と日本語のページ内容がいくつか違う様。
Serviceとは
Service:
ユーザーインターフェイスを使わず、バックグラウンドで長時間処理を実行できるアプリケーションコンポーネントです。
他のアプリケーションコンポーネントを開始することもできるし、ユーザーが他のアプリケーションに変更しても、バックグラウンドで処理し続けます。
さらに、コンポーネントとサービスをバインドして交信し、プロセス間通信もできます。例えば、ネットワーク処理、音楽再生、ファイルI/O、コンテンツプロバイダー通信など、すべてバックグラウンドで処理できます。
3種類のService
■Foreground
foregroundServiceは、ユーザーに通知されている処理を実行します。例えば、オーディオアプリはForegroundServiceを使って、オーディオトラックで再生します。ForegroundServiceでは通知を表示させます。ユーザーがアプリを操作してない時は、ForegroundServiceで処理し続けます。
■Background
BackgroundServiceはユーザーによって直接気が付かない処理を実行します。例えば、アプリのストレージを圧縮するサービスの場合、それはバックグラウンド処理となります。
Note: アプリがAPI26以降で、アプリがforegroundに設定されてなければ、システムはバックグラウンドサービスの実行に制約を課します。このようなケースでは、代わりにスケジュールされた作業を行います。 |
■Bound
bindService()でサービスをアプリケーションコンポーネントにバインドします。バインドされたサービスは、コンポーネントと通信するため、クライアントサーバーインターフェイスを提供します。例えば、リクエスト送信、結果受信、プロセス通信など。
バインドされたサービスは、他のアプリケーションコンポーネントがサービスにバインドされている限り、終了することはありません。
サービスは、明示的な開始、バインド、どちらも使えますが、ドキュメントでは開始とバインドを分けて説明します。
実装は、onStartCommand()でサービス開始を要求するか、onBind()でバインドを許可するか、のどちらかで行います。
どのアプリケーションコンポーネントも、任意のアクティビティを使うのと同じ方法で、Intentを使って同じサービスを開始できます。マニュフェストに他のアプリからの利用禁止を定義することも可能です。詳しくは>https://developer.android.com/guide/components/services#Declaring
COUTION: 特に方法を指定しない限り、Serviceが自身のスレッドを作成することなく、別のスレッドで実行されることもありません。 なので、MP3再生やネットワーク処理など負担のかかる処理では、UIのフリーズエラーを予防するために、サービス内に新しいスレッドを作成し、別スレッドで処理する必要があります。 |
ServiceとThreadどっちを使う?
・ Serviceはバックグラウンド処理する場合 ・ Threadはメインスレッド以外で処理する必要がある場合 例えば、アクティビティを実行してる間だけ音楽再生する場合は、onCreate()にスレッドを作成し、onStart()で実行開始、onStop()で停止。 Threadの代わりに、AsyncTascやHandlerThreadも使えます。 |
Service作成にあたって重要なOverrideメソッド
onStartCommand() / onBind() / onCreate() / onDestroy()
■onStartCommand()
アクティビティなどの他のコンポーネントが、**startService()を呼び出して、Serviceの開始を要求したときに、システムがonStartCommand()**を呼び出します。onStartCommand()が実行されるとServiceが開始されます。
onStartCommand()を実装する時は、Service完了時に**stopSelf()かstopServece()**で、自身でサービスを停止させます(バインドのみを提供する場合には、onStartCommand()は実装しなくてよい)。
■onBind()
**bindService()を呼び出して、他のコンポーネントをServiceにバインドさせるときに、システムがonBind()**を呼び出します。
onBind()実装時にはIBinderを返して、クラインとがServiceとの通信に使うインターフェースを提供する必要があります。
onBind()の実装は常に必要だけれど、バインドを許可しない場合はnullを返す必要があります。
■onCreate()
onStartCommand()かonBind()を呼び出す前で、サービスが始めて作成された時に、1度限りのセットアップ処理をするために呼び出されるメソッド。
■onDestroy()
Serviceが長時間使われなかったり、破棄されたときに呼ばれるメソッド。スレッドや登録済みリスナー、レシーバーのリソースをクリーンアップするのに、Serviceはこのメソッドを実装します。このメソッドは、Serviceが受け取る最後の呼び出しです。
Serviceの終了
■stopSelf() stopService()
onStartCommand()のstartService()によってコンポーネントがServiceを開始したら、サービスがstopSelf()で自身を終了するか、他のコンポーネントがstopService()を実行するまで、サービスは稼働し続けます。
■unbind
コンポーネントが、onStartCommand()を呼ばずに、bindService()によってServiceを生成したら、コンポーネントがServiceにバインドされてる限り、Serviceは稼働し続けます。Serviceがクライアントから全てアンバインドされたら、システムはServiceを破棄します。
■Android System によるServiceの破棄
メモリーが下がり、ユーザーが操作してるアクティビティのシステムリソースを回復させなければならない場合にのみ、アンドロイドシステムはServiceを停止します。ユーザーが使っているアクティビティにバインドされたServiceは、破棄される可能性は低くなります。Foregroundで実行するよう定義したServiceは滅多に破棄されません。
システムは、時間の経過とともに、Serviceのバックグラウンド・タスク・リストでの位置付けを下げます。開発者はシステムによるServiceの復帰処理をデザインしてください。onStartCommand()の戻り値にもよりますが、もしシステムがServiceを破棄したら、システムはリソースが回復するなり、Serviceを復帰させます。詳しくは>https://developer.android.com/guide/components/processes-and-threads.html
マニフェスト宣言
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
~で、ServiceやServiceを実行するプロセスを開始するために必要なプロパティを定義します。
■android:name
Serviceのクラス名を指定する。唯一の必須属性、変更不可
アプリの安全性を保つため、Serviceを開始したりバインドするときは、常に明示的Intentを使います。
COUTION: アプリの安全性を確保するため、Serviceを開始するときには常に明示的Intentを使い、ServiceのIntentフィルタは宣言しません。 暗黙的なインテントは危険です。開発者がインテントから返されるServiceを確認できなかったり、ユーザーがServiceの開始を認識できなかったりします。 Android5.0(API21)以降では、bindService()を呼び出すと、システムは例外を投げます。 |
■android:exported
android:exported属性にfalseを定義して追加することで、そのアプリにのみServiceを使えるようにできます。この方法なら、明示的Intentを使っていても、他のアプリからServiceが呼ばれません。
■android:description
Note: ユーザーはディバイス上で、どのServiceが稼働しているか確認できます。ユーザーが許可してない、もしくは信頼していないServiceを見つけたら、ユーザーはそのServiceを停止できます。 ユーザーが誤ってServiceを停止するのを避けるには、アプリのマニフェストの要素に、android:description属性を追加して、そのServiceが必要/有用であることを短文で説明してください。 |
もっと詳しくServiceのライフサイクル管理をしりたかったら>https://developer.android.com/guide/components/services#Lifecycle
どのServiceを開始するかについて、あいまい性を残す場合には、ServiceにIntentフィルタを定義して、Intentからコンポーネント名を除外して、その後にターゲットのサービスのあいまい性を解消するsetPackage()
でIntentのパッケージを設定する必要があります。
要求されたServiceを生成する
要求されたServiceとは:
他のコンポーネントがstartService()を呼び出し、onStartCommand()メソッドを使って、生成を要求されたService。
Serviceは、Serviceが開始されると、呼び出したコンポーネントから独立して、独自のライフサイクルを持ちます。
呼び出し元のコンポーネントが破棄されても、Serviceはバックグラウンドで無期限に稼働します。ですから処理が終了したら、stopSelf()でServiceが自身を終了させるか、stopService()で、他のコンポーネントからServiceを終了させます。
アクティビティなどのアプリケーションコンポーネントは、startService()の呼び出し、Intentの受け渡し、によってServiceを開始できます。IntentはスタートするServiceを指定し、そのServiceが使うデータを受け渡します。ServiceはonStartCommand()メソッドで、このIntentを受け取ります。
例えば、オンラインデータベースでアクティビティがデータ保存すると仮定します。そのアクティビティはコンパニオンサービスを開始し、startService()にIntentを渡すことで、保存するデータを配信できるようにします。
ServiceはonStartCommand()によってIntentを受け取り、インターネットを通じてデータベース処理を実行します。処理が終了すると、Serviceは自身を終了させ、Serviceは破棄されます。
COUTION: Serviceは宣言されているアプリケーションと同じプロセスで稼働し、デフォルトではそのアプリケーションのメインスレッドで稼働します。 ユーザーが同じアプリケーションのアクティビティを操作してる最中に、Serviceが集中的に稼働したり、ブロック操作を実行したら、アクティビティのパフォーマンスが低下します。 パフォーマンスの低下を防ぐために、Service内で新しくスレッドを作成し、スレッド処理させてください。 |
要求されたサービスを生成するための拡張可能なクラス
Service
全てのServiceの基本クラス。
Serviceはデフォルトでアプリのメインスレッドを使用するため、Serviceの処理によって、アクティビティのパフォーマンスを低下させることがあります。
そのため、このクラスを拡張するときは、Service処理を完結する別スレッドを新しく作成することが重要です。
IntentService
全てのServiceの生成要求を、一件ずつ処理するワーカースレッドを使った、Serviceのサブクラス。Serviceで同時に複数の生成要求を処理する必要がない場合に最適。
onHandleIntent()を実装するだけで、それぞれの生成要求のIntentを受け取り、バックグラウンド処理ができるようになります。
IntentServiceクラスの拡張
Serviceクラスの拡張に比べIntentServiceクラスを拡張したほうが、要求されたServiceをシンプルに実装できます。Serviceクラスを拡張してインテントを処理する方法が適したケースとは、Serviceが(作業キューを介して開始要求を処理するのではなく)複数のスレッドを実行する必要があるケースです。
開始要求されたServiceのほとんどは、同時に複数のリクエストを扱う必要がありません。マルチスレッドを使う設計は危険を伴います。IntentServiceクラスを使ってServiceを実装するのが最善でしょう。
IntentServiceクラスの働き。
- onStartCommand()に配信されたすべてのインテントを実行するためのスレッドを生成します。このスレッドはアプリケーションのメインスレッドから区分します。
- マルチ(複数)スレッドを作成しなくてもいいように、一つずつインテントをonHandleIntent()に渡していく作業キューを生成します。
- 全ての開始要求を処理した後でServiceを停止しますので、stopSelf()<を使う必要はありません。
- onBind()をデフォルトで実装。実装されたonBind()はnullを返します。
- onStartCommand()をデフォルトで実装。実装されたonStartCommand()は、作業キューにインテントと実装されたonHandleIntent()を送信します。
クライアントから求められた作業を完了するために、onHandleIntent()を実装しますが、そのためにはServiceにコンストラクタが必要です。
<参考>IntenServiceの実装例
public class HelloIntentService extends IntentService {
/**
* the super <code><a href="/reference/android/app/IntentService.html#IntentService(java.lang.String)">IntentService(String)</a></code>
* コンストラクタでスーパをコール(必須)
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* IntentServiceは、サービスを開始したインテントで、
* デフォルトのワーカースレッドからこのメソッドを呼び出します。
* このメソッドが戻ると、IntentServiceは必要に応じてサービスを停止します
*/
@Override
protected void onHandleIntent(Intent intent) {
// 普通はこのメソッドで、ファイルをダウンロードするような作業をします
// サンプルでは、5秒スリープする処理をコードしてます
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
onHandleIntent()の実装やコンストラクタなど、IntentService()で必要な処理はこれで全てです。
onCreate(),onStartCommend(),onDestory()など、他のコールバックメソッドもオーバーライドするのなら、スーパーインプリメンテーション(親の実装)を呼び出して、IntentServiceのライフサイクルを適切に管理してください。
onStartCommand()は、onHandleIntent()にインテントを配信した方法で、デフォルトの実装を返します。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
onHandleIntent()の他に、スーパークラスを呼び出す必要のないメソッドはonBind()のみです。これらの実装は、Serviceにバインドを許可する時に必要です。
Serviceクラスの拡張
マルチスレッドを実行する必要がある場合に、開始要求を作業キュー経由での処理ではなく、Serviceを拡張してそれぞれのIntentを使って処理します。
上記のIntentServiceのコードと同じ処理を、以下にServiceクラスを拡張して実装します。それぞれの開始要求に対して、ワーカースレッドでジョブとプロセスを実行し、一度に1つの要求のみを処理します。
public class HelloService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
// Handlerはスレッドからメッセージを受け取ります
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 普通は、ファイルをダウンロードするように、ここで処理を行います
// 5秒スリープするサンプルコードを下記します
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 複数の処理要求がある場合には
// スタートIDを使ってサービスを停止します
// スタートIDを使わないと停止できません
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// サービスを稼働させるスレッドを開始します
// メインスレッドのパフォーマンスを確保するため、別スレッドでサービス処理します
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// ハンドルのスレッドルーパーを取得してハンドルに渡します。
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// リクエストを開始したら、開始した処理にメッセージを送り、スタートIDも送信します。
// 処理が終了した時、停止要求する作業をIDによって確定できます。
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
// サービスが強制破棄されたら、ここに戻ってから再起動します
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
onStartCommand()への各呼び出しを、Service自身で実行するため、同時に複数の要求を実行することも可能です。自身の状況に合う場合は、要求ごとに新しいスレッドを作成し、すぐに実行できます(前の要求が完了するのを待つ必要はありません)。
onStartCommand()メソッドは、整数を返す必要があります。この整数はシステムがサービスを強制終了したときに、サービスをどのように続行させるのかを示す値です(下記)。
-
START_NOT_STICKY
- onStartCommand()から戻った後、システムがサービスを強制終了した場合は、配信が保留中のインテントがない限り、システムはサービスを再開しません。これは、サービスが不要で、アプリケーションが未完了のジョブを再開できる場合に、不要なサービスを実行してしまうのを回避できる最も安全な選択肢です。
-
START_STICKY
- onStartComand()から戻った後、システムがサービスを強制終了した場合は、サービスを再作成し、onStartCommand()を呼び出しますが、最後のインテントは再配信しません。サービスを展開するインテントが保留になっている場合を除いて、システムは代わりにonStartCommand()をnullインテントを使って呼び出します。保留中のインテントがある場合、そのインテントは配信されます。これはコマンドは実行しないが、無期限に実行し、ジョブを待機するメディアプレーヤー(や同様のサービス)に適しています。
-
START_REDELIVER_INTENT
- onStartCommand()から戻った後、システムがサービスを強制終了した場合は、サービスを再作成し、サービスに最後に配信されたインテントでonStartComannd()を呼び出します。すべてのペンディングインテントが順に配信されます。これはファイルのダウンロードのような処理を実行し、終了後に直ちに再開する必要のあるサービスに適しています。
Serviceの開始
アクティビティや他のアプリケーションコンポーネントからIntent(開始Serviceを指定)を、startService()、もしくはstartForegroundService()に渡して、Serviceを開始。
Androidシステムが、ServiceのonStartCommand()メソッドを呼び出し、Intentを渡します。Intentは開始するサービスを指定します。
Note: アプリがAPI26以降の場合、アプリがForegroundになければ、システムはバックグラウンドServiceの使用や生成に制約を課します。もしアプリをForegroundServiceで生成するのなら、startForegroundService()を使ってください。一度Serviceが生成されると、このServiceは5秒以内にstartForegroun()メソッドを呼ばなければなりません。 |
<参考>
startService()で明示的Intentを使って
Serviceを開始するサンプルコードです
Intent intent = new Intent(this,HelloService.class);
startService(intent);
startService()メソッドにより、AndroidシステムはServiceのonStartCommand()メソッドを実行します。もしServiceがまだ稼働してなければ、システムは最初にonCreate()を実行してからonStartCommand()を実行します。
Serviceでバインドが提供されてないときは、startService()で配信されたIntentがアプリケーションコンポーネントとServiceの唯一の通信手段となります。
ただし、Serviceから結果を返す場合、Serviceを要求するクライアントが、ブロードキャスト用にPendingIntentを作成でき(getBroadcast()を使う)、要求されたServiceのIntentに配信できます。その後、Serviceはブロードキャストを使って結果を配信できます。
Service要請が複数ある場合、それに対応するために、onStartCommand()に複数の呼び出しが発生しますが、停止するためには、stopSelf()やstopService()は1つのみでOK。
Serviceの停止
Serviceを開始したら、Serviceのライフサイクルを管理してください。onStartCommand()実行後は、Serviceは無期限実行し、システムメモリーをリカバーする場合を除いて、システムはServiceを停止や破棄しません。Serviceの停止は、Service自身がstopSelf()を実行するか、他のコンポーネントからstopService()を実行して行います。
一度、stopSelf()やstopServiceが実行されると、システムは速やかにServiceを破棄します。
ServiceがonStartCommand()への複数の要求を処理する場合は、1回の停止処理で他の全ての要求が停止しますので、1つの要求が完了しても、Serviceを停止しないでください。
複数の要求を処理するServiceの停止は、stopSelf(int)を使います。このメソッドは、Service停止要求が、いつも最新の開始要求に基づいて行われることを確認します。
具体的には、stopSelf(int)は、停止したい要求に応じた開始要求のIDを渡します(onStartCommand()に送られたstartId)。stopSelf(int)が実行できるようになる前に、Serviceが新しい開始要求を受け取ると、開始要求のIDと停止供給のIDが一致しないので、そのServiceは停止しません。
COUTION: システムリソースの無駄遣いや、電池の消耗を避けるため、アプリケーションが終了したら、必ずServiceを停止します。 必要であれば、他のコンポーネントからstopService()を実行すうことで、Serviceを停止します。 Serviceのバインドを有効にしていても、ServiceがonStartCommand()で実行されてるなら、stopSelf()を使って、Service自身でServiceを停止してください。 |
バインドされたServiceを作成
bindService()でServiceにバインドすると、アプリケーションコンポーネントが長時間接続できます(通常では、コンポーネントがstarService()を呼び出すことではServiceは開始できない)。
アプリケーション内のアクティビティや、他のコンポーネントとServiceとで応答したり、プロセス間通信を介してアプリケーション機能を、他のアプリケーションに提供するときに、バインドされたServiceを生成します。
バインドされたServiceを作成
-
onBind()を実装
Serviceとの通信用のインターフェイスを定義するIBinderを返す -
アプリケーションコンポーネントがbindService()を呼び出
インターフェイスIBinderを取得しServiceのメソッドの呼び出しを開始
バインドされたコンポーネントがなくなると、システムによってServiceが破棄されます(バインドされたサービスは、onStartCommand()でサービスが開始された時と同じ方法で停止する必要はありません)。
バインドされたServiceを生成するには、インターフェイスを定義する必要があります。このインターフェイスで、クライアントとServiceのと通信方法を指定します。クライアントとServiceの通信を担うインターフェイスは、IBinderを実装する必要があり、ServiseがonBind()コールバックメソッドによって返すIBinderでなければなりません。クライアントがIBilderを受け取ったら、インターフェイスを通じてServiceを操作できるようになります。
複数のクライアントが同時にサービスにバインド可能です。あるクライアントがService操作を終了すると、unbindService()を実行し、バインドを解除します。Serviceにバインドするクライアントが無くなれば、システムはServiceを破棄します。
バインドされたサービスを実装する方法はいくつかあり、その実装はServiceを開始する方法よりも複雑ですので、詳しくはこちらのドキュメントで>https://developer.android.com/guide/components/bound-services.html
ユーザーへ通知を送る
Serviceが稼働したら、トースト通知かステータスバー通知で、ユーザーに通知できます。トースト通知は画面に一瞬出てくるメッセージです。ステータスバーの通知はステータスバーにメッセージとともにアイコンを表示します。ユーザーは通知から操作するアクションを選べます(Serviceを開始するとか)。
通常、ステータスバー通知は、ファイルダウンロードを完結させるような作業を、バックグラウンドで行うのに、最善のテクニックと言えます。ユーザーが展開ビューから通知を選択したとき、(ダウンロードしたファイルを表示するように)通知からアクティビティを開始できます。
トースト通知とステータスバー通知について、もっと詳しくは>
もっと詳しくトースト通知を>https://developer.android.com/guide/topics/ui/notifiers/toasts.html
もっと詳しくステータスバー通知は>https://developer.android.com/guide/topics/ui/notifiers/notifications.html
ServiceをForegroundで稼働させる
ForegroundServiceは、ユーザーがServiceを認識できる状態であるので、メモリ不足になっても、システムによる強制終了の候補にはなりません。ForegroundServiceは、ステータスバーに通知を出さなければならず、「進行中」という見出しの下に表示されます。Serviceが停止されるかForegroundから削除されない限り、通知は消えません。
COUTION:ForegroundServiceの利用制限 ForegroundServiceは、ユーザーがアプリを直接操作してなくても、アプリが軌道してることが分かる状態であって、そのアプリを実行させる必要がある場合にのみ利用できます。 ForegroundServiceでは、ユーザーが確実にアプリの実行内容を把握できるように、通知の重要度を設定して、ステータスバーに通知を表示させます。 重要度を最も低く設定するようなアクションには、Serviceを使わず、スケジュールされた処理を使うことを検討すべきです。 Serviceを使うアプリは、システムに負荷を加え、システムリソースを消費します。重要度を低く設定し、通知を非表示にすると、ユーザーが使っているアプリのパフォーマンスを損なう可能性がありますので、重要度を最低に設定してServiceを実行する場合には、通知ドロワーの下部でアプリを呼び出します。(通知ドロワーの下部は、システムの都合などにより強制終了される可能性が高まるということかな?) |
Serviceで音楽再生する音楽プレイヤーは、ユーザーに明示的にアプリの実行を認識させるために、Foregroundで実行するように設定すべきです。ステータスバーの通知は、再生中の音楽を表示したり、音楽プレイヤーを操作して、任意のアクティビティを起動させます。同様に、ユーザーの走行を追跡するアプリは、ユーザーの位置を追跡するForegroundServiceが必要です。
Note: Android9(API28)以降でForegroundServiceを使ってるアプリは、FOREGROUND_SERVICEの許可を要求します。これは通常の許可なので、システムは要求元のアプリに自動的に許可します。 もし、API28以下のレベルで、FOREGROUND_SERVICEを要求せずに、ForegroundServiceを生成した場合は、システムは安全性の例外を投げます。 |
Foreground Sercice
ForegroundServiceでは通知を表示する必要があり、Service停止か、ForegroundからServiceを除去しない限り、通知を消すことはできません。
Foreground Serviceを作成する
startForeground(Id,notification)を実行
・ Notification
・ Intent
・ PendingIntent
・ notification.setLatestEventInfo(this,title,text,PendingIntent)
・ startForeground(Id,notification)
<参考>
new notification は現在非推奨。notificationCompatを使いましょう
setLatestEventInfoは現在非推奨。builderを使いましょう
startForegroundServiceはAPI26以上
Notification notification = new Notification(
R.drawable.icon,
getText(R.string.ticker_text),
System.currentTimeMillis()
);
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(
this,
getText(R.string.notification_title),
getText(R.string.notification_message),
pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
startForeground()に渡すIDには、0はNG
Foregourd Serviceの除去
stopForeground()
・ ServiceをForegroundから除去
・ 通知を除去するかを示すbool値も受け付けます
・ Serviceは停止しない
ただし、ServiceがまだForegroundで実行中に停止した場合は、通知は削除される
Serviceのライフサイクル管理
省略