wake-up-neo.com

Android Background Service wird neu gestartet, wenn die Anwendung beendet wird

Ich entwickle eine Anwendung, in der ein Hintergrunddienst zum Sammeln von Sensordaten erstellt wird. Ich starte den Service von meiner Aktivität aus:

startService(new Intent(this, MyService.class));

Ich habe den Dienst erstellt, damit der Hintergrunddienst weiterhin Daten sammelt, wenn die Anwendung zerstört wird. Ich habe es versucht und es hat bis zu einem gewissen Grad funktioniert. Mein Problem ist, dass der Dienst nach dem Beenden der Anwendung offenbar neu gestartet wird, da die Methoden onCreate() und onStart() aufgerufen werden. Gibt es eine Möglichkeit, mit der der Dienst bitte nicht neu gestartet wird?

PDATE:

Wie in einer Antwort unten vorgeschlagen, habe ich die folgende Methode in den Dienst aufgenommen, aber kein Glück.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}
37
duncanportelli

Dies hängt vom in onStartCommand zurückgegebenen Wert ab.

Sie müssen START_NOT_STICKY zurückgeben

Nach der Dokumentation :

Für gestartete Dienste gibt es zwei zusätzliche Hauptbetriebsmodi, für deren Ausführung sie sich entscheiden können, abhängig von dem Wert, den sie von onStartCommand () zurückgeben: START_STICKY wird für Dienste verwendet, die nach Bedarf explizit gestartet und gestoppt werden, während START_NOT_STICKY oder START_REDELIVER_INTENT verwendet werden für Dienste, die nur während der Verarbeitung der an sie gesendeten Befehle ausgeführt werden sollen

Kurz gesagt: Wenn Sie START_STICKY zurückgeben, wird der Service neu erstellt, sobald die Ressourcen verfügbar sind. Wenn Sie START_NOT_STICKY zurückgeben, müssen Sie den Dienst, der eine neue Absicht sendet, erneut aktivieren.

Da all dies meine Neugier geweckt hat, habe ich eine Beispiel-App erstellt, um dies zu testen. Sie finden die Zip mit allen Quellen hier Es gibt eine startService-Schaltfläche und eine stopService-Schaltfläche, die das tun, was Sie von ihnen erwarten würden. Der Dienst gibt START_NOT_STICKY in onStartCommand zurück. Ich habe Toasts in onCreate, onStartCommand und onDestroy platziert.

Hier was passiert:

  • Wenn ich auf Start drücke, werden onCreate und onStart aufgerufen
  • Wenn ich stop drücke, wird onDestroy ausgelöst
  • Wenn ich zweimal auf Start drücke, wird onCreate einmal und onStartCommand zweimal aufgerufen

Es verhält sich also so, wie man es erwarten würde.

Wenn ich den Dienst starte und die App wie beschrieben beende, wird onDestroy nicht aufgerufen, aber weder onCreate noch onStart.

Wenn ich zur App zurückkehre und erneut auf Start drücke, wird onCreate aufgerufen , was bedeutet, dass START_NOT_STICKY, wie ich zuvor geschrieben habe, den Neustart des Dienstes verhindert automatisch.

Ich vermute, Sie haben noch etwas in Ihrer App, das den Service erneut startet (möglicherweise eine ausstehende Absicht).

20
fedepaol

Die App und der Dienst laufen im selben Prozess ab, dh wenn die App beendet wird, ist auch Ihr Dienst beendet. Das Ändern des Rückgabewerts von onStartCommand wirkt sich nicht auf diesen Prozess aus. Es weist den Dienst einfach an, entweder zu starten/zu stoppen, wenn Sie es mitteilen, oder wenn es fertig ist, was es tun muss. Wie in Ihrem Kommentar zu Ihrem ursprünglichen Beitrag erwähnt, hat es funktioniert, ihn als Vordergrundprozess festzulegen, aber das zwingt den Dienst wirklich nur dazu, eine hohe Priorität zu haben, und löst das Problem nicht.

Geben Sie im Manifest für diesen Service einen Prozessnamen an, um den Service so zu ändern, dass er separat beendet wird und vorausgesetzt, dass es sich um einen gestarteten und nicht um einen gebundenen Service handelt.

Aus dem Process and Threads Developer Guide :

Der Manifest-Eintrag für jeden Typ von Komponentenelement - <activity>, <service>, <receiver>, and <provider>— unterstützt ein Android: process-Attribut, mit dem ein Prozess angegeben werden kann, in dem diese Komponente ausgeführt werden soll. Sie können dieses Attribut so festlegen, dass jede Komponente in einem eigenen Prozess ausgeführt wird oder dass einige Komponenten einen Prozess gemeinsam nutzen, während andere dies nicht tun. Sie können den Android: -Prozess auch so einstellen, dass Komponenten verschiedener Anwendungen im selben Prozess ausgeführt werden - vorausgesetzt, die Anwendungen haben dieselbe Linux-Benutzer-ID und sind mit denselben Zertifikaten signiert.

Android entscheidet sich möglicherweise, einen Prozess zu einem Zeitpunkt herunterzufahren, zu dem der Arbeitsspeicher knapp wird und andere Prozesse, die den Benutzer direkter bedienen, dies erfordern. Anwendungskomponenten, die in dem Prozess ausgeführt werden, der beendet wird, werden folglich zerstört. Für diese Komponenten wird ein Prozess erneut gestartet, wenn sie wieder arbeiten müssen.

Von <service> in Manifest-Datei :

Android: verarbeiten

Der Name des Prozesses, in dem der Dienst ausgeführt werden soll. Normalerweise werden alle Komponenten einer Anwendung im Standardprozess ausgeführt, der für die Anwendung erstellt wurde. Es hat den gleichen Namen wie das Anwendungspaket. Das Prozessattribut des Elements kann für alle Komponenten einen anderen Standard festlegen. Die Komponente kann den Standardwert jedoch mit einem eigenen Prozessattribut überschreiben, sodass Sie Ihre Anwendung auf mehrere Prozesse verteilen können.

Wenn der diesem Attribut zugewiesene Name mit einem Doppelpunkt (':') beginnt, wird bei Bedarf ein neuer Prozess erstellt, der für die Anwendung privat ist, und der Dienst wird in diesem Prozess ausgeführt. Wenn der Prozessname mit einem Kleinbuchstaben beginnt, wird der Dienst in einem globalen Prozess mit diesem Namen ausgeführt, sofern er dazu berechtigt ist. Auf diese Weise können Komponenten in verschiedenen Anwendungen einen Prozess gemeinsam nutzen, wodurch die Ressourcennutzung verringert wird.

Ich bin nicht sicher, warum die andere Antwort, die dies erwähnte, abgelehnt wurde. Ich habe diese Methode in der Vergangenheit verwendet und heute eine einfache Aktivitäts-App mit einem Service für einen anderen Prozess erstellt, um sicherzustellen, dass ich nicht verrückt bin. Ich habe Android Device Monitor verwendet, um den Prozess der App abzubrechen. Sie können beide, separate Prozesse in ADM anzeigen und feststellen, dass der Service dies nicht tut, wenn der Prozess der App abgebrochen wird.

4
Plumbus

Start not sticky funktioniert nicht über KitKat und der andere onTaskRemoved funktioniert nicht über Marshmellow. onTaskRemoved kann von einigen Ausnahmen verwendet werden. Hat nicht daran gearbeitet. Aber probier das aus.

1
Minkoo

Wenn Sie einen IntentService verwenden, hat dieser einen

onHandleIntent() 

methode, in der Sie den auszuführenden Code platzieren sollen. Es wird in einem separaten Thread ausgeführt (kein UI-Thread, in dem Ihre Anwendung ausgeführt wird), daher sollte Ihre App keine Auswirkungen darauf haben. Wenn der Code ausgeführt wurde, wird der Thread beendet und der Dienst automatisch beendet.

0
Marcin S.

Ich weiß, dass es viel zu spät ist, diese Frage zu beantworten, aber vielleicht kann es für andere hilfreich sein. Das hat mir bei meiner Music Player App sehr geholfen.

Wenn es Dienste gibt, die störend sein oder die Benutzererfahrung beeinträchtigen können, z. B. Musik usw., müssen Sie in diesem Fall die Benachrichtigung verwenden. Wenn der Dienst erfolgreich gestartet wurde, erstellen Sie die Benachrichtigung und verwenden Sie die Funktion

startForeground(int Notification_id,Notification);

Dadurch wird Ihr Dienst im Hintergrund ausgeführt, ohne dass die Methoden erneut gestartet und aufgerufen werden müssen

https://developer.Android.com/reference/Android/app/Service.html

0
abissa