web-dev-qa-db-fra.com

Non autorisé à démarrer le service Intention - Android Oreo

J'utilise actuellement la fonction startWakefulService qui se bloque à Oreo. Je me rends compte que je dois soit basculer sur startForegroundService () et utiliser un service de premier plan, soit basculer sur JobIntentService mais en fonction de mon code ci-dessous, je ne sais pas quoi faire. (Désolé je suis un novice Android). Tous les points dans la bonne direction seront grandement appréciés.

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

C’est l’erreur actuelle que j’obtiens lors de l’exécution sur Android 8.x

Fatal Exception: Java.lang.RuntimeException Impossible de démarrer le destinataire com.heyjude.heyjudeapp.gcm.GcmBroadcastReceiver: Java.lang.IllegalStateException: non autorisé à démarrer le service Intent {act = com.google.Android.c2dm.intent.RECEIVE flg = 0x1000010 pkg = com.app.app cmp = com.app.app/.gcm.GCMIntentService (comporte des extras)}: l'application est en arrière-plan uid UidRecord {f602fba u0a114 Processus inactif RCVR: 1 seq (0,0,0)}

4
Marcus Smith

J'éprouve le même comportement.

Pourquoi ce problème se produit?

En raison du nouveau Background Execution Limits d’Android 8, vous devriez pas démarrer des services de fond.

Comment je l'ai corrigé

Migrez votre GCMIntetService en JobIntentService au lieu de IntentService

Veuillez suivre ces étapes: 1) Ajoutez l’autorisation BIND_JOB_SERVICE à votre service:

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

2) Dans votre GCMIntentService, au lieu d'étendre la IntentService, utilisez Android.support.v4.app.JobIntentService et remplacez onHandleWork Puis supprimez la override dans vous 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
    }
}

Enfin, dans votre GCMBroadcastReceiver, mettez en file d'attente votre GCMIntentService

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

Cette mise en œuvre fonctionne pour moi après la mise à jour de notre cible sdk à 27 et j’espère que cela fonctionnera pour vous. 

9
Abdulmoiz Esmail

Basé sur la documentation :

À partir d'Android O, les restrictions de vérification des antécédents rendent ce numéro de classe__. plus généralement utile. (Il n’est généralement pas prudent de démarrer un service Dès la réception d’une émission, car vous n’avez aucune garantie Que votre application est au premier plan à ce stade et donc autorisée à Le faire. .) Au lieu de cela, les développeurs doivent utiliser Android.app.job.JobScheduler à planifier un travail, et cela ne nécessite pas que l'application tienne un sillage verrouiller en même temps (le système se chargera de maintenir un verrou de réveil pour le travail).

La seule alternative est de démarrer ForeGroundService ou d'utiliser JobScheduler/JobIntentService

Vous pouvez démarrer le service de premier plan comme suit:

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

Vous devez également appeler startService() à partir de votre classe de service et afficher une notification. Vous pouvez suivre ma réponse sur ceci SO pour les détails de la mise en œuvre.

1
Sagar