web-dev-qa-db-fra.com

Custom JobIntentService onHandleWork non appelé

Je mettais récemment à jour une application sur laquelle je travaille pour gérer les notifications de Push à l'aide d'un JobIntentService au lieu d'un IntentService normal, car il semble que ce soit la bonne façon de gérer cela sur les appareils pré-Lollipop et après. Je suis en attente de travail en tant que tel:

enqueueWork(context, MyJobServiceExtension.class, JOB_ID, work);

Ceci est la déclaration du manifeste:

<service Android:name="com.example.MyJobServiceExtension" Android:permission="Android.permission.BIND_JOB_SERVICE" Android:exported="true" tools:node="replace">

Je ne vois jamais aucun rappel dans onHandleWork ni aucun journal d'erreur dans mon logcat. Quelqu'un at-il intégré avec succès cela qui pourrait aider?

Mise à jour: j'ai testé cela sur un appareil de niveau 21 api et cela fonctionnait .. mais cela ne semble pas se faire appeler sur mon appareil Android O pixel XL .. Vous avez une idée du pourquoi?

Mise à jour n ° 2: De plus, il semble que le processus onCreate d'Intentservice soit appelé, mais aucune des autres méthodes de cycle de vie (y compris onHandleWork). Quelqu'un at-il rencontré cela non plus?

22
Eshaan

J'ai eu le même problème après la mise à niveau d'IntentService vers JobIntentService. Assurez-vous de supprimer cette méthode de votre ancienne implémentation:

@Override
public IBinder onBind(Intent intent) {
    return null;
}

Pour moi, cela a résolu le problème, et maintenant cela fonctionne à la fois avant et après Oreo.

48
agirardello

J'ai eu le même problème (fonctionne bien sur un appareil pré-O, aucune indication de ce qui se passe sur un appareil O). Aujourd'hui, j'ai réessayé avec exactement le même code qu'hier, maintenant cela fonctionne - la seule différence est que j'ai redémarré l'appareil entre les deux.

Ma théorie actuelle est que ma configuration initiale n'a pas fonctionné. mon actuel et le redéploiement du nouveau code ne supprime pas l’état cassé du JobScheduler; un redémarrage ou une désinstallation/réinstallation du paquet fait.

La configuration qui fonctionne maintenant (migrée depuis un ancien IntentService):

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

et commencer par 

Intent intent = new Intent(); 
intent.putExtra(EXTRA_NAME, extraValue);
JobIntentService.enqueueWork(context, MyJobIntentService.class, FIXED_JOB_ID, intent);

Notez que l’intention est pas une intention explicite (c’est-à-dire que le NomComposant n’est pas défini).

6
Jule

Si vous avez remplacé la méthode onCreate dans votre JobIntentService, cela empêchera l'appel de onHandleWork.

J'ai converti ma Service en JobIntentService et ce n'est qu'après avoir supprimé la méthode onCreate que cela a fonctionné.

2

C'est ce qui a fonctionné pour moi,

Supprimez la substitution IBind comme suggéré par @agirardello

et ajouté le suivant

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

Je ne sais pas pourquoi cela a fonctionné.

2
Sanket Berde

J'ai rencontré un problème quelque peu similaire avec onHandleWork n'étant pas appelé la deuxième fois après avoir migré de Service à JobIntentService. Les journaux indiquaient que enqueueWork était appelé mais onHandleWork n'exécutait que le premier et semblait bloqué.

Après quelques recherches et journalisation supplémentaires, j'ai découvert que la différence était que, dans un scénario "bloqué", il y avait JobIntentService#onDestroy même si toutes les opérations de onHandleWork avaient été effectuées et semblaient se terminer.

Il s’est avéré que le coupable était bindService appel de ce service au cycle de vie de l’activité qui empêchait la suppression du premier emploi et, pour une raison quelconque, appelait enqueueWork après que cette condition causait le blocage et la non-exécution du service. l'un des suivants onHandleWork à nouveau.

Donc, voici un journal incorrect des événements dans lesquels JobIntentService semblera être bloqué après le premier appel ne déclenchant jamais onHandleWork:

enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
enqueueWork -> second call
enqueueWork -> third call

Et voici le journal correct des événements avec JobIntentService fonctionnant correctement après la suppression de bindService appel:

enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy (service is destroyed after the job is finished)
enqueueWork -> second call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy
enqueueWork -> third call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy

J'espère que cela sera utile à quelqu'un.

1
git pull origin

Pour tous ceux qui ne pouvaient pas résoudre le problème avec les autres réponses:

Essayez d’utiliser différents JOB_IDs à chaque fois enqueueWork est appelé. Si un travail précédent n'est pas terminé, le service risque de rester bloqué (problème similaire à celui décrit par l'utilisateur "git pull Origin") et un nouveau travail portant un identifiant différent peut résoudre ce problème.

0

J'ai finalement trouvé la solution à ce problème LoL

Si vous remplacez la méthode "onBind" et que vous appelez le travail à l'aide de la méthode "enqueueWork", vous devez renvoyer la liaison au moteur du travail en procédant comme suit:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        [... Do What You Want ... ]
        return super.onBind(intent);
    }

Donc, en retournant l'IBinder de la méthode "super.onBind", vous devez donc l'utiliser pour lier le JobIntentService.

Si vous souhaitez lier et renvoyer un autre classeur, vous pouvez le faire:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        IBinder binder = initSynchronizer();
        new Thread(
                () -> onHandleWork(intent)
            ).start();
        return binder;
    }

Donc, en commençant par "onHandleWork" dans un autre thread. De cette façon, vous pouvez utiliser:

"bindService (....., JobIntentService.BIND_AUTO_CREATE);"

pour vous lier au service et renvoyer votre classeur. Quoi qu'il en soit, lorsque vous dissociez le service, celui-ci sera supprimé et s'il fonctionne toujours, vous ne pourrez plus vous y associer car le service a été supprimé, mais le fil dans lequel "onHandleWork" est toujours en cours d'exécution ...

Je vous suggère donc d’utiliser cette version uniquement si vous devez effectuer une tâche qui doit communiquer avec l’activité jusqu’à ce qu’elle soit active et qui doit continuer à fonctionner si l’activité est supprimée (sans possibilité de relier à nouveau le service jobService, mais uniquement à commencer un nouveau ...)

Pour ne pas tuer le service après la suppression de la liaison, vous devez le démarrer à "l'avant-plan", le "stopForeground" dans le "onDestroy". De cette façon, votre service reste actif uniquement pour le thread qui gère les méthodes "onHandleWork".

J'espère que Google va résoudre ce problème * rapide, j'ai converti tous les anciens "Service" et "IntentService" en nouveaux emplois mais ... ils fonctionnent vraiment moins bien qu'avant!

Aurevoir un code Nice;)

0
Z3R0

Essayez simplement de quitter et d’exécuter à nouveau Android Studio. Ensuite, testez à nouveau . Dans mon cas, la version d'Android Studio est la v 3.3.1 . Consultez l'exemple de code qui fonctionne correctement.

public class CustomizedIntentService extends JobIntentService
{
    public static final String MY_ACTION = "action.SOME_ACTION";
    private static final int MY_JOB_INTENT_SERVICE_ID = 500;

    public CustomizedIntentService() {
    }

    // Helper Methods to start this JobIntentService.
    public static void enqueueJobAction(Context context, String action) {
        Intent intent = new Intent(context, CustomizedIntentService.class);
        intent.setAction(MY_ACTION);

        enqueueWork(context, CustomizedIntentService.class, MY_JOB_INTENT_SERVICE_ID, intent);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        String action = intent.getAction();

        // action will be "action.SOME_ACTION"
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public boolean onStopCurrentWork() {
        return super.onStopCurrentWork();
    }
}

// lancez JobIntentService selon vos besoins.

CustomizedIntentService.enqueueJobAction (context, CustomizedIntentService.MY_ACTION);

0
Jay

Pour moi, je commençais toujours le service après enqueueWork et me donnais une erreur à cause de cela.

0
Tarun Goel

Aussi drôle que cela puisse paraître, j'ai eu un problème similaire parce que je n'ai pas changé le nom de la classe en son propre nom dans enqueueWork () parce que j'ai copié le code de l'une de mes classes. Après avoir effectué la mise à jour, il a commencé à fonctionner correctement.

0
leeCoder