Beim Start der Anwendung startet die App den Dienst, der eine Netzwerkaufgabe ausführen soll. Nach dem Targeting der API-Ebene 26 kann meine Anwendung den Dienst unter Android 8.0 im Hintergrund nicht starten.
Auslöser: java.lang.IllegalStateException: Dienst darf nicht gestartet werden Absicht {cmp = my.app.tt / com.my.service}: App befindet sich im Hintergrund uid UidRecord {90372b1 u0a136 CEM-Leerlaufprozesse: 1 seq (0,0 , 0)}
so wie ich es verstehe im Zusammenhang mit: Hintergrundausführungsbeschränkungen
Die Methode startService () löst jetzt eine IllegalStateException aus, wenn eine App für Android 8.0 versucht, diese Methode in einer Situation zu verwenden, in der es nicht zulässig ist, Hintergrunddienste zu erstellen.
" in einer Situation, in der es nicht erlaubt ist " - was bedeutet es eigentlich? Und wie man es repariert. Ich möchte meinen Dienst nicht als "Vordergrund" festlegen.
startForegroundService()
anstelle vonstartService()
.Antworten:
Die zulässigen Situationen sind eine temporäre Whitelist, in der sich der Hintergrunddienst wie vor Android O verhält.
Quelle: https://developer.android.com/about/versions/oreo/background.html
Mit anderen Worten, wenn Ihr Hintergrunddienst die Whitelist-Anforderungen nicht erfüllt, müssen Sie den neuen JobScheduler verwenden . Es ist im Grunde dasselbe wie ein Hintergrunddienst, wird jedoch regelmäßig aufgerufen, anstatt kontinuierlich im Hintergrund ausgeführt zu werden.
Wenn Sie einen IntentService verwenden, können Sie zu einem JobIntentService wechseln. Siehe die Antwort von @ kosev unten .
quelle
FirebaseInstanceIdService
und seineonTokenRefresh
Methode eine FCM-Nachricht mit hoher Priorität?Ich habe eine Lösung. Für Geräte vor 8.0 müssen Sie nur verwenden
startService()
, für Geräte nach 7.0 müssen Sie nur verwendenstartForgroundService()
. Hier ist ein Beispiel für den Code zum Starten des Dienstes.Fügen Sie in der Serviceklasse den folgenden Code zur Benachrichtigung hinzu:
Wobei O Android Version 26 ist.
quelle
ContextCompat.startForegroundService(...)
Support-Bibliothek, die stattdessen verwendet werden kann.Am besten verwenden Sie JobIntentService, der den neuen JobScheduler für Oreo oder die alten Dienste verwendet, falls diese nicht verfügbar sind.
Erklären Sie in Ihrem Manifest:
Und in Ihrem Dienst müssen Sie onHandleIntent durch onHandleWork ersetzen:
Dann starten Sie Ihren Dienst mit:
quelle
enqueueWork(...)
ist ebenfalls eine statische Methode.Wenn der Dienst durch die Erweiterung in einem Hintergrund - Thread ausgeführt wird
IntentService
, können Sie ersetzenIntentService
mitJobIntentService
der als Teil der Android Support Library zur Verfügung gestelltDer Vorteil der Verwendung
JobIntentService
besteht darin, dass sie sichIntentService
auf Pre-O-Geräten verhält und auf O und höher als Job versendetJobScheduler
kann auch für periodische / On-Demand-Jobs verwendet werden. Stellen Sie jedoch sicher, dass die Abwärtskompatibilität gewährleistet ist, da dieJobScheduler
API nur über API 21 verfügbar istquelle
In Oreo hat Android Grenzen für Hintergrunddienste definiert .
Wenn Sie jedoch immer einen Dienst ausführen müssen, können Sie den Vordergrunddienst verwenden.
So können Sie einen Vordergrunddienst erstellen . Sie müssen dem Benutzer eine Benachrichtigung anzeigen, wenn Ihr Dienst ausgeführt wird. Siehe diese Antwort (Es gibt viele andere)
Eine Lösung, wenn -
Sie möchten keine Benachrichtigung für Ihren Dienst?
Sie können regelmäßige Aufgaben mit Alarm Manager , Job Scheduler , Evernote-Jobs oder Work Manager verwenden .
Ich habe den für immer laufenden Dienst mit Work-Manager getestet.
quelle
Ja, das liegt daran, dass Sie auf API 26 keine Dienste mehr im Hintergrund starten können. Sie können ForegroundService also über API 26 starten.
Du musst verwenden
und senden Sie eine Benachrichtigung, während Sie das Leck verarbeiten.
quelle
Wie @kosev in seiner Antwort sagte , können Sie JobIntentService verwenden. Ich verwende jedoch eine alternative Lösung: Ich fange IllegalStateException ab und starte den Dienst als Vordergrund. Zum Beispiel startet diese Funktion meinen Dienst:
und wenn ich Intent verarbeite, mache ich so etwas:
quelle
context.startService
im Hintergrund arbeitet - manchmal nicht - das sieht aus wie der einzigen beste Weg , sonst müssen Sie mehr Code in Ihrer Hauptklasse implementierenextending Application
undimplementing ActivityLifecycleCallbacks
und zu verfolgen , ob die App im Vordergrund oder im Hintergrund sind und starten Sie Ihre Absicht entsprechend.In den Versionshinweisen zu Firebase heißt es, dass die Unterstützung für Android O erstmals in 10.2.1 veröffentlicht wurde (obwohl ich die Verwendung der neuesten Version empfehlen würde).
Bitte fügen Sie neue Firebase-Messaging-Abhängigkeiten für Android O hinzu
Aktualisieren Sie bei Bedarf die Google Play-Dienste und die Google-Repositorys.
quelle
Wenn eine Absicht zuvor gut funktioniert hat, wenn sich die App im Hintergrund befindet, ist dies ab Android 8 und höher nicht mehr der Fall. Bezieht sich nur auf die Absicht, die etwas verarbeitet werden muss, wenn sich die App im Hintergrund befindet.
Die folgenden Schritte müssen befolgt werden:
JobIntentService
anstelle von verwendet werdenIntentService
.Die Klasse, die erweitert wird,
JobIntentService
sollte dieonHandleWork(@NonNull Intent intent)
Methode - implementieren und unter der Methode stehen, die dieonHandleWork
Methode aufruft :Rufen Sie
enqueueWork(Context, intent)
aus der Klasse an, in der Ihre Absicht definiert ist.Beispielcode:
com.android.support:support-compat
wird benötigt fürJobIntentService
- ich benutze26.1.0 V
.Am wichtigsten ist es, sicherzustellen, dass die Version der Firebase-Bibliotheken mindestens aktiviert ist
10.2.1
. Ich hatte Probleme damit10.2.0
- wenn Sie welche haben!Ihr Manifest sollte die folgende Berechtigung für die Serviceklasse haben:
Hoffe das hilft.
quelle
Ich sehe viele Antworten, die empfehlen, nur einen ForegroundService zu verwenden. Um einen ForegroundService nutzen zu können, muss ihm eine Benachrichtigung zugeordnet sein. Benutzer sehen diese Benachrichtigung. Je nach Situation können sie sich über Ihre App ärgern und diese deinstallieren.
Die einfachste Lösung ist die Verwendung der neuen Architekturkomponente WorkManager. Sie können die Dokumentation hier einsehen : https://developer.android.com/topic/libraries/architecture/workmanager/
Sie definieren einfach Ihre Worker-Klasse, die Worker erweitert.
Dann planen Sie, wann Sie es ausführen möchten.
Einfach! Es gibt viele Möglichkeiten, Worker zu konfigurieren. Es unterstützt wiederkehrende Jobs und Sie können sogar komplexe Aufgaben wie Verketten ausführen, wenn Sie diese benötigen. Hoffe das hilft.
quelle
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately
... es ist vielleicht am einfachsten, aber meine App benötigt einen Hintergrunddienst, der die Anforderungen der Benutzer sofort ausführt!Alternative Lösung mithilfe von JobScheduler kann der Dienst in regelmäßigen Abständen im Hintergrund gestartet werden.
Machen Sie zuerst eine Klasse mit dem Namen Util.java
Erstellen Sie dann die JobService-Klasse mit dem Namen TestJobService.java
Danach BroadCast Receiver-Klasse mit dem Namen ServiceReceiver.java
Aktualisieren Sie die Manifest-Datei mit dem Service- und Empfängerklassencode
Linke main_intent Launcher in der standardmäßig erstellten Datei mainActivity.java und Änderungen in der Datei MainActivity.java
WOOAAH !! Der Hintergrunddienst startet ohne Vordergrunddienst
quelle
Wenn Sie Ihren Code unter 8.0 ausführen, stürzt die Anwendung ab. Starten Sie also den Dienst im Vordergrund. Wenn unter 8.0, verwenden Sie dies:
Wenn über oder 8.0, dann verwenden Sie dies:
quelle
java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE
. Fix bei stackoverflow.com/a/52382711/550471Wenn Sie eine Push-Benachrichtigung für Firebase-Messaging integriert haben,
Fügen Sie aufgrund der Einschränkungen für die Hintergrundausführung neue / aktualisierte Firebase-Messaging-Abhängigkeiten für Android O (Android 8.0) hinzu .
Aktualisieren Sie bei Bedarf die Google Play-Dienste und die Google-Repositorys.
Aktualisieren:
quelle
Verwenden Sie
startForegroundService()
anstelle vonstartService()
und vergessen Sie nicht,startForeground(1,new Notification());
innerhalb von 5 Sekunden nach dem Start des Dienstes in Ihrem Dienst zu erstellen .quelle
Aufgrund kontroverser Abstimmungen zu dieser Antwort (+ 4 / -4 zum Zeitpunkt dieser Bearbeitung) BITTE BITTE DIE ANDEREN ANTWORTEN ZUERST ANSEHEN UND DIESE NUR ALS LETZTE RESORT VERWENDEN . Ich habe dies nur einmal für eine Netzwerk-App verwendet, die als Root ausgeführt wird, und ich stimme der allgemeinen Meinung zu, dass diese Lösung unter normalen Umständen nicht verwendet werden sollte.
Ursprüngliche Antwort unten:
Die anderen Antworten sind alle richtig, aber ich möchte darauf hinweisen, dass eine andere Möglichkeit, dies zu umgehen, darin besteht, den Benutzer zu bitten, die Batterieoptimierungen für Ihre App zu deaktivieren (dies ist normalerweise keine gute Idee, es sei denn, Ihre App ist systembezogen). In dieser Antwort erfahren Sie, wie Sie die Deaktivierung von Batterieoptimierungen anfordern können, ohne dass Ihre App in Google Play gesperrt wird.
Sie sollten auch überprüfen, ob die Batterieoptimierungen in Ihrem Receiver deaktiviert sind, um Abstürze zu vermeiden über:
quelle
JobScheduler
und so batteriefreundlich gestaltet werden . Einige der Apps müssen auf einer niedrigeren Ebene als typische Synchronisierungsanwendungen arbeiten. Dies ist eine alternative Lösung, wenn dies nicht funktioniert.nicht in onStartCommand verwenden:
Ändern Sie es einfach in:
und es wird funktionieren
quelle