wake-up-neo.com

Dienst darf nicht gestartet werden Intent - Android Oreo

Ich verwende derzeit die startWakefulService-Funktion, die in Oreo abstürzt. Ich erkenne, dass ich entweder zu startForegroundService () wechseln und einen Vordergrunddienst verwenden muss oder zu JobIntentService wechseln muss, aber aufgrund meines Codes unten bin ich nicht sicher, was ich tun soll. (Sorry, ich bin ein Android-Neuling). Alle Punkte in die richtige Richtung werden sehr geschätzt.

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    // Explicitly specify that GCMIntentService will handle the intent.
    ComponentName comp = new ComponentName(context.getPackageName(), GCMIntentService.class.getName());
    // Start the service, keeping the device awake while it is launching.
    startWakefulService(context, (intent.setComponent(comp)));

    setResultCode(Activity.RESULT_OK);
}
}

Dies ist der aktuelle Fehler, den ich bekomme, wenn er auf Android 8.x läuft

Schwerwiegende Ausnahme: Java.lang.RuntimeException Empfänger com.heyjude.heyjudeapp.gcm.GcmBroadcastReceiver kann nicht gestartet werden: Java.lang.IllegalStateException: Dienst darf nicht gestartet werden cmp = com.app.app/.gcm.GCMIntentService (hat Extras)}: App befindet sich im Hintergrund.

4
Marcus Smith

Ich erlebe das gleiche Verhalten.

Warum tritt dieses Problem auf?

Aufgrund der neuen Background Execution Limits von Android 8 sollten Sie Dienst-Hintergrund nicht starten.

Wie ich das Problem behoben habe

Migrieren Sie Ihre GCMIntetService nach JobIntentService anstelle von IntentService

Bitte befolgen Sie diese Schritte: 1) Fügen Sie Ihrem Dienst die Berechtigung BIND_JOB_SERVICE hinzu:

<service Android:name=".service.GCMIntentService"
        Android:exported="false"
        Android:permission="Android.permission.BIND_JOB_SERVICE"/>

2) Verwenden Sie in Ihrer GCMIntentService anstelle der IntentServiceAndroid.support.v4.app.JobIntentService und überschreiben Sie onHandleWork Entfernen Sie dann die override in Ihrer onHandleIntent.

public class GCMIntentService extends JobIntentService {

    // Service unique ID
    static final int SERVICE_JOB_ID = 50;

    // Enqueuing work in to this service.
    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, GCMIntentService.class, SERVICE_JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        onHandleIntent(intent);
    }

    private void onHandleIntent(Intent intent) {
        //Handling of notification goes here
    }
}

Schliessen Sie schließlich in Ihrer GCMBroadcastReceiver Ihre GCMIntentService ein. 

public class GCMBroadcastReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                GCMIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        // startWakefulService(context, (intent.setComponent(comp)));

        //setResultCode(Activity.RESULT_OK);

        GCMIntentService.enqueueWork(context, (intent.setComponent(comp)));
    }
}

Diese Implementierung funktioniert für mich, nachdem wir unser Ziel-SDK auf 27 aktualisiert haben, und ich hoffe, es funktioniert für Sie. 

9

Basierend auf der Dokumentation :

Ab Android O machen Einschränkungen bei der Hintergrundprüfung diese Klasse zu Nr länger allgemein nützlich. (Es ist im Allgemeinen nicht sicher, einen Dienst .__ vom Empfang einer Sendung aus zu starten, da Sie keine Zusicherung haben , Dass sich Ihre App zu diesem Zeitpunkt im Vordergrund befindet und dies daher zulässig ist ) .) Stattdessen sollten Entwickler Android.app.job.JobScheduler für .__ verwenden. Planen Sie einen Job, und dies erfordert nicht, dass die App eine Reaktivierung aufhält sperren Sie dabei (das System sorgt dafür, dass eine Wecksperre für den Job gehalten wird).

Die einzige Alternative ist, einen ForeGroundService zu starten oder JobScheduler/JobIntentService zu verwenden

Sie können den Vordergrunddienst wie folgt starten:

@Override
public void onReceive(Context context, Intent intent) {

    // Explicitly specify that GCMIntentService will handle the intent.
    ComponentName comp = new ComponentName(context.getPackageName(), GCMIntentService.class.getName());
    // Start the service, keeping the device awake while it is launching.
    ContextCompat.startForegroundService(context,intent.setComponent(comp));
    ...
}

Sie müssen auch startService() von Ihrer Service-Klasse aus aufrufen und eine Benachrichtigung anzeigen. Sie können meine Antwort auf dieser SO für Implementierungsdetails verfolgen.

1
Sagar