Accueil / Articles PiApplications. / La plate-forme Android

Les classes à la base de la dynamique des applications Android.

Maintenant que nous avons vu comment les intentions permettaient une forme d'IPC (Inter Processes Communication), découvrons les quatre composants principaux d'Android. Même si une application Android ne contient pas les quatre, elle en comporte au moins un.

L'activité.

Une application qui dispose d'une interface graphique dispose d'au moins une activité (class Activity). L'activité joue le rôle de contrôleur du modèle MVC. Elle est chargée d'afficher le contenu du modèle et de transmettre les actions de l'utilisateur. Le code de base d'une classe décrivant une activité est le suivant :

import android.app.Activity;
import android.os.Bundle;

public class MyActivity extends Activity
{
  @Override
  public void onCreate(Bundle bndSavedInstanceState)
  {
    super.onCreate(bndSavedInstanceState);
    setContentView(R.layout.main);
  }
}

Le rôle principal d'une activité est d'afficher les contrôles décrits dans une vue (en général un "layout" XML qui agit comme descripteur de la vue). Le passage d'une activité à une autre se fait au moyen d'une des méthodes startActivity ou startActivityForResult. Un des arguments de la méthode est une intention. Android 3.0 a introduit une nouvelle classe de gestion des interfaces graphiques : les fragments (classe Fragment). Les fragments sont relatifs aux activités.

Cycle de vie d'une activité.

Le service.

Lorsqu'une application est destinée à avoir un long cycle de vie et particulièrement si elle doit fonctionner lorsqu'elle n'est pas à l'avant-plan, il est préférable voire indispensable de la faire reposer sur un service. Toutefois, il faut garder à l'esprit qu'un service n'a pas de "vue".

Voici un exemple de code basique pour lancer un service sur un thread dédié :

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

public class MyService extends Service implements Runnable
{
  public static final String TAG = "myService";
  private int _iCounter = 0;

  @Override
  protected void onCreate()
  {
    super.onCreate();
    Thread thr = new Thread(this);
    thr.start();
  }

  public void run()
  {
    while (true)
    {
      try
      {
        // Trace dans le moniteur toute les 10 secondes
        Log.i(tag,"Lancement de myService : N° " + _iCounter++);
        Thread.sleep(10000);
      }
      catch (Exception exc)
      {
        Log.e(TAG, exc.getMessage());
      }
    }
  }

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

Le récepteur de diffusion.

Un récepteur de diffusion est mis en oeuvre via la classe BroadcastReceiver. Il permet à une application de s'enregistrer comme un gestionnaire capable de répondre à certains évènements.

Pour s'enregistrer, l'application peut le faire via l'élément <receiver> du fichier Manifest.xml ou via la méthode registerReceiver de la classe Context.

A l'instar d'un service, un récepteur de diffusion n'a pas de "vue". De plus, le code de al méthode onReceive ne doit pas faire de supposition sur les opérations persistantes ou de longue durée. C'est pourquoi il est recommandé lorsque le code de cette méthode n'est pas trivial, d'y placer une requête d'exécution d'un service. Là encore les intentions permettent de faire le line entre ces différents composants.

La réponse du récepteur se fait via la méthode onReceive qui ne retourne aucune résultat. Toutefois, de nombreuses méthodes dont setResult permettent de le faire.

Voici un exemple basique de mise en oeuvre d'une classe réceptrice de diffusion :

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import.android.content.BroadcastReceiver;

public class SMSMailbox extends BroadcastReceiver
{
  public static final String TAG = "myMailbox";

  @Override
  public void onReceive(Context cnt, Intent inn)
  {
    Log.i(TAG, "onReceive invoqué");
    if (inn.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))
      Log.i(TAG, "Il y a au moins un SMS dans votre boîte !");
  }
}

Le manifeste de l'application devra déclarer cette classe comme récepteur de diffusion :

<receiver android:name=".SMSMailBox">
  <intent-filter>
    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
  </intent-filter>
</receiver>

Au passage, ce même manifeste devra autoriser l'application à accéder à la boîte aux lettres des SMS :

<uses-permission android:name="android.permission.RECEIVE_SMS" />

Les fournisseurs de contenu.

Si une application gère les données et peut ou a besoin de les exposer, elle semble bien convenir à être un fournisseur de contenu. Ces données peuvent être délivrées aussi bien pour des activités, services ou récepteurs de diffusion internes à l'application qu'au profit d'applications externes. D'autre part, les données peuvent être accédées en lecture, en écriture ou les deux.

Un fournisseur de contenu hérite de la classe ContentProvider.

Un fournisseur de contenu est accédé via un URI qui est définit par la classe en tant que chaîne de caractères publique et statique. L'accès au fournisseur se fait à la manière du langage SQL même si ce dernier est ici allégé. Il supporte tout de même les requêtes paramétrées, les clauses WHERE et la clause ORDER BY. Les résultats sont placés dans un curseur (classe Cursor).

(c) PiApplications 2016