TP 4 Intent, IntentFilter et Receiver

Thème : usage du patron publish/subscribe

Réaliser une application permettant de démarrer et d'arrêter une horloge et d'enregistrer 3 receveurs locaux.

Ci-dessous, une copie d'écran au bout de 4 secondes, à chaque seconde écoulée un affichage du compteur de secondes est réalisé par les trois receveurs locaux

 

Question 1 ) Installer 3 receveurs locaux, tous sont souscripteurs de l'action "time_action_tic"  Ticker.TIME_ACTION_TIC

Au click sur start ticker, l'horloge démarre et délivre une notification "time.action.tic" toutes les secondes, tous les receveurs reçoivent cette notification et affichent la valeur reçue dans la zone de texte associée, au click sur stop ticker l'horloge est suspendue. Un nouveau click sur start timer permettra de reprendre le compte. Un click sur finish arrête l'horloge et termine l'activité.

Notez que pour ce tp, l'horloge est indépendante du cycle de vie de l'activité principale, i.e. quitter l'activité alors que l'horloge est active n'a aucune incidence sur celle-ci. Par exemple après une rotation de l'écran, (ce qui induit une destruction de l'activité), l'horloge continue l'incrément du compteur et s'exécute en "tache de fond". Deux méthodes assurant la persistance de l'horloge sont fournies, notez .

public class MainActivity extends Activity {
  private final String TAG = this.getClass().getSimpleName();
  private final boolean I = true;
  private Ticker ticker;
  private static long count;
// ...
private class Ticker extends Thread implements Serializable{  // ligne à commenter en q3
// private class Ticker extends Thread implements Parcelable // ligne à décommenter en q3
  public static final String TIME_ACTION_TIC = "time_action_tic";
  public static final String COUNT_EXTRA = "count";
  private Context context;


  public Ticker(Context context){
    this.context = context;
  }
  public void startTicker(){
    this.start();
  }
  public void stopTicker(){
    this.interrupt();
  }
  public void run(){
    Intent intent = new Intent();
    intent.setAction(TIME_ACTION_TIC);
    while(!isInterrupted()){
        SystemClock.sleep(1000L);
        count++;
        intent.putExtra(Ticker.COUNT_EXTRA, count);
        context.sendBroadcast(intent);
        //if(count<=10)                                  // à décommenter pour q2
            context.sendBroadcast(intent);
        //else                                           // à décommenter pour q2
            //context.sendOrderedBroadcast(intent,null); // à décommenter pour q2

    }
  }
}

private Receiver r1,r2,r3;
@Override
public void onResume(){
  super.onResume();
  if(I)Log.i(TAG,"onResume");

  IntentFilter filter = new IntentFilter();
  filter.addAction(Ticker.TIME_ACTION_TIC);
  filter.setPriority(100);
  registerReceiver(r1, filter);
  filter.setPriority(200);
  registerReceiver(r2, filter);
  filter.setPriority(300);
  registerReceiver(r3, filter);
}
public void onSaveInstanceState(Bundle outState){
  if(I)Log.i(TAG,"onSaveInstanceState");
  outState.putSerializable("ticker", ticker); // à commenter pour q3
  // outState.putParcelable("ticker",ticker); // demandé en q3
}

public void onRestoreInstanceState(Bundle outState){
  if(I)Log.i(TAG,"onRestoreInstanceState");
  ticker = (Ticker)outState.getSerializable("ticker"); // à commenter pour q3
  // ticker = (Ticker)outState.getParcelable("ticker"); // demandé en q3
  // suivie d'une mise à jour de l'IHM
}
 

Proposez une activité et son interface (3 boutons, 3 zones de texte)  et ses 3 receveurs. Veillez à ce qu'il n'y ait qu'un seul thread horloge à la fois.

 

Question 2 ) Le receveur r2 interrompt la notification

    Les trois receveurs r1,r2 et r3 ont respectivement une priorité de 100, 200 et 300, dès que le compte atteint la valeur de 20 le receveur r2 interrompt la propagation de la notification(cf. isOrderedBroadcast et abortBroadcast).

Question) Complétez l'activité en installant cette fonctionnalité pour le receveur r2
Ci-dessous une copie d'écran après 32 secondes, r1 ne doit plus être notifié

 

Question 3 ) Persistance avec l'implémentation de Parcelable , lire aussi Parcelable vs Serializable

    La persistance à la question 1 est assurée par la classique "serialisation java" cf. implements Serializable, remplacez l'implémentation de cette interface par ce qui est proposé, voire recommandé, par Android : implements Parcelable, la sérialisation est alors à votre charge...

 

Proposition : lors de la sauvegarde seule la référence associée à l'attribut ticker devient persistante, ci-dessous un extrait de la classe Ticker

 public void writeToParcel(Parcel dest, int flags){
   dest.writeValue(this); // sauvegarde de la référence
 }
 private Ticker(Parcel in){
   MainActivity.this.ticker = (Ticker)in.readValue(MainActivity.class.getClassLoader());
 }