Po uruchomieniu aplikacji aplikacja uruchamia usługę, która powinna wykonać jakieś zadanie sieciowe. Po wybraniu interfejsu API na poziomie 26 moja aplikacja nie uruchamia się w systemie Android 8.0 w tle.
Przyczyna: java.lang.IllegalStateException: Niedozwolony do uruchomienia usługi Zamiar {cmp = my.app.tt / com.my.service}: aplikacja jest w tle UidRecord {90372b1 u0a136 Bezczynność CEM: 1 seq (0,0 , 0)}
jak rozumiem, dotyczy to: limitów wykonania w tle
Metoda startService () generuje teraz wyjątek IllegalStateException, jeśli aplikacja atakująca system Android 8.0 próbuje użyć tej metody w sytuacji, gdy nie można tworzyć usług w tle.
„ w sytuacji, gdy nie jest to dozwolone ” - co to właściwie znaczy? I jak to naprawić. Nie chcę ustawiać mojej usługi jako „pierwszego planu”
startForegroundService()
zamiaststartService()
.Odpowiedzi:
Dozwolone sytuacje to tymczasowa biała lista, w której usługa w tle zachowuje się tak samo jak przed Androidem O.
Źródło: https://developer.android.com/about/versions/oreo/background.html
Innymi słowy, jeśli twoja usługa w tle nie spełnia wymagań białej listy, musisz użyć nowego JobScheduler . Zasadniczo działa tak samo jak usługa w tle, ale jest okresowo wywoływana zamiast ciągłego działania w tle.
Jeśli korzystasz z usługi IntentService, możesz zmienić ją na JobIntentService. Zobacz odpowiedź @ kosev poniżej .
źródło
FirebaseInstanceIdService
i jegoonTokenRefresh
metoda jest komunikatem FCM o wysokim priorytecie?Mam rozwiązanie. W przypadku urządzeń w wersji wcześniejszej niż 8.0 wystarczy użyć
startService()
, ale w przypadku urządzeń w wersji późniejszej niż 7.0 należy użyćstartForgroundService()
. Oto przykład kodu, aby uruchomić usługę.W klasie usług dodaj poniższy kod w celu powiadomienia:
Gdzie O to wersja Androida 26.
źródło
ContextCompat.startForegroundService(...)
biblioteka wsparcia, której można użyć zamiast tego.Najlepszym sposobem jest użycie JobIntentService który korzysta z nowego JobScheduler dla Oreo lub starych usług, jeśli nie są dostępne.
Oświadcz w swoim manifeście:
A w twoich usługach musisz wymienić onHandleIntent na onHandleWork:
Następnie zaczynasz swoją usługę od:
źródło
enqueueWork(...)
jest również metodą statyczną.Jeśli usługa jest uruchomiona w wątku tła poprzez rozszerzenie
IntentService
, można zastąpićIntentService
zJobIntentService
którego jest wykonane jako część biblioteki Android WsparciaZaletą używania
JobIntentService
jest to, że zachowuje się jakIntentService
na urządzeniach sprzed O, a na O i wyżej, wysyła to jako zadanieJobScheduler
może być również stosowany do zadań okresowych / na żądanie. Pamiętaj jednak, aby obsługiwać zgodność wsteczną, ponieważJobScheduler
interfejs API jest dostępny tylko w interfejsie API 21źródło
W Oreo Android zdefiniowano ograniczenia usług w tle .
Jeśli jednak zawsze potrzebujesz usługi, możesz skorzystać z usługi pierwszego planu.
Możesz więc zrobić usługę pierwszego planu . Będziesz musiał pokazać użytkownikowi powiadomienie, gdy usługa jest uruchomiona. Zobacz tę odpowiedź (Jest wiele innych)
Rozwiązanie, jeśli -
nie chcesz otrzymywać powiadomienia o swojej usłudze?
Możesz używać zadań okresowych z Menedżerem alarmów , Harmonogramem zadań , Evernote-Jobs lub Work Manager .
Testowałem zawsze działającą usługę z Work-Managerem.
źródło
Tak, to dlatego, że nie możesz już uruchamiać usług w tle na API 26. Możesz więc uruchomić ForegroundService powyżej API 26.
Musisz użyć
i opublikuj powiadomienie podczas przetwarzania wycieku.
źródło
Jak powiedział @kosev w swojej odpowiedzi , możesz użyć JobIntentService. Ale używam alternatywnego rozwiązania - wychwytuję IllegalStateException i uruchamiam usługę na pierwszym planie. Na przykład ta funkcja uruchamia moją usługę:
a kiedy przetwarzam Intent, robię takie rzeczy:
źródło
context.startService
działa w tle - czasami nie - to wygląda na tylko najlepszy sposób inaczej trzeba zaimplementować więcej kodu w głównej klasyextending Application
aimplementing ActivityLifecycleCallbacks
i śledzić, czy aplikacja jest na pierwszym planie lub w tle i rozpocząć intencją odpowiednio.Z informacji o wydaniu bazy ogniowej wynika, że obsługa Androida O została wydana po raz pierwszy w wersji 10.2.1 (chociaż zalecałbym używanie najnowszej wersji).
dodaj nowe zależności komunikatów firebase dla Androida O
w razie potrzeby zaktualizuj usługi Google Play i repozytoria Google.
źródło
Jeśli jakakolwiek intencja wcześniej działała dobrze, gdy aplikacja jest w tle, nie będzie już tak w przypadku Androida 8 i nowszych. Dotyczy tylko zamiaru, który musi wykonać pewne przetwarzanie, gdy aplikacja jest w tle.
Należy postępować zgodnie z poniższymi krokami:
JobIntentService
zamiastIntentService
.Rozszerzająca się klasa
JobIntentService
powinna implementowaćonHandleWork(@NonNull Intent intent)
metodę - i powinna mieć poniżej metody, która wywołaonHandleWork
metodę:Zadzwoń
enqueueWork(Context, intent)
z klasy, w której określono twoje zamiary.Przykładowy kod:
com.android.support:support-compat
jest potrzebny doJobIntentService
- używam26.1.0 V
.Najważniejsze jest, aby upewnić się, że wersja bibliotek Firebase jest przynajmniej włączona
10.2.1
, miałem problemy z10.2.0
- jeśli masz!Twój manifest powinien mieć poniższe uprawnienia dla klasy usługi:
Mam nadzieję że to pomoże.
źródło
Widzę wiele odpowiedzi, które zalecają użycie usługi ForegroundService. Aby korzystać z usługi ForegroundService, musi być z nią powiązane powiadomienie. Użytkownicy zobaczą to powiadomienie. W zależności od sytuacji mogą się denerwować aplikacją i odinstalować ją.
Najłatwiejszym rozwiązaniem jest użycie nowego komponentu architektury o nazwie WorkManager. Możesz sprawdzić dokumentację tutaj: https://developer.android.com/topic/libraries/architecture/workmanager/
Wystarczy zdefiniować klasę pracownika, która rozszerza pracownika.
Następnie planujesz, kiedy chcesz go uruchomić.
Łatwy! Istnieje wiele sposobów konfigurowania pracowników. Obsługuje powtarzające się zadania, a nawet możesz wykonywać skomplikowane czynności, takie jak tworzenie łańcuchów, jeśli jest to potrzebne. Mam nadzieję że to pomoże.
źródło
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately
... może to być najłatwiejsze, jednak moja aplikacja potrzebuje usługi w tle, która natychmiast wykonuje żądania użytkowników!Alternatywne rozwiązanie przy użyciu JobScheduler, może uruchomić usługę w tle w regularnych odstępach czasu.
Najpierw ułóż klasę o nazwie Util.java
Następnie utwórz klasę JobService o nazwie TestJobService.java
Po tej klasie BroadCast Receiver o nazwie ServiceReceiver.java
Zaktualizuj plik manifestu za pomocą kodu klasy usługi i odbiornika
Pozostawiłem program uruchamiający main_intent do pliku mainActivity.java, który jest tworzony domyślnie, a zmiany w pliku MainActivity.java zostały
WOOAAH !! Usługa w tle uruchamia się bez usługi pierwszego planu
źródło
Jeśli korzystasz z kodu w wersji 8.0, aplikacja ulegnie awarii. Więc uruchom usługę na pierwszym planie. Jeśli poniżej 8.0, użyj tego:
Jeśli powyżej lub 8.0, użyj tego:
źródło
java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE
. Poprawka na stackoverflow.com/a/52382711/550471jeśli masz zintegrowane powiadomienie push z bazy ogniowej,
Dodaj nowe / zaktualizuj zależności komunikatów firebase dla Androida O (Android 8.0), ze względu na limity wykonywania w tle .
w razie potrzeby zaktualizuj usługi Google Play i repozytoria Google.
Aktualizacja:
źródło
Użyj
startForegroundService()
zamiaststartService()
i nie zapomnij utworzyćstartForeground(1,new Notification());
w swoim serwisie w ciągu 5 sekund od uruchomienia usługi.źródło
Z powodu kontrowersyjnych głosów na tę odpowiedź (+ 4 / -4 od tej edycji) PROSIMY PATRZEĆ NA INNE ODPOWIEDZI PIERWSZE I WYKORZYSTAĆ TEN WYŁĄCZNIE OSTATNI OŚRODEK . Użyłem tego tylko raz dla aplikacji sieciowej działającej jako root i zgadzam się z ogólną opinią, że tego rozwiązania nie należy używać w normalnych okolicznościach.
Oryginalna odpowiedź poniżej:
Wszystkie pozostałe odpowiedzi są poprawne, ale chciałbym zauważyć, że innym sposobem na obejście tego jest poproszenie użytkownika o wyłączenie optymalizacji baterii dla Twojej aplikacji (zazwyczaj nie jest to dobry pomysł, chyba że aplikacja jest związana z systemem). Zobacz tę odpowiedź, aby dowiedzieć się, jak zrezygnować z optymalizacji baterii bez blokowania aplikacji w Google Play.
Należy również sprawdzić, czy optymalizacje baterii są wyłączone w odbiorniku, aby zapobiec awariom poprzez:
źródło
JobScheduler
i tak dalej. Niektóre aplikacje muszą działać na niższym poziomie niż typowe aplikacje do synchronizacji. Jest to alternatywne rozwiązanie, gdy to nie działa.nie używaj w onStartCommand:
po prostu zmień na:
i będzie działać
źródło