wake-up-neo.com

onTaskRemoved wird nicht aufgerufen, wenn die vom Dienst gestartete Aktivität entfernt wird

Ich verwende oreo 8.1.0 . Ich stehe vor einem seltsamen Problem, dessen Lösung ich bei stackoverflow nicht finden kann, daher schreibe ich diese Frage. Ich kenne eine Lösung, die ich durch den Vordergrunddienst implementieren kann, aber ich finde die Benachrichtigung in meinem Anwendungskontext nicht als benutzerfreundlich.

Ich werde mein Problem anhand zweier Fälle beschreiben.

Fall 1: Wenn der Benutzer meine App durch Klicken auf das Symbol öffnet und aus den letzten Apps entfernt, wird der Dienst automatisch neu gestartet. Das ist okay.

Fall 2: Hier ist meine App geschlossen und befindet sich nicht in den letzten Apps. Wenn ein Benutzer einen Text kopiert, startet mein Dienst eine der Aktivitäten meiner App, aber wenn er ihn aus den letzten Apps entfernt, dann mein Dienst wird dauerhaft gestoppt.

Mein Problem liegt also im zweiten Fall, ich möchte nicht, dass mein Dienst getötet wird. Selbst wenn es getötet wird, möchte ich, dass es neu startet.

Ich habe alle im stackoverflow genannten Methoden ausprobiert, wie START_STICKY und onTaskRemoved, aber ich kann es nicht zum Laufen bringen.

Ich habe sogar versucht, meine Aktivität abzubrechen, wenn der Benutzer auf die Schaltfläche der letzten App klickt und diese programmgesteuert aus den letzten Apps entfernt. Dies hat jedoch nicht funktioniert. Obwohl dies den Dienst auch im zweiten Fall neu startet, wenn der Benutzer meine App über die Zurück-Schaltfläche beendet .

Dieser Teil des Codes stammt aus der Aktivität, die geöffnet wird, wenn der Benutzer Text kopiert. 

@Override
public void finish() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        super.finishAndRemoveTask();
    } else {
        super.finish();
    }

}

Dieser Teil des Codes stammt von dem Dienst, der die Aktivität startet.

@Override
public void onTaskRemoved(Intent rootIntent){
    Log.d("testing 12","onTaskRemoved");
    Intent restartServiceTask = new Intent(getApplicationContext(),CBWatcherService.class);
    restartServiceTask.setPackage(getPackageName());
    PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(this.ALARM_SERVICE);
    myAlarmService.set(
            AlarmManager.ELAPSED_REALTIME,
            SystemClock.elapsedRealtime() + 1000,
            restartPendingIntent);

    super.onTaskRemoved(rootIntent);
}

@Override
public int onStartCommand(Intent intent,int flag,int startId){
    super.onStartCommand(intent, flag, startId);
    return START_STICKY;

}

BEARBEITEN 1
Ich brauche nur den Dienst, um am Leben zu bleiben. Dies sind die Dinge, die die Benutzererfahrung in meinem App-Fall nicht behindern werden
1. Wenn Sie die Aktivität programmgesteuert abbrechen, wenn onPause aufgerufen wird, damit der Dienst nicht beendet wird, ist dies akzeptabel, wenn Sie dies zulassen
2. Das Anzeigen der Benachrichtigung für einige Sekunden ist akzeptabel
3. Der Neustart des Dienstes ist akzeptabel

9
royatirek

Dies war das Problem Wann immer mein Dienst die Aktivität startete, wurde mein Dienst nach der Aktivität, die zum Starten verwendet wurde, zerstört. 

Warum funktionierte onTaskRemoved nicht?
.__Das Ding, das ich tat, funktionierte nicht, weil mein Dienst zerstört wurde und es daher nicht aktiv war, onTaskRemoved zu hören.

Wie habe ich es gelöst?
Die Lösung für dieses Problem bestand darin, die Aktivität (durch den Dienst gestartet) zu prüfen, um zu prüfen, ob der Dienst aktiv ist oder nicht. Wie in meinem Fall wurde der Service zerstört. Daher muss ich den Dienst erneut starten, wenn der Dienst nicht aktiv ist. 
Es passt sogar zum OREO-Entwurfsmuster, da wir den Hintergrunddienst starten können, wenn sich die App im Vordergrund befindet und der Dienst auch dann erhalten bleibt, wenn die Aktivität zerstört wird.

Auf Oreo wird der Service zwar irgendwann einmal zerstört, dies ist jedoch ein anderes Problem.

Mehr Info

0
royatirek

Von Android Oreo aus gibt es einen Paradigmenwechsel, um die Ausführung von Hintergrunddiensten zu beschränken. Es war eine häufige Kritik, die sich auf Batterielaufzeit, Leistung und Sicherheit auswirkte. Wie in den Kommentaren oben angegeben, gibt es alternative Ansätze wie JobScheduler.

Das Refactoring von Services auf das JobScheduler-Muster kann sehr kompliziert sein. Ich empfehle Ihnen, Ihren IntentService in einen JobintentService aus der Android-Support-v4-Bibliothek zu ändern. Es verwendet JobScheduler für Oreo und spätere Ziele, kehrt jedoch bei älteren Geräten zum älteren IntentService-Design zurück. Sie müssen lediglich Ihre Überschreibung von onHandleIntent durch onHandleWork in Ihrer Service-Implementierung ersetzen. 

Hinzufügen 

Android:permission="Android.permission.BIND_JOB_SERVICE"

zur Diensterklärung in Ihrer AndroidManifest.xml. Es kann auch nützlich sein, hinzuzufügen

 <uses-permission Android:name=”Android.permission.WAKE_LOCK” />

Wenn Sie das alles durchlesen und Ihre Frage durchlesen, scheint mir Ihre grundlegende Beschwerde die kosmetische Frage der Vordergrunddienste zu sein, die eine Benachrichtigung erfordern. Aus meiner Sicht besteht Ihre Lösung darin, entweder Context.startForegroundService zu verwenden oder sicherzustellen, dass Ihr Dienst gebunden ist. In beiden Fällen gibt es für den Benutzer sichtbaren Inhalt, dass der Dienst ausgeführt wird. Es wird schwierig sein, Android-Designentscheidungen zu untergraben. Um es besser anzunehmen - Sie möchten, dass Sie diese Benachrichtigungen von jetzt an zeigen. 

Das Aktualisieren des Codes für neuere Android-Ziele ist jedoch immer noch empfehlenswert, auch wenn Sie diese Benachrichtigungssymbole nicht vollständig vermeiden können. 

0
dr_g