Android 8.0: java.lang.IllegalStateException: Nie można uruchomić usługi Intent

359

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”

phnmnn
źródło
4
Oznacza to, że nie można uruchomić usługi, gdy aplikacja jest w tle
Tim
22
nie ma to nic wspólnego z uprawnieniami do wykonywania
Tim
10
Użyj startForegroundService()zamiast startService().
frogatto
2
Możesz spróbować użyć targetSdkVersion 25, ale skompilować z compileSdkVersion 26. W ten sposób możesz korzystać z nowych klas z Androida 8 i najnowszej biblioteki wsparcia, ale Twoja aplikacja nie będzie ograniczona limitami wykonywania w tle.
Kacper Dziubek
2
@KacperDziubek To powinno zadziałać, ale jest rozwiązaniem tymczasowym, ponieważ będzie wymagane, aby celować w SDK26 jesienią 2018 r.
RightHandedMonkey

Odpowiedzi:

194

Dozwolone sytuacje to tymczasowa biała lista, w której usługa w tle zachowuje się tak samo jak przed Androidem O.

W pewnych okolicznościach aplikacja w tle jest umieszczana na tymczasowej białej liście na kilka minut. Gdy aplikacja znajduje się na białej liście, może uruchamiać usługi bez ograniczeń, a jej usługi w tle mogą być uruchamiane. Aplikacja jest umieszczana na białej liście, gdy obsługuje zadanie widoczne dla użytkownika, takie jak:

  • Obsługa komunikatu Firebase Cloud Messaging (FCM) o wysokim priorytecie.
  • Odbieranie transmisji, takiej jak wiadomość SMS / MMS.
  • Wykonanie PendingIntent z powiadomienia.
  • Uruchomienie usługi VpnService, zanim aplikacja VPN awansuje na pierwszy plan.

Ź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 .

Murat Karagöz
źródło
Dostaję awarię po tym, jak chcę uruchomić usługę zaraz po otrzymaniu wiadomości GCM o „wysokim” prio. Nadal używam GCM: „com.google.android.gms: play-services-gcm: 11.4.2”, a nie „com.google.firebase: firebase-messaging: 11.4.2”. Nie jestem pewien, czy to ma znaczenie ...
Alex Radzishevsky
„Jest to w zasadzie to samo, co usługa w tle, ale jest okresowo wywoływana zamiast ciągłego działania w tle”. - nie jestem pewien, co masz na myśli, ponieważ usługi Android nigdy nie działały w sposób ciągły. Zaczynają, biegają, a potem zamykają się.
Melllvar,
2
Czy FirebaseInstanceIdService i jego onTokenRefreshmetoda jest komunikatem FCM o wysokim priorytecie?
Cord Rehn
@ phnmnn nie, GCMTaskService tak naprawdę nie podąża za FCM, więc nie działa.
Abhinav Upadhyay
4
Czy nie powinieneś używać WorkManager (tutaj: developer.android.com/topic/libraries/architecture/workmanager ) zamiast JobScheduler lub innych? Mam na myśli to: youtu.be/IrKoBFLwTN0
programista Androida
254

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ę.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, ServedService.class));
    } else {
        context.startService(new Intent(context, ServedService.class));
    }

W klasie usług dodaj poniższy kod w celu powiadomienia:

@Override
public void onCreate() {
    super.onCreate();
    startForeground(1,new Notification());
}

Gdzie O to wersja Androida 26.

Sagar Kacha
źródło
9
Usługa pierwszoplanowa to coś, o czym użytkownik będzie wiedział i które wymaga powiadomienia. Będzie również ANR, jeśli będzie działał zbyt długo. Nie jest to więc odpowiednia odpowiedź, jeśli aplikacja działa już w tle.
SimonH
80
Istnieje ContextCompat.startForegroundService(...)biblioteka wsparcia, której można użyć zamiast tego.
jayeffkay
37
To nie jest rozwiązanie.
JacksOnF1re
17
Zgadzam się również, że to nie jest rozwiązanie. Jest to obejście i pomaga, ale limity tła w Oreo zostały wprowadzone z jakiegoś powodu. Ominięcie tych limitów w ten sposób zdecydowanie nie jest właściwym podejściem (nawet jeśli działa). Najlepszym sposobem jest użycie JobScheduler (patrz zaakceptowana odpowiedź).
Vratislav Jindra
6
Nie sądzę, aby było to wygodne dla użytkownika, jeśli musisz pokazać puste powiadomienie na pierwszym planie. Biorąc pod uwagę fakt, że musisz. - Android 8.0 wprowadza nową metodę startForegroundService () w celu uruchomienia nowej usługi na pierwszym planie. Po utworzeniu usługi przez system aplikacja ma pięć sekund na wywołanie metody startForeground () usługi w celu wyświetlenia powiadomienia nowej usługi widocznego dla użytkownika. Jeśli aplikacja nie wywoła funkcji startForeground () w wyznaczonym terminie, system zatrzymuje usługę i deklaruje aplikację jako ANR.
heeleeaz
85

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:

<service android:name=".YourService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>

A w twoich usługach musisz wymienić onHandleIntent na onHandleWork:

public class YourService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, YourService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // your code
    }

}

Następnie zaczynasz swoją usługę od:

YourService.enqueueWork(context, new Intent());
kosev
źródło
Jak możesz wywołać metodę niestatyczną w metodzie statycznej? Czy możesz wyjaśnić?
Maddy
@Maddy enqueueWork(...)jest również metodą statyczną.
hgoebl
2
Gdzie nazwałbyś YourService.enqueueWork (kontekst, nowa Intent ()); ? Od odbiornika?
TheLearner
Nie wierzę, że jest to najłatwiejsze rozwiązanie. Zobacz mój komentarz poniżej na temat WorkManager. W razie potrzeby korzysta z JobIntentService, ale ma znacznie mniej płyty kotła.
TALE,
36

Jeśli usługa jest uruchomiona w wątku tła poprzez rozszerzenie IntentService, można zastąpić IntentServicezJobIntentService którego jest wykonane jako część biblioteki Android Wsparcia

Zaletą używania JobIntentServicejest to, że zachowuje się jak IntentServicena urządzeniach sprzed O, a na O i wyżej, wysyła to jako zadanie

JobSchedulermoże być również stosowany do zadań okresowych / na żądanie. Pamiętaj jednak, aby obsługiwać zgodność wsteczną, ponieważ JobSchedulerinterfejs API jest dostępny tylko w interfejsie API 21

Harini S.
źródło
1
Problem z JobIntentService polega na tym, że Android może zaplanować twoją pracę raczej arbitralnie i nie można jej niejawnie rozpocząć bez majsterkowania, w przeciwieństwie do IntentService. Zobacz stackoverflow.com/questions/52479262/...
kilokahn
15

W Oreo Android zdefiniowano ograniczenia usług w tle .

Aby poprawić wrażenia użytkownika, system Android 8.0 (poziom API 26) nakłada ograniczenia na to, co aplikacje mogą robić, gdy działają w tle.

Jeśli jednak zawsze potrzebujesz usługi, możesz skorzystać z usługi pierwszego planu.

Ograniczenia usługi w tle: gdy aplikacja jest bezczynna, istnieją ograniczenia w korzystaniu z usług w tle. Nie dotyczy to usług nowej wiedzy, które są bardziej zauważalne dla użytkownika.

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 wykonać zadanie okresowe, 1. uruchamia usługę, 2. usługa wykona swoją pracę, 3. zatrzymuje się. Dzięki temu Twoja aplikacja nie będzie uważana za rozładowanie baterii.

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.

Khemraj
źródło
WorkManager wydaje się najlepszą drogą, zakładając, że praca nie musi zostać wykonana natychmiast. Jest wstecznie kompatybilny z API 14, używając JobScheduler na urządzeniach z API 23+ i kombinacją BroadcastReceiver + AlarmManager na urządzeniach z API 14-22
James Allen
kluczową rzeczą w WorkManager jest to, że WorkManager jest przeznaczony do zadań, które można odroczyć - to znaczy, że nie trzeba ich uruchamiać natychmiast
touhid udoy
13

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ć

ContextCompat.startForegroundService(...)

i opublikuj powiadomienie podczas przetwarzania wycieku.

PK
źródło
1
OP konkretnie powiedział, że nie chce być na pierwszym planie. Należy to umieścić w komentarzu lub w ramach pełniejszej odpowiedzi.
Ricardo A.,
7

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ę:

@JvmStatic
protected fun startService(intentAction: String, serviceType: Class<*>, intentExtraSetup: (Intent) -> Unit) {
    val context = App.context
    val intent = Intent(context, serviceType)
    intent.action = intentAction
    intentExtraSetup(intent)
    intent.putExtra(NEED_FOREGROUND_KEY, false)

    try {
        context.startService(intent)
    }
    catch (ex: IllegalStateException) {
        intent.putExtra(NEED_FOREGROUND_KEY, true)
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        }
        else {
            context.startService(intent)
        }
    }
}

a kiedy przetwarzam Intent, robię takie rzeczy:

override fun onHandleIntent(intent: Intent?) {
    val needToMoveToForeground = intent?.getBooleanExtra(NEED_FOREGROUND_KEY, false) ?: false
    if(needToMoveToForeground) {
        val notification = notificationService.createSyncServiceNotification()
        startForeground(notification.second, notification.first)

        isInForeground = true
    }

    intent?.let {
        getTask(it)?.process()
    }
}
Alex Shevelev
źródło
Podoba mi się twoja próba złapania rozwiązania. Dla mnie jest to rozwiązanie, ponieważ czasami context.startServicedziała w tle - czasami nie - to wygląda na tylko najlepszy sposób inaczej trzeba zaimplementować więcej kodu w głównej klasy extending Applicationa implementing ActivityLifecycleCallbacksi śledzić, czy aplikacja jest na pierwszym planie lub w tle i rozpocząć intencją odpowiednio.
Pierre
Czy można uchwycić ten wyjątek?
thecr0w
5

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

compile 'com.google.firebase:firebase-messaging:11.6.2'

w razie potrzeby zaktualizuj usługi Google Play i repozytoria Google.

Dhaval Jivani
źródło
To nie odpowiada na pytanie, ani pytanie nie ma nic wspólnego z bazą ogniową. Należy to umieścić w komentarzu.
Ricardo A.,
5

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:

  1. Wyżej wymienione zamiary powinny być używane JobIntentServicezamiast IntentService.
  2. Rozszerzająca się klasa JobIntentServicepowinna implementować onHandleWork(@NonNull Intent intent)metodę - i powinna mieć poniżej metody, która wywoła onHandleWorkmetodę:

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, xyz.class, 123, work);
    }
  3. Zadzwoń enqueueWork(Context, intent)z klasy, w której określono twoje zamiary.

    Przykładowy kod:

    Public class A {
    ...
    ...
        Intent intent = new Intent(Context, B.class);
        //startService(intent); 
        B.enqueueWork(Context, intent);
    }

Poniższa klasa poprzednio rozszerzała klasę Service

Public Class B extends JobIntentService{
...

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, B.class, JobId, work);
    }

    protected void onHandleWork(@NonNull Intent intent) {
        ...
        ...
    }
}
  1. com.android.support:support-compatjest potrzebny do JobIntentService- używam 26.1.0 V.

  2. Najważniejsze jest, aby upewnić się, że wersja bibliotek Firebase jest przynajmniej włączona 10.2.1, miałem problemy z 10.2.0- jeśli masz!

  3. Twój manifest powinien mieć poniższe uprawnienia dla klasy usługi:

    service android:name=".B"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"

Mam nadzieję że to pomoże.

chitraju chaithanya
źródło
4

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.

public class CompressWorker extends Worker {

    public CompressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Worker.Result doWork() {

        // Do the work here--in this case, compress the stored images.
        // In this example no parameters are passed; the task is
        // assumed to be "compress the whole library."
        myCompress();

        // Indicate success or failure with your return value:
        return Result.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}

Następnie planujesz, kiedy chcesz go uruchomić.

    OneTimeWorkRequest compressionWork = 
        new OneTimeWorkRequest.Builder(CompressWorker.class)
            .build();
    WorkManager.getInstance().enqueue(compressionWork);

Ł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.

OPOWIEŚĆ
źródło
3
Obecnie WorkManager jest nadal w wersji alfa.
pzulw
3
05 marca 2019 - stabilna wersja WorkManager 1.0.0.
phnmnn,
powinien używać WorkManager zamiast interservice lub JobIntentService
sivaBE35
1
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!
Ktoś gdzieś
Jeśli chcesz, aby zadanie zostało natychmiast wykonane, powinieneś skorzystać z usługi pierwszego planu. Użytkownik zobaczy powiadomienie i będzie wiedział, że wykonujesz pracę. Sprawdź dokumenty, jeśli potrzebujesz pomocy w podjęciu decyzji, z czego korzystać. Mają całkiem niezły przewodnik do przetwarzania w tle. developer.android.com/guide/background
TALE
4

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

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;

public class Util {
// schedule the start of the service every 10 - 30 seconds
public static void schedulerJob(Context context) {
    ComponentName serviceComponent = new ComponentName(context,TestJobService.class);
    JobInfo.Builder builder = new JobInfo.Builder(0,serviceComponent);
    builder.setMinimumLatency(1*1000);    // wait at least
    builder.setOverrideDeadline(3*1000);  //delay time
    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);  // require unmetered network
    builder.setRequiresCharging(false);  // we don't care if the device is charging or not
    builder.setRequiresDeviceIdle(true); // device should be idle
    System.out.println("(scheduler Job");

    JobScheduler jobScheduler = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        jobScheduler = context.getSystemService(JobScheduler.class);
    }
    jobScheduler.schedule(builder.build());
   }
  }

Następnie utwórz klasę JobService o nazwie TestJobService.java

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.widget.Toast;

  /**
   * JobService to be scheduled by the JobScheduler.
   * start another service
   */ 
public class TestJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
    Util.schedulerJob(getApplicationContext()); // reschedule the job
    Toast.makeText(this, "Bg Service", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    return true;
  }
 }

Po tej klasie BroadCast Receiver o nazwie ServiceReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

 public class ServiceReceiver extends BroadcastReceiver {
 @Override
public void onReceive(Context context, Intent intent) {
    Util.schedulerJob(context);
 }
}

Zaktualizuj plik manifestu za pomocą kodu klasy usługi i odbiornika

<receiver android:name=".ServiceReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <service
        android:name=".TestJobService"
        android:label="Word service"
        android:permission="android.permission.BIND_JOB_SERVICE" >

    </service>

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

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Util.schedulerJob(getApplicationContext());
  }
 }

WOOAAH !! Usługa w tle uruchamia się bez usługi pierwszego planu

Anshul1507
źródło
2

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:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
context.startService(serviceIntent);

Jeśli powyżej lub 8.0, użyj tego:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
ContextCompat.startForegroundService(context, serviceIntent );
iamfaizuddin
źródło
Zaleca się korzystanie z usług Foreground tylko w przypadkach, w których użytkownik musi wiedzieć, że usługa jest uruchomiona. Typowym przykładem jest odtwarzanie muzyki w tle. Są inne przypadki, które mają sens, ale nie powinieneś po prostu przekształcać wszystkich swoich usług w usługi pierwszego planu. Rozważ przekonwertowanie swoich usług, aby korzystały z WorkManager z komponentów architektonicznych Google, gdy potrzebujesz trochę pracy w tle i masz pewność, że będzie działać.
TALE
startForegroundService wymaga pozwolenia, w przeciwnym razie java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE. Poprawka na stackoverflow.com/a/52382711/550471
Ktoś gdzieś
1

jeś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 .

compile 'com.google.firebase:firebase-messaging:11.4.0'

w razie potrzeby zaktualizuj usługi Google Play i repozytoria Google.

Aktualizacja:

 compile 'com.google.firebase:firebase-messaging:11.4.2'
Samir Mangroliya
źródło
0

Użyj startForegroundService()zamiast startService() i nie zapomnij utworzyć startForeground(1,new Notification());w swoim serwisie w ciągu 5 sekund od uruchomienia usługi.

Arpit
źródło
2
Wygląda na to, że nowa funkcja Notificaction () nie działa w systemie Android 8.1; Powinieneś utworzyć kanał powiadomień: stackoverflow.com/a/47533338/1048087
Prizoff
0

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:

if (Build.VERSION.SDK_INT < 26 || getSystemService<PowerManager>()
        ?.isIgnoringBatteryOptimizations(packageName) != false) {
    startService(Intent(context, MyService::class.java))
} // else calling startService will result in crash
Mój Boże
źródło
1
Poproszenie użytkowników o pozwolenie na darmową przepustkę przy użyciu jak największej ilości baterii nie jest dobrym rozwiązaniem. Zastanów się nad konwersją kodu na rozwiązanie bardziej przyjazne dla baterii. Twoi użytkownicy będą Ci wdzięczni.
TALE
5
@TALE Nie każda usługa działająca w tle może być przyjazna dla baterii przy użyciu JobScheduleri 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.
Mygod
-17

nie używaj w onStartCommand:

return START_NOT_STICKY

po prostu zmień na:

return START_STICKY

i będzie działać

Omar Othman
źródło