Jump to content

Archived

This topic is now archived and is closed to further replies.

Jorodan

[Bonnes pratiques] Un service avec une action récurrente

Recommended Posts

Amis HardCodeurs, j'ai besoin de votre avis.

Je commence une liste de Tutoriels "Bonnes pratiques" dans http://wiki.frandroid.com/wiki/D%C3%A9veloppement_Android#Tutoriels_par_cat.C3.A9gories

Ma première idée est le service récurrent. J'ai besoin de votre avis pour écrire un truc bon.

Voici l'implémentation que je propose :

package org.frandroid.tutoriels;


import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

public class MonService extends Service {

   private LocalBinder binder = new LocalBinder();
   private Handler mHandler = new Handler();
   private long frequency = 60 * 1000 * 2;

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

   @Override
   public void onStart(Intent intent, int startId) {
       super.onStart(intent, startId);
       mHandler.removeCallbacks(mActionRecurrente);
       mHandler.postDelayed(mActionRecurrente, 1);
   }

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

   public class LocalBinder extends Binder {
       MonService getService() {
           return MonService.this;
       }
   }


   private Runnable mActionRecurrente = new Runnable() {
       public void run() {
           Log.d("Action", "Je suis récurrent toutes les 2 minutes.");

           mHandler.postDelayed(this, frequency);
       }
   };
}

Comme vous voyez, j'utilise une retard sur un handler plutôt que par le AlarmManager comme conseillé ici : http://android-developers.blogspot.com/2007/11/stitch-in-time.html

Pensez vous que c'est une "bonne pratique" ???

(ps : je vous invite à faire pleins de tutos comme ca avec moi).

Share this post


Link to post
Share on other sites

nan, l'alarm manager est plus adapté

si ton appli est tuée, je crois que ton handler est détruit (contrairement à alarm)

Share this post


Link to post
Share on other sites

http://developer.android.com/reference/android/app/AlarmManager.html

Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

donc ça dépend de ce que tu veux faire :P

si c'est un texte qui clignote, Handler est plus adapté

si tu dois faire une requete http à intervalle régulier, AlarmManager est plus adéquat

Share this post


Link to post
Share on other sites

Ok ! Je vais modifier mon code en conséquence !

Je reviens vers vous pour proposer une nouvelle version :)

Share this post


Link to post
Share on other sites

et si tu décides d'arreter tes évènements récurrents, il faut pour cela :

- cancel dans l'AlarmManager

- ne pas oublier de stop le service

Share this post


Link to post
Share on other sites

Bonjour Jorandan,

Effectivement l'utilisation d'un couple Service/Handler n'est pas réellement adapter dans ton exemple. Le couple AlarmManager/BrodcastReceiver me semble une meilleur alternative.

Un site "in english" pas mal pour ce type de problématique est http://www.androidguys.com. Il y'a par exemple ce billet sur le sujet ici.

Bon courage,

ichpa

Share this post


Link to post
Share on other sites

Nouvelle proposition !

Qu'en pensez vous ?

package org.frandroid.tutoriels;


import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

public class MonService extends Service {

   private LocalBinder binder = new LocalBinder();
   private Handler mHandler = new Handler();
   private long frequency = 60 * 1000 * 2;
   private static boolean started = false;

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

   @Override
   public void onStart(Intent intent, int startId) {
       super.onStart(intent, startId);
       MesActions
   }

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

   public class LocalBinder extends Binder {
       MonService getService() {
           return MonService.this;
       }
   }


   public final static void scheduleService(Context context) {
           if (!started) {
               Intent newIntent = new Intent(context, MonService.class);
               PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, newIntent, 0);

               AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
               am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, frequency, pendingIntent);
           }
           started = true;
   }

   public final static void unscheduleService(Context context) {
           if (started) {
               Intent newIntent = new Intent(context, MonService.class);
               PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, newIntent, 0);
                   AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
               am.cancel(pendingIntent);
           }
           started = false;
           }

}

L'intéret vient des deux méthodes statiques pour lancer le service par l'Alarm Manager

Share this post


Link to post
Share on other sites

Pour moi, il y a plusieurs choses qui ne "vont pas" :P

Tu utilises PendingIntent.getBroadcast() pour démarrer un service :P (sauf si je me trompe)

Tu oublies de "stop" ton service dans unscheduleService()

Ce qui veut dire que ton service continue de "tourner" :P

Que se passe t-il quand un service est lancé?

L'appli reste "chargée", et le système ne peut pas la dégager.

Si on la tue via un TaskKiller, elle se relance.

Comme tu utilises un AlarmManager, il n'est pas nécessaire que l'application continue de "tourner".

Et le fait que tu utilises un service oblige le système à garder ton appli active.

Mon conseil :

- Garde l'AlarmManager

- Utilise PendingIntent.getBroadcast() pour lancer un broadcast (et non démarrer un service) à intervalle régulier

Par contre, ça oblige à déclarer un BroadcastReceiver dans ton manifest.xml (car ton appli peut ne pas être lancée au moment du Broadcast)

Share this post


Link to post
Share on other sites





×
×
  • Create New...