web-dev-qa-db-fra.com

Job Scheduler vs Background Service

J'ai une application qui a une fonctionnalité A qui devrait fonctionner en arrière-plan chaque minute. La caractéristique A est que l'application doit se connecter à une base de données, lire certaines données, puis obtenir l'emplacement actuel de l'appareil et, en fonction de celles-ci, vérifier une condition. Si la condition est vraie, elle doit envoyer une notification à la barre d'état pour que l'utilisateur puisse clique sur la notification, l'interface utilisateur de l'application s'affiche et il se passe quelque chose.
Cette tâche en arrière-plan devrait s’exécuter de manière permanente toutes les minutes, que l’application soit utilisée, fermée ou interrompue (comme Facebook ou Whatsapp qui affiche des notifications, qu’elles soient ou non dans la pile des applications).
Maintenant, j'ai cherché et trouvé que Android offre Job Scheduler , Service en arrière-plan , Gestionnaire d'alarmes et Gestionnaires .
Mais plus je lis à leur sujet, plus les déclarations me paraissent contradictoires.

  1. À propos des gestionnaires J'ai lu qu'ils n'existaient pas pour de longs délais et qu'ils seraient résiliés après le redémarrage du système. Donc, ils ne seront pas appropriés pour ma tâche.
  2. Mais AlarmManager semble être un bon candidat au problème car, une fois autorisé, il existe même après le redémarrage du système et peut réexécuter l'application. Mais dans le Documentation Android , le gestionnaire d’alarmes est destiné à être utilisé pour des tâches devant être exécutées à une heure précise (comme le réveil). Mais ma tâche doit être exécutée chaque minute.
  3. Ensuite, il y a le service d'arrière-plan. C’est davantage pour les tâches comme le téléchargement en arrière-plan que j'ai lu et non pour faire quelque chose que j'ai expliqué.
  4. JobScheduler ne semble pas être destiné à une tâche qui doit être effectuée de manière permanente, mais à des tâches qui répondent à une contrainte spécifique telle que la veille, ou à l'absence de réseau ... Alors, lequel de ceux-ci (ou d'autres s'ils existent) recommandez-vous d'utiliser pour la tâche que j'ai expliqué dans la première partie
28
Code Pope

J'ai une application qui a une fonctionnalité A qui devrait fonctionner en arrière-plan chaque minute.

Cela ne se produira pas sur des centaines de millions de périphériques Android, ceux qui fonctionnent Android 6.0 et versions supérieures, en raison du mode Doze (et éventuellement de la veille de l'application, sur le reste de votre application).

Mais AlarmManager semble être un bon candidat au problème car, une fois autorisé, ils existent même après le redémarrage du système.

Non, ils ne pas. Vous devez replanifier toutes les alarmes planifiées avec AlarmManager après un redémarrage.

alarm Manager est destiné à être utilisé pour des tâches devant être exécutées à une heure précise

AlarmManager supporte les options de répétition.

C’est davantage pour les tâches comme le téléchargement en arrière-plan que j'ai lu et non pour faire quelque chose que j'ai expliqué.

Un Service sera essentiel pour la solution que vous utiliserez.

JobScheduler ne semble pas être destiné à une tâche qui doit être effectuée de manière permanente, mais à des tâches qui remplissent une contrainte spécifique telle que la veille, ou l'absence de réseau.

JobScheduler, comme AlarmManager, prend en charge les tâches répétitives.

Alors, lequel de ceux-ci (ou d’autres s’ils existent) recommandez-vous d’utiliser pour la tâche que j’ai expliquée dans la première partie

N'utilisez aucun d'entre eux, car vous ne pouvez pas exécuter les choses toutes les minutes sur Android 6.0+ une fois que l'appareil passe en mode Doze, ce qui aura lieu moins d'une heure après la mise hors tension de l'écran. L'application n'a besoin que d'un travail de fond quelques fois par jour, ou ne vous fatiguez pas à écrire l'application.

28
CommonsWare

Vous pouvez utiliser l'API moderne JobScheduler introduite dans Android 5.0 si votre minSdkVersion = 21.

En outre, il existe https://github.com/firebase/firebase-jobdispatcher-Android qui nécessite l'installation de Google Play minSdkVersion = 9

Mais je recommande d’utiliser cette bibliothèque https://github.com/evernote/Android-job où, en fonction de la Android, soit la JobScheduler , GcmNetworkManager ou AlarmManager sera utilisé.

Avec ces API, vous pouvez planifier votre travail et exécuter un service décrivant la tâche.

[~ # ~] met à jour [~ # ~] Maintenant, il est préférable d'utiliser new WorkManager ( docs =). Android-job sera bientôt déconseillé

12
nastasina

Tout d'abord, un JobService est un service. Un service en arrière-plan est ambigu, laissez-moi deviner que vous parlez d'un service qui s'exécute dans le fil de l'arrière-plan. Job Service s'exécute sur le thread d'interface utilisateur, mais vous pouvez créer un objet de tâche asynchrone pour le faire fonctionner en arrière-plan.

D'après votre question, JobService n'est pas la solution. Ce que je suggère est:

  1. Vous pouvez créer une classe qui étend IntentService (cela s'exécute sur le thread en arrière-plan) dans la méthode onDestroy de cette classe, envoyer une diffusion et faire en sorte que la diffusion redémarre le service.

     @onDestroy(){
     Intent broadcastIntent = new 
     Intent("com.example.myapp.serviceRestarted");
     sendBroadcast(broadcastIntent);}
    
  2. Créer une classe qui étend le récepteur de diffusion

     public class RestartServiceReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
     context.startService(new Intent(context, 
     MyService.class));
    } 
    }
    
    1. Dans votre manifeste, inscrivez votre service et votre destinataire
<receiver
            Android:name=".RestartServiceReceiver"
            Android:enabled="true"
            Android:exported="true">
            <intent-filter>
                <action Android:name="com.example.myapp.serviceRestarted" />
                <action Android:name="Android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

La permission de démarrage permet au récepteur de s'appeler, le système a fini de démarrer et une fois que le récepteur est appelé, le service est appelé à nouveau.

6
Idee

Selon this et un autre lien dans le commentaire 1 ci-dessous

Vous devez utiliser AlarmManager pour votre tâche.

Si vous devez définir des alarmes qui se déclenchent à Doze, utilisez:

 setAndAllowWhileIdle() or setExactAndAllowWhileIdle().

Pour une explication complète facile à comprendre des différentes façons de faire des choses en arrière-plan, lisez: https://www.bignerdranch.com/blog/choosing-the-right-background-scheduler-in-Android/

Bonne chance!

2
Mena

Dans les versions précédentes d'Android, les utilisateurs utilisaient Handler ou des services d'arrière-plan à cette fin. Après un certain temps, ils ont annoncé la classe de gestionnaire d’alarmes pour les travaux permanents et planifiés.

Whatsapp, Facebook ou certaines applications de médias sociaux utilisent principalement la messagerie en nuage Google pour les notifications, ce qui ne vous est pas utile.

Je vous recommanderai d'utiliser le gestionnaire d'alarmes pour cela. Après la version KitKat (4.2), le système d'exploitation bloque le gestionnaire d'arrière-plan pour une meilleure utilisation de la batterie.

Les services d'arrière-plan sont principalement utilisés pour le téléchargement d'images ou pour certains processus lourds comportant une heure de fin. Lorsque vous envoyez une vidéo à votre ami sur Whatsapp, le processus d'arrière-plan démarre et la télécharge sur le serveur principal.

Je ne suis pas sûr de l’application de JobScheduler api pour la prise en charge des anciennes versions du support, mais c’est aussi bon que Alarm Manager.

1
Abdullah Tellioglu

vous pouvez le faire à l'aide du service, avec return start_sticky dans "START_STICKY indique au système d'exploitation de recréer le service lorsqu'il dispose de suffisamment de mémoire et appelle à nouveau onStartCommand () avec une intention nulle. START_NOT_STICKY demande au système de ne pas recréer le service. est également un troisième code START_REDELIVER_INTENT qui indique au système d'exploitation de recréer le service et de renvoyer la même intention à onStartCommand () "

et réglez un TIMER avec une période de 1 minute et exécutez votre code.

De même, si vous souhaitez redémarrer le service lorsque l'utilisateur l'arrête de force, vous pouvez le faire "comme les réponses précédentes".

  1. Vous pouvez créer une classe qui étend IntentService (celle-ci s'exécute sur le thread en arrière-plan) dans la méthode onDestroy de cette classe, envoyer une diffusion et faire en sorte que la diffusion redémarre le service.

    @onDestroy(){
        Intent broadcastIntent = new Intent("com.example.myapp.serviceRestarted");
        sendBroadcast(broadcastIntent);
    }
    
  2. Créer une classe qui étend le récepteur de diffusion

    public class RestartServiceReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            context.startService(new Intent(context, MyService.class));
        } 
    }
    
  3. Enregistrez votre service et votre destinataire dans votre manifeste.

    <receiver
       Android:name=".RestartServiceReceiver"
        Android:enabled="true"
        Android:exported="true">
        <intent-filter>
            <action Android:name="com.example.myapp.serviceRestarted" />
            <action Android:name="Android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

Vous pouvez également utiliser AlarmManager. Si vous devez définir des alarmes qui se déclenchent à Doze, utilisez:

setAndAllowWhileIdle () ou setExactAndAllowWhileIdle ().

réglez-le sur "l'heure actuelle en secondes + 60 s" pour pouvoir le définir à la minute suivante.

et exécutez votre code et, dans le dernier cas, réinitialisez AlarmManager à la minute suivante.

En outre, vous pouvez démarrer votre service ou AlarmManager après le redémarrage du périphérique. Utilisez simplement un brodcastReciever lorsque "RECEIVE_BOOT_COMPLETED".

et mettre cette permission:

<uses-permission Android:name="Android.permission.RECEIVE_BOOT_COMPLETED" />
0
Momen Zaqout