Comment intégrer des graphiques dans une application Android ?

Android ne propose nativement aucune solution pour générer des courbes, camemberts et autres graphiques. Lors du développement d’applications, il est pourtant fréquent que l’on veuille afficher ce genre d’informations. Les terminaux Android disposant pour la plupart d’une résolution plutôt petite (< 800*600), il est souvent plus simple et plus efficace d'afficher les valeurs d'un tableau sous forme de graphique.

Cet article a pour but de vous présenter quelques-unes des solutions les plus répandues pour répondre à ce besoin. Pour cela, nous allons créer un camembert de 3 manières différentes :

Cet article est une adaptation libre du billet de l’un des mes collègues indiens Yogesh Kapoor, l’original est disponible en anglais sur le blog de Xebee.

Google Charting API

L’utilisation de Google Charting est très simple. Cette API permet de créer des graphiques par l’intermédiaire d’une URL. Vous n’avez qu’à passer les bon arguments à celle-ci pour récupérer votre graphique. Comme ce service est basé sur une URL, vous devez disposer d’une connexion internet pour que celle-ci fonctionne. Si votre application s’exécute hors ligne, passez votre chemin.

L’appel à l’API Google Charting s’effectue par l’intermédiaire d’URL ressemblant à celle-ci :


http://chart.apis.google.com/chart?cht=p3&chs=250x100&chd=t:30,60,10&chl=cars|bikes|trucks

Dans cet exemple, voici comment lire les paramètres :

  • cht=t3, type du graphique, t3 = camembert 3D,
  • chs=250×100, la résolution,
  • chd=t:30,60,10, les données,
  • chl=cars|bikes|trucks, les libellés.

Le google code du projet est plutôt bien fait, il vous permet de créer différents types de graphiques en vous inspirant d’une multitude d’exemples.

Vous pouvez intégrer un graphique de ce type dans une application Android par l’intermédiaire d’une simple WebView. Difficile de faire plus simple.

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  WebView webView = new WebView(this);
  webView.loadUrl("http://chart.apis.google.com/chart?cht=p3&chs=250x100&chd=t:30,60,10&chl=cars|bikes|trucks");

  setContentView(webView);
}

La méthode onCreate() est appelée à la création d’une activité. Dans l’exemple ci-dessus, nous avons créé une WebView, chargé l’url de notre graphique dans celle-ci et affecté notre vue comme composant principal de l’activité.

Pour que cela fonctionne, comme vous avez besoin d’un accès internet, vous devez ajouter la permission suivante dans votre AndroidManifest.xml.

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

Et c’est tout ce que vous avez à faire ! Notez au passage que vous n’êtes pas obligé de passer par une WebView, vous pouvez également télécharger cette image et l’afficher comme n’importe quel autre drawable dans n’importe quel composant (imageView, boutons, backgounds …)

Voici un capture d’écran du résultat obtenu, le graphique est plutôt joli. Il vous est possible de modifier les couleurs, ajouter une légende, changer le type de graphique en ajoutant des paramètres supplémentaires.

Google Char Api Android

Si votre application n’a pas besoin d’accéder à internet, ce type de graphique n’est pas adapté. Continuons notre tour d’horizon avec une autre solution … hors ligne.

achartengine

achartengine est un projet permettant de générer différents types de graphique pour Android. Cette API utilise le mécanisme d’Intent, des messages configurables qui permettent de lancer l’exécution d’une activité tierce. Elle ne nécessite aucune connexion internet..

Qui dit Intent dit nouvelle activité. Les graphiques sont affichés sur des activités dédiées. Contrairement à Google Chart API, vous ne pourrez donc pas intégrer vos graphiques directement dans vos activités.

Pour l’utiliser, télécharger la dernière version du jar du projet sur le Google Code du projet, puis ajoutez le à votre projet Android.

Voici l’exemple d’une classe contenant une méthode qui créer un Intent configuré pour afficher un camembert :

public class MyChartExample {

  public Intent createIntent(Context context) {
    int[] colors = new int[] { Color.RED, Color.YELLOW, Color.BLUE };
    DefaultRenderer renderer = buildCategoryRenderer(colors);

    CategorySeries categorySeries = new CategorySeries("Vehicles Chart");
    categorySeries.add("cars ", 30);
    categorySeries.add("trucks", 20);
    categorySeries.add("bikes ", 60);

    return ChartFactory.getPieChartIntent(context, categorySeries, renderer);
  }

  private DefaultRenderer buildCategoryRenderer(int[] colors) {
    DefaultRenderer renderer = new DefaultRenderer();
    for (int color : colors) {
      SimpleSeriesRenderer r = new SimpleSeriesRenderer();
      r.setColor(color);
      renderer.addSeriesRenderer(r);
    }
    return renderer;
  }
}

La récupération de l’Intent bien configuré s’effectue par l’intermédiaire de la méthode createIntent. À l’intérieur de celle-ci, un SimpleSeriesRenderer est créé pour chaque part du camembert. Ces renderers sont ensuite ajoutés à un DefaultRenderer global au graphique.

À ce stade, la structure du graphique est configurée, il nous reste plus qu’à déclarer les valeurs des différentes parts de notre camembert. Pour cela, nous créons un CategorySeries avec les mêmes libellés et valeurs que nous avons utilisé dans l’exemple précédent.

Pour finir, nous fabriquons à partir de tout cela (renderers + series) un Intent correctement configuré en utilisant la factory prévue à cet effet.

Notre Intent créé, il ne nous reste plus qu’à l’utiliser pour lancer une nouvelle activité contenant le graphique. Il s’agit du mécanisme habituel pour lancer une nouvelle activité.

  Intent achartIntent = MyChartExample.createIntent(this);
  startActivity(achartIntent);

Après avoir exécuté ce code, voici ce qui devrait s’afficher.

Chartdroid

La dernière solution présentée dans cet article est plus contraignante d’utilisation. Elle utilise le même mécanisme d’Intent que la solution précédente, mais ici les activités ne sont pas directement intégrées à votre projet. Pour que les Intents fonctionnent, vous devez installer une application tierce : ChartDroid. Notez qu’il vous est cependant possible de faciliter cette installation en proposant programmatiquement un lien sur le market pour la récupérer (ce mécanisme n’est pas présenté dans cet article, il fonctionne, une fois encore, via un Intent).

Pour utiliser cette solution, vous devez créer un ContentProvider. C’est un mot qui peut faire peur au premier abord, mais il s’agit d’un des mécanismes proposé par Android pour communiquer entre application. Un ContentProvider est utilisable après la création d’un Intent, il permet de récupérer des données à partir d’un type et d’un URL.

public class ChartDroidDataProvider extends ContentProvider {
 
  static final String AUTHORITY =  "com.xyz.contentprovider.chardroid";

  @Override
  public String getType(Uri uri) {
    return "vnd.android.cursor.dir/vnd.com.googlecode.chartdroid.graphable";
  }

  public static final Uri PROVIDER_URI = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build();

  @Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 
    // Fetch the actual data
    MatrixCursor c = new MatrixCursor(new String[] { 
      BaseColumns._ID,
      "COLUMN_AXIS_INDEX", "COLUMN_SERIES_INDEX",
      "COLUMN_DATUM_VALUE", "COLUMN_DATUM_LABEL"  
    });

    c.newRow().add(1).add(0).add(1).add(30).add(null);
    c.newRow().add(2).add(0).add(1).add(10).add(null);
    c.newRow().add(3).add(0).add(1).add(60).add(null);
    return c;
  }

  ...

}

Notez que nous avons supprimé du code précédent les méthodes qui sont générées par défaut par nos IDEs et que nous n’avons pas eu besoin de modifier.

La méthode query est en fait chargée de fournir les données nécessaires à la construction du graphique. Ce listing est l’un des exemples les plus minimalistes nécessaire à l’API pour générer un camembert. Nous utilisons un MatrixCursor afin de passer les valeurs de notre graphique. Au premier abord, la manière de récupérer les données ne semblent pas très claire, la syntaxe n’est pas des plus conviviale. Au final, on dit souvent que la première impression est souvent la bonne :)

N’hésitez pas à consulter le site officiel pour plus d’informations sur ce projet.

Maintenant que notre content provider est crée, il ne nous reste plus qu’à démarrer l’activité ChartDroid pour afficher notre graphique. Cela s’effectue par un Intent :

Intent chartDroidIntent = new Intent(Intent.ACTION_VIEW, ChartDroidDataProvider.PROVIDER_URI);
chartDroidIntent.putExtra(Intent.EXTRA_TITLE, "Chart droid");
chartDroidIntent.addCategory("com.googlecode.chartdroid.intent.category.PIE_CHART");
startActivity(chartDroidIntent);

Dans le morceau de code précédent, la ligne category est importante car elle définie le type de graphique à afficher.

Après exécution, vous devriez avoir un résultat qui ressemble à cela :

Conclusion

Pour conclure, la solution Google Chart API est la plus aboutie, je vous la recommande vivement. Les graphiques sont obtenus très facilement et sont plutôt jolis. Si vous n’êtes pas prêt à dépendre d’une connexion internet, je vous recommanderais la deuxième solution : achartengine. Bien que cela ne se voit pas sur les captures d’écran ci-dessous, les graphiques obtenus par achartengine sont généralement un peu moins jolis que ceux obtenus par chartdroid. C’est la contrainte d’avoir à installer une application tierce qui cause du tord à la troisième solution.

Pour finir, notez que toutes les solutions n’ont pas été présentées dans cet article. Je pense en particulier aux nombreuses petites surcouches jfreechart qui émergent (et meurent) ici et là. Je ne les ai pas présentées car la majorité d’entre elles ne sont que très peu actives.

4 Responses

  • salut j’ai un problème lors de l’exécution de l’application (achartengine) il m’affiche un msg d’erreur « process has stopped unexpectedly  » g pas compris le prb ???? merci

  • ça ne marche pas sur android 1.6

  • Bonjour
    Merci pour cet article
    Il est à noter que achartengine 1.0 est utilisable dans les fragments (c’est à dire sans créer d’activité) en passant par :
    ChartFactory.getBarChartView

  • svp je veux créer un graphe à partir de la base de données SQLite, ici vous ne montrer que la méthode static (faire entrer des valeurs statiquement) veuillez m’aider svp

Laisser un commentaire