2017-09-01 3 views
0

Ich habe gerade angefangen zu lernen, einen Dienst gestern schreiben, und hier habe ich einen Service, den ich erwarten, die ganze Zeit laufen, auch wenn meine App endet. Dieser Dienst hat einen Listener in meiner Firebase-Datenbank und generiert Benachrichtigungen, wenn sich die Daten geändert haben.Android: Dienst abgestürzt nach dem Schließen der App

Was mich verwirrt war, dass mein Dienst erfolgreich ausgeführt werden konnte, nur wenn die App ausgeführt wurde. Unmittelbar nachdem ich die App geschlossen hatte, benachrichtigte mich mein Handy: "Leider ist diese App gestoppt (abgestürzt)". Die Warnung kam zweimal und dann wurde der Dienst nie neu gestartet (ich denke).

Ich konnte nicht herausfinden, warum mein Dienst nach dem Schließen der App abgestürzt ist. Ich habe den Dienst in der OnCreate-Methode in MainActivity gestartet. Und hier ist die ganze Serviceklasse:

Wenn Sie eine Idee haben, bitte helfen. Vielen Dank im Voraus ~~

Antwort

1

Ihr Service verwendet statische Elemente von MainActivity: databaseReference, uid und sharedPreferences. Wie Sie in Ihrem Post erklären, wird der Dienst von MainActivity.onCreate() gestartet. In diesem Fall wurden databaseReference, uid und sharedPreferences (vermutlich) initialisiert und haben gültige Werte.

Die onStartCommand() Methode im Service gibt START_STICKY zurück. Wenn Ihre App zum Beispiel beendet wird, wenn Sie sie in den Hintergrund stellen und sie dann von der Liste der letzten Aufgaben streichen, wird der Prozess für die App zerstört und dann, weil Ihr Dienst START_STICKY ist, erstellt das System eine neue Instanz des App (neuer Prozess). Diese neue Instanz enthält die Servicekomponente, aber keine gültige Instanz von MainActivity. Die statischen Elemente von MainActivity haben Standardwerte. Insbesondere wird uid null sein, was beim Aufruf databaseReference.child("users").child(uid) eine Ausnahme auslöst. Sie können bestätigen, dass dies geschieht, indem Sie die Debugprotokollierung hinzufügen, um die Werte uid und sharedPreferences auszugeben.

Aber bevor Sie eine Menge Mühe aufwenden, versuchen Sie, dass das aktuelle Design ein Akku-Killer ist. Wenn ein Dienst die ganze Zeit mit einem aktiven Listener in der Datenbank ausgeführt wird, muss Firebase eine Netzwerkverbindung zur Datenbank aufrechterhalten. Ich weiß nicht, was Ihre Anforderungen an die Datenbanküberwachung sind, aber in der Regel ist es besser, serverseitige Verarbeitung der Monitore zu ändern (z. B. eine Cloud-Funktion) und FCM-Nachrichten an die Benutzer zu senden, die benachrichtigt werden müssen.

+0

Vielen Dank für die detaillierte Erklärung ~ Ich werde bald nach FCM Nachrichten suchen. Aber abgesehen davon frage ich mich, ob es irgendeinen Weg gibt, den Wert der Benutzer-ID zu behalten und ihn an die neue Service-Instanz weiterzugeben. – Einsambr

+1

@Einsambr: Übergeben Sie anstelle von statischen Membern auf MainActivity die Daten, die Sie benötigen, im 'Intent', der für' startService() 'verwendet wird und als Parameter von' onStartCommand() 'verfügbar ist. 'Service' erweitert' Context', so dass Sie 'getSharedPreferences()' erhalten und nicht in der Absicht übergeben müssen. Anstelle von START_STICKY. Ich denke, Sie möchten [START_REDELIVER_INTENT] (https://developer.android.com/reference/android/app/Service.html#START_REDELIVER_INTENT) zurückgeben, damit der Intent, der die Startdaten enthält, beim Neustart des Dienstes erneut gestartet wird. –

Verwandte Themen