フォアグラウンドサービスとして実行されているサービスを停止しようとしています。
現在の問題は、stopService()
を呼び出したときに通知がまだ残っていることです。
したがって、私のソリューションでは、onCreate()
内に登録するレシーバーを追加しました。
onReceive()
メソッド内でstopforeground(true)
を呼び出し、通知を非表示にします。そして、stopself()
でサービスを停止します。
onDestroy()
内で、レシーバーの登録を解除しました。
これを処理するより適切な方法はありますか? stopService()が機能しないためです。
@Override
public void onDestroy(){
unregisterReceiver(receiver);
super.onDestroy();
}
アクティビティからstartService(intent)
を呼び出して、キーを表すデータをサービスの停止に渡します。
サービスからstopForeground(true)
を呼び出し、その直後にstopSelf()
を呼び出します。
アクティビティからフォアグラウンドサービスを開始および停止するには:
//start
Intent startIntent = new Intent(MainActivity.this, ForegroundService.class);
startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(startIntent);
//stop
Intent stopIntent = new Intent(MainActivity.this, ForegroundService.class);
stopIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
startService(stopIntent);
フォアグラウンドサービスで-(少なくとも)このコードを使用します。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
Log.i(LOG_TAG, "Received Start Foreground Intent ");
// your start service code
}
else if (intent.getAction().equals( Constants.ACTION.STOPFOREGROUND_ACTION)) {
Log.i(LOG_TAG, "Received Stop Foreground Intent");
//your end servce code
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
他の回答に加えて、私はAndroid oreo以降を使用してジョブサービスを停止するこのスニペットで終了しました。
Intent intent = new Intent(getApplicationContext(), LocationService.class);
intent.setAction(status);
ContextCompat.startForegroundService(getApplicationContext(), intent);
そしてサービス中
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
startForeground(121, notification);
if (intent.getAction().equals("StopService")) {
stopForeground(true);
stopSelf();
}
アプリが呼び出さずにクラッシュしない限り、startForeground()は必須です
新しいContext.startForegroundService()メソッドは、フォアグラウンドサービスを開始します。システムは、アプリがバックグラウンドにあるときでも、アプリがContext.startForegroundService()を呼び出すことを許可します。ただし、アプリは、サービスの作成後5秒以内にそのサービスのstartForeground()メソッドを呼び出す必要があります。
https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html
ここに記載されているとおり: https://developer.Android.com/guide/components/services#Stopping
開始されたサービスは、独自のライフサイクルを管理する必要があります。つまり、システムはシステムメモリを回復する必要があり、onStartCommand()が戻った後もサービスの実行を継続しない限り、サービスを停止または破棄しません。サービスは、stopSelf()を呼び出すことによって自身を停止する必要があります。または、別のコンポーネントがstopService()。
stopSelf()またはstopService()で停止するように要求されると、システムはできるだけ早くサービスを破棄します。
したがって、startService()の呼び出しに使用したアクティビティからstopService()を呼び出すことができます。私はここでそれをやった:
start_button.setOnClickListener {
applicationContext.startForegroundService(Intent(this, ServiceTest::class.Java))
}
stop_button.setOnClickListener {
applicationContext.stopService(Intent(this, ServiceTest::class.Java))
}
サービスを開始および停止する2つのボタンを作成しましたが、機能します。
サービスを停止してから通知を更新する場合は、最初にstopSelf()を呼び出してからnotify()を呼び出すことができます。 stopForeground(false)は、通知をキャンセル可能にします。
private final BroadcastReceiver myBgWorkCompleteReceiver= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
stopSelf();
notificationLayoutExpanded.setTextViewText(R.id.file_download_notify_download_percentage, "Background work completed");
manager.notify(mNotificationId, notification);
stopForeground(false);
}
};
public void onDestroy() {
super.onDestroy();
// cancel any running threads here
LocalBroadcastManager.getInstance(this).unregisterReceiver(myBgWorkCompleteReceiver);
}
サービスを停止する最良の方法は、サービス自体を停止することです。これにより、実際に停止し、データの整合性が維持されることが確実になります。あなたが外部(アクティビティ)からそれをしたい場合、私は通常グローバルな静的属性を使用します。
ここで私の答えを確認してください: https://stackoverflow.com/a/57833370/7795547