Ich verwende Service
Class unter Android O OS.
Ich habe vor, das Service
im Hintergrund zu verwenden.
Die Android-Dokumentation besagt dies
Wenn Ihre App auf API-Level 26 oder höher abzielt, legt das System Einschränkungen für die Verwendung oder Erstellung von Hintergrunddiensten fest, es sei denn, die App selbst steht im Vordergrund. Wenn eine App einen Vordergrunddienst erstellen muss, sollte die App aufrufen
startForegroundService()
.
Wenn Sie verwenden startForegroundService()
, wird Service
der folgende Fehler ausgegeben.
Context.startForegroundService() did not then call
Service.startForeground()
Was ist daran falsch?
android
service
operating-system
foreground
android-8.0-oreo
Netter Typ
quelle
quelle
Antworten:
In den Google-Dokumenten zu Android 8.0 werden Verhaltensänderungen vorgenommen :
Lösung: Rufen Sie
startForeground()
inonCreate()
für die ,Service
die Sie verwendenContext.startForegroundService()
Siehe auch: Hintergrundausführungsbeschränkungen für Android 8.0 (Oreo)
quelle
onStartCommand
Methode getan , aber ich erhalte immer noch diesen Fehler. Ich riefstartForegroundService(intent)
in meinemMainActivity
. Möglicherweise wird der Dienst zu langsam gestartet. Ich denke, das Fünf-Sekunden-Limit sollte nicht existieren, bevor sie versprechen können, dass der Dienst sofort gestartet wird.onStartCommand()
anstelle von aufrufenonCreate
, denn wenn Sie den Dienst schließen und erneut starten, kann es gehen,onStartCommand()
ohne anzurufenonCreate
...Ich habe dann angerufen
ContextCompat.startForegroundService(this, intent)
, um den Dienst zu startenIm Dienst
onCreate
quelle
onCreate
in 5 Sekunden aufruft. Deshalb sollten sie es neu gestalten, bevor sie uns zwingen, die Regeln zu befolgen.StopService
nach dem Aufruf hinzufügenstartForegroundService
.Dieses Problem tritt auf, weil das Android-Framework nicht garantieren kann, dass Ihr Dienst innerhalb von 5 Sekunden gestartet wird. Andererseits muss die Vordergrundbenachrichtigung innerhalb von 5 Sekunden ausgelöst werden, ohne zu überprüfen, ob das Framework versucht hat, den Dienst zu starten .
Dies ist definitiv ein Framework-Problem, aber nicht alle Entwickler, die mit diesem Problem konfrontiert sind, geben ihr Bestes:
startForeground
Eine Benachrichtigung muss in beiden enthalten seinonCreate
und wird nicht aufgerufenonStartCommand
, wenn Ihr Dienst bereits erstellt wurde und Ihre Aktivität irgendwie versucht, ihn erneut zu startenonCreate
.Die Benachrichtigungs-ID darf nicht 0 sein, da sonst derselbe Absturz auftritt, auch wenn dies nicht der gleiche Grund ist.
stopSelf
darf vorher nicht aufgerufen werdenstartForeground
.Mit allen oben genannten 3 kann dieses Problem ein wenig reduziert werden, aber immer noch kein Fix. Der eigentliche Fix oder die Problemumgehung besteht darin, die SDK-Zielversion auf 25 herunterzustufen.
Beachten Sie auch, dass Android P dieses Problem höchstwahrscheinlich weiterhin aufweist, da Google nicht einmal versteht, was vor sich geht, und nicht glaubt, dass dies ihre Schuld ist. Weitere Informationen finden Sie in den Abschnitten 36 und 56
quelle
startForeground
. Das Ändern auf 1 behebt das Problem für mich (hoffentlich)Ich weiß, es wurden bereits zu viele Antworten veröffentlicht, aber die Wahrheit ist - startForegroundService kann nicht auf App-Ebene repariert werden und Sie sollten es nicht mehr verwenden. Die Empfehlung von Google, die API Service # startForeground () innerhalb von 5 Sekunden nach dem Aufruf von Context # startForegroundService () zu verwenden, kann eine App nicht immer ausführen.
Android führt viele Prozesse gleichzeitig aus und es gibt keine Garantie dafür, dass Looper Ihren Zieldienst aufruft, der startForeground () innerhalb von 5 Sekunden aufrufen soll. Wenn Ihr Zieldienst den Anruf nicht innerhalb von 5 Sekunden erhalten hat, haben Sie kein Glück und Ihre Benutzer werden eine ANR-Situation erleben. In Ihrer Stapelverfolgung sehen Sie ungefähr Folgendes:
Soweit ich weiß, hat Looper die Warteschlange hier analysiert, einen "Missbraucher" gefunden und sie einfach getötet. Das System ist jetzt glücklich und gesund, Entwickler und Nutzer jedoch nicht. Da Google jedoch seine Verantwortlichkeiten auf das System beschränkt, warum sollten sie sich für die beiden letzteren interessieren? Anscheinend nicht. Könnten sie es besser machen? Natürlich hätten sie beispielsweise den Dialog "Anwendung ist beschäftigt" bedienen und einen Benutzer bitten können, eine Entscheidung über das Warten oder Beenden der App zu treffen, aber warum sich die Mühe machen, liegt nicht in ihrer Verantwortung. Die Hauptsache ist, dass das System jetzt gesund ist.
Nach meinen Beobachtungen kommt dies relativ selten vor, in meinem Fall ungefähr 1 Absturz pro Monat für 1K-Benutzer. Es ist unmöglich, es zu reproduzieren, und selbst wenn es reproduziert wird, können Sie nichts tun, um es dauerhaft zu reparieren.
In diesem Thread gab es einen guten Vorschlag, "bind" anstelle von "start" zu verwenden und dann, wenn der Dienst bereit ist, onServiceConnected zu verarbeiten. Dies bedeutet jedoch wiederum, dass startForegroundService-Aufrufe überhaupt nicht verwendet werden.
Ich denke, die richtige und ehrliche Aktion von Google-Seite wäre, allen zu sagen, dass startForegourndServcie einen Mangel hat und nicht verwendet werden sollte.
Die Frage bleibt weiterhin: Was soll stattdessen verwendet werden? Zum Glück gibt es jetzt JobScheduler und JobService, die eine bessere Alternative für Vordergrunddienste darstellen. Aus diesem Grund ist es eine bessere Option:
Es bedeutet, dass Sie sich nicht mehr um den Umgang mit Wakelocks kümmern müssen, und deshalb unterscheidet es sich nicht von Vordergrunddiensten. Aus Sicht der Implementierung ist JobScheduler nicht Ihr Dienst, sondern ein System, vermutlich wird es die Warteschlange richtig behandeln und Google wird niemals sein eigenes Kind beenden :)
Samsung hat in seinem Samsung Accessory Protocol (SAP) von startForegroundService auf JobScheduler und JobService umgestellt. Dies ist sehr hilfreich, wenn Geräte wie Smartwatches mit Hosts wie Telefonen kommunizieren müssen, bei denen der Job über den Hauptthread einer App mit einem Benutzer interagieren muss. Da die Jobs vom Scheduler an den Hauptthread gesendet werden, wird dies möglich. Sie sollten sich jedoch daran erinnern, dass der Job auf dem Hauptthread ausgeführt wird, und alle schweren Inhalte auf andere Threads und asynchrone Aufgaben auslagern.
Die einzige Gefahr beim Wechsel zu JobScheduler / JobService besteht darin, dass Sie alten Code umgestalten müssen, und es macht keinen Spaß. Ich habe die letzten zwei Tage damit verbracht, die SAP-Implementierung des neuen Samsung zu nutzen. Ich werde meine Absturzberichte ansehen und Sie wissen lassen, ob die Abstürze erneut auftreten. Theoretisch sollte es nicht passieren, aber es gibt immer Details, die uns möglicherweise nicht bekannt sind.
UPDATE Keine Abstürze mehr vom Play Store gemeldet. Dies bedeutet, dass JobScheduler / JobService kein solches Problem haben und der Wechsel zu diesem Modell der richtige Ansatz ist, um das Problem startForegroundService ein für alle Mal zu beseitigen. Ich hoffe, Google / Android liest es und wird irgendwann eine offizielle Anleitung für alle kommentieren / beraten / bereitstellen.
UPDATE 2
Für diejenigen, die SAP verwenden und fragen, wie SAP V2 JobService verwendet, finden Sie unten eine Erklärung.
In Ihrem benutzerdefinierten Code müssen Sie SAP initialisieren (es ist Kotlin):
Jetzt müssen Sie den Samsung-Code dekompilieren, um zu sehen, was im Inneren vor sich geht. Sehen Sie sich in SAAgentV2 die Implementierung von requestAgent und die folgende Zeile an:
Wechseln Sie jetzt zur SAAdapter-Klasse und suchen Sie die Funktion onServiceConnectionRequested, mit der ein Job mithilfe des folgenden Aufrufs geplant wird:
SAJobService ist nur eine Implementierung von Android'd JobService und dies ist diejenige, die eine Jobplanung durchführt:
Wie Sie sehen, verwendet die letzte Zeile hier Android'd JobScheduler, um diesen Systemdienst abzurufen und einen Job zu planen.
Im requestAgent-Aufruf haben wir mAgentCallback übergeben, eine Rückruffunktion, die die Kontrolle erhält, wenn ein wichtiges Ereignis eintritt. So wird der Rückruf in meiner App definiert:
MessageJobs hier ist eine Klasse, die ich implementiert habe, um alle Anfragen von einer Samsung-Smartwatch zu verarbeiten. Es ist nicht der vollständige Code, nur ein Skelett:
Wie Sie sehen, erfordert MessageJobs auch die MessageSocket-Klasse, die Sie implementieren müssten, und die alle von Ihrem Gerät kommenden Nachrichten verarbeitet.
Unterm Strich ist es nicht so einfach und erfordert einige Eingriffe in Interna und Codierung, aber es funktioniert und vor allem - es stürzt nicht ab.
quelle
JobIntentService
das sofortIntentService
unter Oreo ausgeführt wird, aber einen Job auf und über Oreo plant, alsoJobIntentService
nicht sofort startet. Weitere InformationenJob...
der Start einige Zeit in Anspruch nimmt und es sich um eine Vorabversion von handeltAlarmManager
.Ihre App stürzt ab, wenn Sie anrufen
Context.startForegroundService(...)
und dann anrufen,Context.stopService(...)
bevorService.startForeground(...)
aufgerufen wird.Ich habe hier einen klaren Repro ForegroundServiceAPI26
Ich habe einen Fehler in diesem Bereich geöffnet: Google Issue Tracker
Mehrere Fehler wurden geöffnet und geschlossen. Wird nicht behoben.
Hoffentlich schaffen meine mit klaren Repro-Schritten den Schnitt.
Informationen vom Google-Team
Google Issue Tracker Kommentar 36
Dies ist kein Framework-Fehler. es ist beabsichtigt. Wenn die App eine Dienstinstanz mit startet
startForegroundService()
, muss sie diese Dienstinstanz in den Vordergrundzustand versetzen und die Benachrichtigung anzeigen. Wenn die Dienstinstanz gestoppt wird, bevor siestartForeground()
aufgerufen wird, wird dieses Versprechen nicht erfüllt: Dies ist ein Fehler in der App.Zu # 31 ist die Veröffentlichung eines Dienstes, den andere Apps direkt starten können, grundsätzlich unsicher. Sie können dies ein wenig abmildern, indem Sie alle Startaktionen dieses Dienstes als erforderlich behandeln
startForeground()
, obwohl dies offensichtlich möglicherweise nicht das ist, was Sie sich vorgestellt haben.Google Issue Tracker Kommentar 56
Es gibt verschiedene Szenarien, die hier zum gleichen Ergebnis führen.
Das geradezu semantische Problem, dass es einfach ein Fehler ist, etwas anzufangen,
startForegroundService()
aber es zu vernachlässigen, es tatsächlich über in den Vordergrund zu stellenstartForeground()
, ist genau das: ein semantisches Problem. Das wird absichtlich als App-Fehler behandelt. Das Beenden des Dienstes vor dem Übergang in den Vordergrund ist ein App-Fehler. Das war der Kern des OP, und deshalb wurde dieses Problem als "wie beabsichtigt funktionieren" gekennzeichnet.Es gibt jedoch auch Fragen zur falschen Erkennung dieses Problems. Das ist , wird wird als ein echtes Problem behandelt, obwohl es getrennt von dieser Bug - Tracker Ausgabe verfolgt. Wir sind nicht taub für die Beschwerde.
quelle
Ich habe ein paar Tage lang darüber recherchiert und die Lösung gefunden. Jetzt können Sie in Android O die Hintergrundbeschränkung wie folgt einstellen
Der Dienst, der eine Dienstklasse aufruft
und die Serviceklasse sollte wie sein
quelle
Ich habe ein Widget, das relativ häufig aktualisiert, wenn das Gerät wach ist, und ich habe in nur wenigen Tagen Tausende von Abstürzen gesehen.
Der Problemauslöser
Ich habe das Problem sogar bei meinem Pixel 3 XL bemerkt, als ich nicht gedacht hätte, dass das Gerät überhaupt viel Last hat. Und alle Codepfade wurden mit abgedeckt
startForeground()
. Aber dann wurde mir klar, dass mein Service in vielen Fällen die Arbeit sehr schnell erledigt. Ich glaube, der Auslöser für meine App war, dass der Dienst beendet wurde, bevor das System tatsächlich eine Benachrichtigung zeigte.Die Problemumgehung / Lösung
Ich konnte alle Abstürze loswerden. Was ich getan habe, war den Anruf zu entfernen
stopSelf()
. (Ich habe darüber nachgedacht, den Stopp zu verzögern, bis ich ziemlich sicher war, dass die Benachrichtigung angezeigt wurde, aber ich möchte nicht, dass der Benutzer die Benachrichtigung sieht, wenn dies nicht erforderlich ist.) Wenn der Dienst eine Minute lang inaktiv war oder das System zerstört es normalerweise ohne Ausnahmen.quelle
Nur ein Kopf hoch, da ich viel zu viele Stunden damit verschwendet habe. Ich bekam diese Ausnahme immer wieder, obwohl ich
startForeground(..)
als erstes anriefonCreate(..)
. Am Ende stellte ich fest, dass das Problem durch die Verwendung verursacht wurdeNOTIFICATION_ID = 0
. Die Verwendung eines anderen Werts scheint dies zu beheben.quelle
Ich habe eine Lösung für dieses Problem. Ich habe dieses Update in meiner eigenen App (300K + DAU) überprüft, wodurch mindestens 95% dieser Art von Absturz reduziert werden können, dieses Problem jedoch immer noch nicht zu 100% vermieden werden kann.
Dieses Problem tritt auch dann auf, wenn Sie sicherstellen, dass startForeground () direkt nach dem Start des Dienstes aufgerufen wird, wie von Google dokumentiert. Dies kann daran liegen, dass der Prozess zur Erstellung und Initialisierung von Diensten in vielen Szenarien bereits mehr als 5 Sekunden dauert. Unabhängig davon, wann und wo Sie die Methode startForeground () aufrufen, ist dieser Absturz unvermeidbar.
Meine Lösung besteht darin, sicherzustellen, dass startForeground () innerhalb von 5 Sekunden nach der Methode startForegroundService () ausgeführt wird, unabhängig davon, wie lange Ihr Dienst erstellt und initialisiert werden muss. Hier ist die detaillierte Lösung.
Verwenden Sie startForegroundService nicht an erster Stelle, sondern bindService () mit dem Flag auto_create. Es wird auf die Dienstinitialisierung warten. Hier ist der Code, mein Beispieldienst ist MusicService:
Dann ist hier die MusicBinder-Implementierung:
Der wichtigste Teil, die MusicService-Implementierung, die forceForeground () -Methode, stellt sicher, dass die startForeground () -Methode direkt nach startForegroundService () aufgerufen wird:
Wenn Sie das Code-Snippet von Schritt 1 in einer ausstehenden Absicht ausführen möchten, z. B. wenn Sie einen Vordergrunddienst in einem Widget starten möchten (Klicken auf die Widget-Schaltfläche), ohne Ihre App zu öffnen, können Sie das Code-Snippet in einen Broadcast-Empfänger einbinden und ein Broadcast-Ereignis auslösen, anstatt den Dienstbefehl zu starten.
Das ist alles. Ich hoffe es hilft. Viel Glück.
quelle
Dieser Fehler tritt auch unter Android 8+ auf, wenn Service.startForeground (int id, Benachrichtigungsbenachrichtigung) aufgerufen wird, während id auf 0 gesetzt ist.
quelle
Da jeder, der hierher kommt, das gleiche leidet, möchte ich meine Lösung teilen, die noch niemand zuvor versucht hat (in dieser Frage jedenfalls). Ich kann Ihnen versichern, dass es funktioniert, auch an einem gestoppten Haltepunkt, der diese Methode bestätigt.
Das Problem ist,
Service.startForeground(id, notification)
vom Dienst selbst anzurufen , oder? Android Framework garantiert leider nicht,Service.startForeground(id, notification)
innerhalbService.onCreate()
von 5 Sekunden anzurufen, löst aber trotzdem die Ausnahme aus, also habe ich mir diesen Weg ausgedacht.Context.startForegroundService()
Context.startForegroundService()
über die Dienstverbindung an und rufen Sie sofortService.startForeground()
innerhalb der Dienstverbindung an.Context.bindService()
Methode in einem Try-Catch auf, da der Aufruf in einigen Fällen eine Ausnahme auslösen kann. In diesem Fall müssen Sie sich auf denContext.startForegroundService()
direkten Aufruf verlassen und hoffen, dass er nicht fehlschlägt. Ein Beispiel kann ein Broadcast-Empfängerkontext sein. Das Abrufen des Anwendungskontexts löst in diesem Fall jedoch keine Ausnahme aus, die direkte Verwendung des Kontexts jedoch.Dies funktioniert sogar, wenn ich nach dem Binden des Dienstes und vor dem Auslösen des Aufrufs "startForeground" auf einen Haltepunkt warte. Warten zwischen 3-4 Sekunden löst die Ausnahme nicht aus, während sie nach 5 Sekunden die Ausnahme auslöst. (Wenn das Gerät nicht in 5 Sekunden zwei Codezeilen ausführen kann, ist es Zeit, diese in den Papierkorb zu werfen.)
Beginnen Sie also mit dem Erstellen einer Dienstverbindung.
Erstellen Sie in Ihrem Dienst einen Ordner, der die Instanz Ihres Dienstes zurückgibt.
Dann versuchen , den Dienst zu binden , aus diesem Zusammenhang. Wenn dies erfolgreich ist, wird die
ServiceConnection.onServiceConnected()
Methode von der von Ihnen verwendeten Dienstverbindung aufgerufen . Behandeln Sie dann die Logik in dem oben gezeigten Code. Ein Beispielcode würde folgendermaßen aussehen:Es scheint an den Anwendungen zu arbeiten, die ich entwickle, also sollte es auch funktionieren, wenn Sie es versuchen.
quelle
Problem mit Android O API 26
Wenn Sie den Dienst sofort beenden (damit Ihr Dienst nicht wirklich ausgeführt wird (Wortlaut / Verständnis) und Sie sich weit unter dem ANR-Intervall befinden, müssen Sie vor stopSelf immer noch startForeground aufrufen
https://plus.google.com/116630648530850689477/posts/L2rn4T6SAJ5
Versuchte diesen Ansatz, aber es entsteht immer noch ein Fehler: -
Ich benutze dies, bis der Fehler behoben ist
quelle
Ich stehe vor dem gleichen Problem und nachdem ich Zeit damit verbracht habe, eine Lösung zu finden, können Sie den folgenden Code ausprobieren. Wenn Sie verwenden
Service
, geben SieIntent Service
diesen Code in onCreate ein. Andernfalls verwenden Sie diesen Code in onHandleIntent.quelle
Ich habe dieses Problem untersucht und dies ist, was ich bisher entdeckt habe. Dieser Absturz kann passieren, wenn wir einen ähnlichen Code haben:
MyForegroundService.java
MainActivity.java
Die Ausnahme wird im folgenden Block des Codes ausgelöst:
ActiveServices.java
Diese Methode wird vor der Ausführung
onCreate()
vonMyForegroundService
da Android Plänen der Erstellung des Dienstes auf den Haupt - Thread - Handler , sondernbringDownServiceLocked
auf einem genanntBinderThread
, Weicht eine Race - Bedingung ist. Es bedeutet, dassMyForegroundService
wir keine Chance hatten anzurufen,startForeground
was den Absturz verursachen würde.Um dies zu beheben, müssen wir sicherstellen, dass dies
bringDownServiceLocked
nicht vorheronCreate()
von aufgerufen wirdMyForegroundService
.Durch die Verwendung von klebrigen Sendungen stellen wir sicher , dass die Sendung erhält nicht verloren und
stopReceiver
erhält den Anschlag Absicht, sobald sie registriert wurdeonCreate()
vonMyForegroundService
. Zu diesem Zeitpunkt haben wir bereits angerufenstartForeground(...)
. Wir müssen diese klebrige Sendung auch entfernen, um zu verhindern, dass stopReceiver das nächste Mal benachrichtigt wird.Bitte beachten Sie, dass die Methode
sendStickyBroadcast
veraltet ist und ich sie nur als vorübergehende Problemumgehung verwende, um dieses Problem zu beheben.quelle
So viele Antworten, aber keine haben in meinem Fall funktioniert.
Ich habe den Dienst so begonnen.
Und in meinem Dienst in onStartCommand
Und vergessen Sie nicht, NOTIFICATION_ID ungleich Null zu setzen
Also war alles perfekt, stürzte aber immer noch auf 8.1 ab, also war die Ursache wie unten.
Ich habe Stop Vordergrund mit Benachrichtigung entfernen aufgerufen, aber sobald die Benachrichtigung entfernt wurde, wird der Dienst zum Hintergrund und der Hintergrunddienst kann nicht in Android O aus dem Hintergrund ausgeführt werden. gestartet nach Push erhalten.
So magisch ist das Wort
Befolgen Sie alle oben genannten Schritte und genießen Sie jeden Grund, warum Ihr Dienst abstürzt.
quelle
startForeground
angerufen werdenonCreate
?https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)
Service.startForeground(int, android.app.Notification)
Stellen Sie sicher, dass Sie onCreate () aufrufen, damit es aufgerufen wird. Wenn Sie eine Bedingung haben, die Sie möglicherweise daran hindert, sollten Sie das normale verwendenContext.startService(Intent)
und sichService.startForeground(int, android.app.Notification)
selbst aufrufen .Es scheint, dass der
Context.startForegroundService()
einen Wachhund hinzufügt, um sicherzustellen, dass Sie den angerufen haben,Service.startForeground(int, android.app.Notification)
bevor er zerstört wurde ...quelle
Bitte rufen Sie keine StartForgroundServices innerhalb der onCreate () -Methode auf. Sie müssen die StartForground-Dienste in onStartCommand () aufrufen, nachdem Sie den Arbeitsthread erstellt haben. Andernfalls erhalten Sie immer ANR. Schreiben Sie daher keine komplexe Anmeldung in den Hauptthread von onStartCommand (). ;;
EDIT: Achtung! Die Funktion startForeground kann nicht 0 als erstes Argument verwenden, sondern löst eine Ausnahme aus! Dieses Beispiel enthält einen falschen Funktionsaufruf. Ändern Sie 0 in Ihre eigene Konstante, die nicht 0 oder größer als Max (Int32) sein kann.
quelle
Auch nach dem Aufruf des
startForeground
InService
stürzt es auf einigen Geräten ab, wenn wirstopService
kurz vor dem Aufruf anrufenonCreate
. Daher habe ich dieses Problem behoben, indem ich den Dienst mit einem zusätzlichen Flag gestartet habe:und fügte einen Check in onStartCommand hinzu, um zu sehen, ob es gestoppt wurde:
PS Wenn der Dienst nicht ausgeführt würde, würde er zuerst den Dienst starten, was ein Overhead ist.
quelle
Sie müssen eine Berechtigung als Balg für Android 9-Gerät hinzufügen, wenn Sie Ziel SDK 28 oder höher verwenden. Andernfalls tritt immer die Ausnahme auf:
quelle
Ich überprüfe nur die
PendingIntent
Null oder nicht, bevor ich die anrufecontext.startForegroundService(service_intent)
Funktion aufrufe.das funktioniert bei mir
quelle
Rufen Sie einfach die startForeground-Methode unmittelbar nach dem Erstellen von Service oder IntentService auf. so was:
quelle
Ok, etwas, das mir aufgefallen ist und das vielleicht auch einigen anderen helfen könnte. Dies ist ausschließlich ein Test, um festzustellen, ob ich herausfinden kann, wie die aufgetretenen Vorkommnisse behoben werden können. Nehmen wir der Einfachheit halber an, ich habe eine Methode, die dies vom Moderator aufruft.
Dies wird mit dem gleichen Fehler abstürzen. Der Dienst wird NICHT gestartet, bis die Methode abgeschlossen ist, daher nicht
onCreate()
im Dienst.Selbst wenn Sie die Benutzeroberfläche außerhalb des Hauptthreads aktualisieren, startet sie nicht rechtzeitig, wenn Sie etwas haben, das diese Methode möglicherweise aufhält, und gibt Ihnen den gefürchteten Vordergrundfehler. In meinem Fall haben wir einige Dinge in eine Warteschlange geladen und jeweils angerufen
startForegroundService
, aber im Hintergrund war jeweils eine Logik enthalten. Wenn die Logik also zu lange gedauert hat, um diese Methode zu beenden, da sie hintereinander aufgerufen wurden, Absturzzeit. Das altestartService
ignorierte es einfach und machte sich auf den Weg und da wir es jedes Mal anriefen, endete die nächste Runde.Ich fragte mich daher, ob ich den Dienst von einem Thread im Hintergrund aus aufrufen konnte, ob er beim Start nicht vollständig gebunden und sofort ausgeführt werden konnte, und begann zu experimentieren. Obwohl dies NICHT sofort gestartet wird, stürzt es nicht ab.
Ich werde nicht vorgeben zu wissen, warum es nicht abstürzt, obwohl ich vermute, dass dies dazu zwingt, zu warten, bis der Haupt-Thread es rechtzeitig handhaben kann. Ich weiß, dass es nicht ideal ist, es an den Haupt-Thread zu binden, aber da meine Verwendung es im Hintergrund aufruft, bin ich nicht wirklich besorgt, wenn es wartet, bis es abgeschlossen sein kann, anstatt abzustürzen.
quelle
Ich füge Code in @humazed Antwort hinzu. Es gibt also keine erste Benachrichtigung. Es könnte eine Problemumgehung sein, aber es funktioniert für mich.
Ich füge transparentColor in kleinem Symbol und Farbe bei Benachrichtigung hinzu. Es wird klappen.
quelle
Ich habe das Problem behoben, dass der Dienst mit
startService(intent)
anstattContext.startForeground()
gestartet undstartForegound()
sofort danach angerufen wurdesuper.OnCreate()
. Wenn Sie den Dienst beim Booten starten, können Sie außerdem die Aktivität starten, mit der der Dienst beim Booten gestartet wird. Obwohl es keine dauerhafte Lösung ist, funktioniert es.quelle
Aktualisieren von Daten in
onStartCommand(...)
onBind (...)
onBind(...)
Veranstaltung ist eine bessere Lebenszyklus zu initiierenstartForeground
vs.onCreate(...)
weilonBind(...)
Pässe in einemIntent
der wichtigen Daten in denen enthaltenBundle
benötigten die initialisierenService
. Es ist jedoch nicht erforderlich, wieonStartCommand(...)
es aufgerufen wird, wenn dasService
zum ersten Mal erstellt wird oder nachfolgende Male aufgerufen wird.onStartCommand (...)
startForeground
inonStartCommand(...)
ist wichtig, um das zu aktualisieren,Service
sobald es bereits erstellt wurde.Wann
ContextCompat.startForegroundService(...)
wird aufgerufen, nachdem einService
erstellt wurdeonBind(...)
undonCreate(...)
nicht aufgerufen wird. Daher können aktualisierte DatenonStartCommand(...)
über dieIntent
Bundle
zu aktualisierenden Daten in die übergeben werdenService
.Stichprobe
Ich verwende dieses Muster, um die
PlayerNotificationManager
in der Coinverse Cryptocurrency News App zu implementieren .Aktivität / Fragment.kt
AudioService.kt
quelle
Bedienung
Prüfer
Ergebnis
quelle