Android 8.0: java.lang.IllegalStateException: Dienst Intent darf nicht gestartet werden

360

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.

phnmnn
quelle
4
Es bedeutet, dass Sie keinen Dienst starten können, wenn sich Ihre App im Hintergrund befindet
Tim
22
Dies hat nichts mit Laufzeitberechtigungen zu tun
Tim
10
Verwenden Sie startForegroundService()anstelle von startService().
Frogatto
2
Sie können versuchen, targetSdkVersion 25 zu verwenden, aber mit compileSdkVersion 26 kompilieren. Auf diese Weise können Sie neue Klassen aus Android 8 und der neuesten Unterstützungsbibliothek verwenden, Ihre App wird jedoch nicht durch Hintergrundausführungsbeschränkungen eingeschränkt.
Kacper Dziubek
2
@KacperDziubek Das sollte funktionieren, ist aber eine vorübergehende Lösung, da SDK26 im Herbst 2018 als Ziel festgelegt werden muss.
RightHandedMonkey

Antworten:

194

Die zulässigen Situationen sind eine temporäre Whitelist, in der sich der Hintergrunddienst wie vor Android O verhält.

Unter bestimmten Umständen wird eine Hintergrund-App für einige Minuten auf einer temporären Whitelist platziert. Während sich eine App auf der Whitelist befindet, kann sie Dienste ohne Einschränkung starten, und ihre Hintergrunddienste können ausgeführt werden. Eine App wird in die Whitelist aufgenommen, wenn sie eine Aufgabe bearbeitet, die für den Benutzer sichtbar ist, z.

  • Behandlung einer FCM-Nachricht (Firebase Cloud Messaging) mit hoher Priorität.
  • Empfangen einer Sendung, z. B. einer SMS / MMS-Nachricht.
  • Ausführen eines PendingIntent aus einer Benachrichtigung.
  • Starten eines VpnService, bevor sich die VPN-App in den Vordergrund rückt.

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 .

Murat Karagöz
quelle
Ich erhalte einen Absturz, nachdem ich den Dienst starten möchte, kurz nachdem ich die GCM-Nachricht "High" Prio erhalten habe. Ich verwende immer noch GCM: "com.google.android.gms: play-services-gcm: 11.4.2", nicht "com.google.firebase: firebase-messaging: 11.4.2". Ich
bin
"Es ist im Grunde dasselbe wie ein Hintergrunddienst, wird jedoch regelmäßig aufgerufen, anstatt kontinuierlich im Hintergrund ausgeführt zu werden." - Ich bin mir nicht sicher, was Sie damit meinen, da Android-Dienste nie kontinuierlich ausgeführt wurden. Sie starten, rennen und fahren dann herunter.
Melllvar
2
Ist das FirebaseInstanceIdService und seine onTokenRefreshMethode eine FCM-Nachricht mit hoher Priorität?
Cord Rehn
@phnmnn nein, GCMTaskService folgt FCM nicht wirklich, daher funktionieren sie nicht.
Abhinav Upadhyay
4
Sollten Sie nicht WorkManager (hier: developer.android.com/topic/libraries/architecture/workmanager ) anstelle von JobScheduler oder anderen verwenden? Ich meine das: youtu.be/IrKoBFLwTN0
Android-Entwickler
255

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 verwenden startForgroundService(). Hier ist ein Beispiel für den Code zum Starten des Dienstes.

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

Fügen Sie in der Serviceklasse den folgenden Code zur Benachrichtigung hinzu:

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

Wobei O Android Version 26 ist.

Sagar Kacha
quelle
9
Ein Vordergrunddienst ist etwas, das dem Benutzer bekannt ist und das eine Benachrichtigung benötigt. Es wird auch ANR, wenn es zu lange läuft. Es ist also keine wirklich passende Antwort, wenn die App bereits im Hintergrund ausgeführt wird.
SimonH
80
Es gibt eine ContextCompat.startForegroundService(...)Support-Bibliothek, die stattdessen verwendet werden kann.
Jayeffkay
37
Das ist keine Lösung.
JacksOnF1re
17
Ich stimme auch zu, dass dies keine Lösung ist. Es ist eine Problemumgehung und hilft, aber die Hintergrundbeschränkungen in Oreo wurden aus einem bestimmten Grund eingeführt. Diese Grenzen auf diese Weise zu umgehen, ist definitiv nicht der richtige Ansatz (obwohl es funktioniert). Am besten verwenden Sie JobScheduler (siehe akzeptierte Antwort).
Vratislav Jindra
6
Ich denke nicht, dass es eine gute Benutzererfahrung sein wird, wenn Sie eine leere Vordergrundbenachrichtigung anzeigen müssen. In Anbetracht der Tatsache, dass Sie müssen. - Android 8.0 führt die neue Methode startForegroundService () ein, um einen neuen Dienst im Vordergrund zu starten. Nachdem das System den Dienst erstellt hat, hat die App fünf Sekunden Zeit, die startForeground () -Methode des Dienstes aufzurufen, um die vom Benutzer sichtbare Benachrichtigung des neuen Dienstes anzuzeigen. Wenn die App startForeground () nicht innerhalb des Zeitlimits aufruft, stoppt das System den Dienst und deklariert die App als ANR.
Heeleeaz
85

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:

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

Und in Ihrem Dienst müssen Sie onHandleIntent durch onHandleWork ersetzen:

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
    }

}

Dann starten Sie Ihren Dienst mit:

YourService.enqueueWork(context, new Intent());
kosev
quelle
Wie können Sie eine nicht statische Methode innerhalb einer statischen Methode aufrufen? Kannst du bitte Erklären?
Maddy
@Maddy enqueueWork(...)ist ebenfalls eine statische Methode.
Hgoebl
2
Wo würden Sie YourService.enqueueWork aufrufen (Kontext, neue Absicht ()); ? Vom Rundfunkempfänger?
TheLearner
Ich glaube nicht, dass dies die einfachste Lösung ist. Siehe meinen Kommentar unten zu WorkManager. Es verwendet gegebenenfalls den JobIntentService, hat jedoch viel weniger Kesselplatte.
TALE
36

Wenn der Dienst durch die Erweiterung in einem Hintergrund - Thread ausgeführt wird IntentService, können Sie ersetzen IntentServicemit JobIntentServiceder als Teil der Android Support Library zur Verfügung gestellt

Der Vorteil der Verwendung JobIntentServicebesteht darin, dass sie sich IntentServiceauf Pre-O-Geräten verhält und auf O und höher als Job versendet

JobSchedulerkann auch für periodische / On-Demand-Jobs verwendet werden. Stellen Sie jedoch sicher, dass die Abwärtskompatibilität gewährleistet ist, da die JobSchedulerAPI nur über API 21 verfügbar ist

Harini S.
quelle
1
Das Problem mit JobIntentService ist, dass Android Ihre Arbeit eher willkürlich planen kann und im Gegensatz zu einem IntentService nicht implizit gestartet werden kann, ohne etwas herumzubasteln. Siehe stackoverflow.com/questions/52479262/…
kilokahn
15

In Oreo hat Android Grenzen für Hintergrunddienste definiert .

Um die Benutzererfahrung zu verbessern, schränkt Android 8.0 (API-Stufe 26) die Funktionen von Apps im Hintergrund ein.

Wenn Sie jedoch immer einen Dienst ausführen müssen, können Sie den Vordergrunddienst verwenden.

Einschränkungen für Hintergrunddienste: Während eine App inaktiv ist, gibt es Einschränkungen für die Verwendung von Hintergrunddiensten. Dies gilt nicht für Vordergrunddienste, die für den Benutzer auffälliger sind.

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 ausführen, 1. es startet Ihren Dienst, 2. der Dienst erledigt seine Arbeit und 3. stoppt sich selbst. Dadurch wird Ihre App nicht als Batterieentladung betrachtet.

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.

Khemraj
quelle
WorkManager scheint der beste Weg zu sein, vorausgesetzt, die Arbeit muss nicht sofort ausgeführt werden. Es ist abwärtskompatibel zu API 14 und verwendet JobScheduler auf Geräten mit API 23+ und eine Kombination aus BroadcastReceiver + AlarmManager auf Geräten mit API 14-22
James Allen
Das Wichtigste an WorkManager ist, dass WorkManager für Aufgaben gedacht ist, die
aufgeschoben werden können
13

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

ContextCompat.startForegroundService(...)

und senden Sie eine Benachrichtigung, während Sie das Leck verarbeiten.

PK
quelle
1
Das OP sagte ausdrücklich, er wolle nicht als Vordergrund. Dies sollte als Kommentar oder als Teil einer vollständigeren Antwort erfolgen.
Ricardo A.
7

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:

@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)
        }
    }
}

und wenn ich Intent verarbeite, mache ich so etwas:

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
quelle
Ich mag deine Try-Catch-Lösung. Für mich ist es eine Lösung , weil manchmal context.startServiceim Hintergrund arbeitet - manchmal nicht - das sieht aus wie der einzigen beste Weg , sonst müssen Sie mehr Code in Ihrer Hauptklasse implementieren extending Applicationund implementing ActivityLifecycleCallbacksund zu verfolgen , ob die App im Vordergrund oder im Hintergrund sind und starten Sie Ihre Absicht entsprechend.
Pierre
Kann diese Ausnahme abgefangen werden?
thecr0w
5

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

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

Aktualisieren Sie bei Bedarf die Google Play-Dienste und die Google-Repositorys.

Dhaval Jivani
quelle
Dies beantwortet weder die Frage noch hat die Frage etwas mit Firebase zu tun. Es sollte als Kommentar gesetzt werden.
Ricardo A.
5

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:

  1. Die oben erwähnte Absicht sollte JobIntentServiceanstelle von verwendet werden IntentService.
  2. Die Klasse, die erweitert wird, JobIntentServicesollte die onHandleWork(@NonNull Intent intent)Methode - implementieren und unter der Methode stehen, die die onHandleWorkMethode aufruft :

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, xyz.class, 123, work);
    }
  3. Rufen Sie enqueueWork(Context, intent)aus der Klasse an, in der Ihre Absicht definiert ist.

    Beispielcode:

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

Die folgende Klasse hat zuvor die Service-Klasse erweitert

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-compatwird benötigt für JobIntentService- ich benutze 26.1.0 V.

  2. Am wichtigsten ist es, sicherzustellen, dass die Version der Firebase-Bibliotheken mindestens aktiviert ist 10.2.1. Ich hatte Probleme damit 10.2.0- wenn Sie welche haben!

  3. Ihr Manifest sollte die folgende Berechtigung für die Serviceklasse haben:

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

Hoffe das hilft.

Chitraju Chaithanya
quelle
4

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.

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.)
    }
}

Dann planen Sie, wann Sie es ausführen möchten.

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

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.

GESCHICHTE
quelle
3
Derzeit ist WorkManager noch Alpha.
Pzulw
3
05. März 2019 - WorkManager 1.0.0 stabile Version.
phnmnn
sollte WorkManager anstelle von interservice oder JobIntentService verwenden
sivaBE35
1
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!
Jemand irgendwo
Wenn Sie möchten, dass die Aufgabe sofort ausgeführt wird, sollten Sie einen Vordergrunddienst verwenden. Der Benutzer sieht eine Benachrichtigung und weiß, dass Sie arbeiten. Lesen Sie die Dokumente, wenn Sie Hilfe bei der Entscheidung benötigen, was verwendet werden soll. Sie haben eine ziemlich gute Anleitung für die Hintergrundverarbeitung. developer.android.com/guide/background
TALE
4

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

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());
   }
  }

Erstellen Sie dann die JobService-Klasse mit dem Namen 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;
  }
 }

Danach BroadCast Receiver-Klasse mit dem Namen 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);
 }
}

Aktualisieren Sie die Manifest-Datei mit dem Service- und Empfängerklassencode

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

Linke main_intent Launcher in der standardmäßig erstellten Datei mainActivity.java und Änderungen in der Datei MainActivity.java

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 !! Der Hintergrunddienst startet ohne Vordergrunddienst

Anshul1507
quelle
2

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:

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

Wenn über oder 8.0, dann verwenden Sie dies:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
ContextCompat.startForegroundService(context, serviceIntent );
iamfaizuddin
quelle
Es wird empfohlen, Vordergrunddienste nur in Fällen zu verwenden, in denen der Benutzer wissen muss, dass ein Dienst ausgeführt wird. Das typische Beispiel ist das Abspielen von Musik im Hintergrund. Es gibt andere Fälle, die sinnvoll sind, aber Sie sollten nicht einfach alle Ihre Dienste in Vordergrunddienste konvertieren. Erwägen Sie, Ihre Dienste für die Verwendung von WorkManager aus den Architekturkomponenten von Google zu konvertieren, wenn Sie nur im Hintergrund arbeiten müssen und sicher sein müssen, dass sie ausgeführt werden.
TALE
Für startForegroundService ist ansonsten eine Berechtigung erforderlich java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE. Fix bei stackoverflow.com/a/52382711/550471
Jemand irgendwo
1

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

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

Aktualisieren Sie bei Bedarf die Google Play-Dienste und die Google-Repositorys.

Aktualisieren:

 compile 'com.google.firebase:firebase-messaging:11.4.2'
Samir Mangroliya
quelle
0

Verwenden Sie startForegroundService()anstelle von startService() und vergessen Sie nicht, startForeground(1,new Notification());innerhalb von 5 Sekunden nach dem Start des Dienstes in Ihrem Dienst zu erstellen .

Arpit
quelle
2
Es scheint, dass new Notificaction () unter Android 8.1 nicht funktioniert. Sie sollten den Kanal für die Benachrichtigung erstellen: stackoverflow.com/a/47533338/1048087
Prizoff
0

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:

if (Build.VERSION.SDK_INT < 26 || getSystemService<PowerManager>()
        ?.isIgnoringBatteryOptimizations(packageName) != false) {
    startService(Intent(context, MyService::class.java))
} // else calling startService will result in crash
Mein Gott
quelle
1
Es ist keine gute Lösung, Ihre Benutzer zu bitten, Ihnen einen Freipass mit so viel Batterie wie möglich zu ermöglichen. Konvertieren Sie Ihren Code in eine batteriefreundlichere Lösung. Ihre Benutzer werden es Ihnen danken.
TALE
5
@TALE Nicht jeder Hintergrunddienst kann mit JobSchedulerund 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.
Mygod
-17

nicht in onStartCommand verwenden:

return START_NOT_STICKY

Ändern Sie es einfach in:

return START_STICKY

und es wird funktionieren

Omar Othman
quelle