Fév 24

Android : Mélanger des vues statiques et dynamiques

Android propose deux méthodes pour créer un écran d’une application :

  • Une méthode dynamique, se basant sur une structure de composants créés dans du code Java : les pages sont créés en assemblant des conteneurs (Layout) et des composants (Button, TextView, …). Par exemple, voilà le code pour créer un formulaire avec un texte, un input et un bouton de validation :
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout addTask = new LinearLayout(this);
    addTask.setOrientation(LinearLayout.HORIZONTAL);
    
    // Interface pour ajouter des tâches
    TextView label = new TextView(this);
    label.setText("new");
    addTask.addView(label);
    newTask = new EditText(this);
    newTask.setWidth(100);
    addTask.addView(newTask);
    Button addButton = new Button(this);
    addButton.setText("add");
    initButton(addButton);
    addTask.addView(addButton);
    setContentView(layout);
    }
  • Une méthode statique, se basant sur des fichiers XML. Ici, on décrit le même genre d’éléments (conteneurs et composants) mais dans un format XML, plus convivial :
    
    
        
        
        

Chaque méthode a ses avantages et ses inconvénients. Par exemple, la méthode statique et plus concise et plus lisible, alors que la méthode dynamique est plus flexible (car dynamique !) mais plus abscons. C’est pourquoi il peut être utile de mélanger les deux méthodes, et ainsi obtenir des vues facilement modifiables et dynamiques !

Pour cela, deux possibilités : mettre des éléments dynamiques dans une vue statique, ou mettre des éléments statiques dans une vue dynamique.

Eléments statiques dans une vue dynamique

Le but de cette manipulation et de récupérer des vues décrites dans des fichiers XML, et de les placer où on le souhaite dans une vue créée dynamiquement. Pour le faire (et le faire bien!), il faut comprendre le système de chargement des ressources. Je ne m’étendrais pas sur le sujet (le guide de dev d’Android est assez bien fourni dessus), mais pour charger un layout autrement qu’en l’associant à la vue complète (Activity.setContentView(R.layout.*)), il est nécessaire de passer par un object LayoutInflater, qui va se charger de transformer les éléments déjà traité par le système de ressource en Object Layout exploitable.

Dans l’exemple suivant, le layout menu (créé dans le fichier XML res/layout/menu.xml) est chargé et ajouté dans un layout existant :

	LinearLayout layout = new LinearLayout(this);
	layout.setOrientation(LinearLayout.VERTICAL);

	// ... Construction du début de la page

	LinearLayout menu = (LinearLayout) getLayoutInflater().inflate(R.layout.menu, null);
	layout.addView(menu);

	//... Construction de la fin de la page

	setContentView(layout);

Eléments dynamiques dans une vue statique

Le but de cette manipulation est d’avoir une page statique représentant la structure de la page, et de la compléter avec des éléments dynamiques.

Fév 15

Débuter le développement pour Android – Le poste de travail

Comme je suis en train de débuter le développement pour des applications Android, et que c’est un sujet fort prisé par bon nombre de développeur qui ont une dose de geekitude dans les veines, je vais tâcher de faire part de mon expérience sur le sujet à travers divers post sur ce blog.

Cette première partie est déjà un écart par rapport au sujet initial, car il ne parle pas directement de développement, mais de préparer son poste de travail à faire du développement. En effet, il est rare de nos jours de débuter un développement from scratch, sans outils, avec uniquement un éditeur de texte et un compilateur en ligne de commande (rare et suicidaire!). D’autant plus que la communauté Android fourni pléthore d’outils et de documentation pour automatiser la plupart des tâches nécessaires à la création d’une application Android.

Le kit de développement

La première chose à faire est d’installer le SDK (Software Development Kit) Android, qui est disponible à l’adresse suivante : http://developer.android.com/sdk/index.html. La description est assez bien faite pour m’éviter d’avoir à décrire le processus d’installation.

L’interface de développement

L’outil de prédilection pour développer des applications Android est l’IDE Eclipse. Celui est téléchargeable ici. Celui-ci est majoritairement utilisé pour faire du développement Java, ce qui est parfait car c’est le langage utilisé pour écrire des applications Android.
La communauté Android propose un plugin pour Eclipse permettant de prendre en charge la plupart des tâches liées au développement Android : génération de code, génération de fichier de configuration, packaging, transformation en application Dalvik, gestion du SDK et lancement des terminaux virtuels (et bien d’autres encore). L’installation de ce plugin est décrit sur la page dédiée.

Le code source d’Android

Dernier point pour simplifier le développement d’application Android avec Eclipse : récupérer le code source d’Android. Ce code ne sera pas utilisé pour être lu exhaustivement (sinon vous commencerez votre application Android au moment où l’informatique sera passé de mode, et que l’espèce humaine sera rayée de la surface de la terre par les robots), mais il permettra à Eclipse d’extraire les commentaires des différentes méthodes utilisées, et éventuellement de naviguer à travers le code si vous avez un problème et que vous accusez inutilement la plateforme de bugs car elle ne fait pas tourner votre application parfaite.
Le code source d’Android est hébergé sur un serveur GIT dédié. GIT est un gestionnaire de version distribué, permettant de partager du code entre plusieurs développeurs (en gros). Pour récupérer le code source d’Android, il faut donc tout d’abord disposer des outils permettant de dialoguer avec le serveur.
Pour les systèmes Linux et Mac, la marche à suivre est expliqué directement sur le site des sources d’Android.
Pour les windowsiens, il faut :

  • soit installer l’application msysgit et accéder à l’URL GIT git://android.git.kernel.org/platform/frameworks/base.git
  • soit installer l’application Cygwin (permettant d’avoir la plupart des utilitaires de base d’Unix sur Windows) avec à minima les paquets suivants : automake, bison, curl, flex, gcc, git, gnupg, python, zip (merci à ce site pour l’info), et ensuite utiliser la même méthode que pour Linux.

Ensuite, il est nécessaire de lier le code source télécharger aux librairies qu’utilise Eclipse pour la compilation.

Et voilà, vous diposez maintenant d’un poste de travail parfait pour le développement Android ! En attendant le prochain post, je vous laisse avec la documentation très fournie d’Android.

Jan 10

JD : Décompileur Java

Certains outils prennent une place prépondérante lorsqu’il s’agit de faire la chasse aux bugs et autres dysfonctionnements.
Un décompilateur Java permet de transformer un fichier de bytecode Java en un fichier de code Java. Un tel outil est pratique dans le cas où on dispose de classes (dans un répertoire, un JAR ou autre), et on souhaite pouvoir analyser leur fonctionnement (en cas de bug, de retro-engineering ou de curiosité mal placée).
Pour cela, j’avais l’habitude d’utiliser JAD, qui est un des plus anciens, des plus utilisés (à l’époque) et qui avait l’avantage indéniable de disposer d’un plugin pour Eclipse, permettant d’un simple « Ctrl + clic » de naviguer dans toutes les classes disponibles sur chaque projet.
Par contre, certaines fonctionnalités étaient mal supportées (comme les blocs try / catch) et ce phénomène s’est aggravé avec l’apparition de Java 5.

Aujourd’hui, j’ai découvert un remplaçant digne de ce nom à JAD : Java Decompiler. Il dispose des même fonctionnalités que JAD, mais génère un code beaucoup plus propre que son ancêtre. Ses principaux atouts :

  • Ecriture du numéro de ligne correspondant à chaque instruction (utile lors de l’analyse de stacktrace);
  • Gestion des blocs try / catch;
  • Gestion des generics et autres nouveautés Java 5;

Bien évidemment, il dispose également d’un plugin Eclipse.

Déc 08

Application Android pour contrôler un robot Lego

Quelle ne fut pas ma joie de découvrir, au détour d’une page web, l’existence d’une application Android permettant de contrôler la brique Lego Mindstorms NXT par Bluetooth ! Cette application, Minddroid, disponible dans le Android Market, permet de diriger un robot Lego à partir des accéléromètres du mobile.

En dirigeant l’extrémité du mobile vers le bas, le robot va vers l’avant. En le dirigeant vers le haut, il recule. La gauche et la droite le font tourner dans la direction correspondante. Simple. Et magique à la fois.

Que demander de plus ? Que l’application soit open source. Et là … c’est le cas. Pardonnez mes larmes, c’est l’émotion.

La news sur le site Lego et le repository GIT http://github.com/NXT/LEGO-MINDSTORMS-MINDdroid

Déc 06

Création du Wiki IT

J’ai créé une base de connaissance pour référencer tout un tas d’information sur l’informatique en général, et plus particulièrement les domaines pour lesquels j’ai des affinités ou dans lesquels j’ai travaillé. Il est encore assez vide, il ne faut pas m’en tenir rigueur.
Vous pouvez y accéder en allant dans l’onglet « Wiki IT » on bien directement à l’URL http://it.pisson.eu

Nov 30

Scala User Group : API Akka

Ce lundi 29/11 à eu lieu, chez Xebia, le Scala User Group. La session de cette soirée a été l’occasion d’avoir un aperçu de l’API Akka, destinée à mettre en place un système de calcul distribué.

Celui-ci se base sur des acteurs (« Actors »), qui sont des composants distribués sur une ou plusieurs machines, et qui prennent en charge des calculs à partir d’une file de message propre. Un orchestrateur va prendre l’ensemble des données à traiter, les subdiviser en paquets, mettre ces paquets dans des messages et les répartir suivant les différents acteurs. De cette manière, chaque acteur peut traiter son contenu indépendamment des autres, ce qui permet de pouvoir lancer les calculs en parallèle (sur différents coeurs de processeur, ou différentes machines, etc…). Ce modèle, assez classique pour du calcul réparti, est enrichi dans Akka d’une gestion de fail-over et d’une gestion de transaction propres et simples.

Voilà un exemple de code (tiré de la homepage de Akka):

// Code du serveur
class HelloWorldActor extends Actor {
  //Définition de l'action à la réception d'un message
  def receive = {
    case msg => self reply (msg + " World")
  }
}
// Démarrage du serveur et inscription
RemoteNode.start("localhost", 9999).register(
  "hello-service", actorOf[HelloWorldActor])

// Code du client
val actor = RemoteClient.actorFor("hello-service", "localhost", 9999)
//Envoi d'un message sur l'acteur et attente du résultat
val result = actor !! "Hello"
Nov 09

Présentation de l'API HTML5 AppCache

Le 08/11/2010 à eu lieu chez Zenika une présentation par Peter Lubbers de la spécification HTML5 AppCache.

AppCache permet de mettre en cache, au niveau du navigateur web, une partie du site web que l’utilisateur est en train de visiter. Ce cache permet de pouvoir continuer à consulter le site web même si l’utilisateur perd sa connexion.

Le cas d’utilisation le plus classique est lorsque l’utilisateur prend l’avion : avec une partie du site mis en cache, l’utilisateur peut continuer à consulter les pages web même si il n’y a pas accéder avant d’embarquer.

La spécification de ce système est disponible sur le WHATWG et sur le W3C.

Fonctionnement

Pour peupler le cache à partir d’une page (par exemple « index.html »), il suffit d’ajouter l’attribut manifest à la balise html de cette page.

<html manifest="site.manifest">
<!-- Code de la page -->
</html>

Le contenu de l’attribut est le nom du fichier qui va contenir la description du contenu du cache. Par convention, son extension est « .manifest » et son MIME-type doit être « text/cache-manifest ».

Ce fichier est un fichier textuel, case-sensitive, qui contient trois sections : CACHE, NETWORK et FALLBACK.

CACHE va contenir la liste des ressources à télécharger et à placer dans le cache ; NETWORK liste les ressources qu’il faut forcément aller rechercher sur le réseau (et donc ne pas contenir en cache) ; Enfin FALLBACK permet de définir les pages qui seront affichées lorsqu’une ressource ne sera pas disponible (pas dans le cache et pas de connexion pour aller la récupérer).

CACHE MANIFEST
#Pages dans le cache. Si cette section est au début,
#on peut omettre le header "CACHE:"
CACHE:
index.html
next.html
fallback.html

#Pages à automatiquement rechercher sur le réseau
NETWORK:
versatile.html

#Toute page tombant en erreur va être remplacer par fallback.html
FALLBACK:
/ fallback.html

Si on accède, lorsqu’on est connecté, à la page index.html, le navigateur va enregistrer en cache les pages index.html, next.html et fallback.html. Si le réseau est coupé, et que l’utilisateur veut accéder à la page next.html, il pourra y accéder. Si par contre, il tente d’accéder à la page versatile.html, comme cette page est cherchée sur le réseau et que celui-ci est coupé, le navigateur va fournir la page fallback.html à la place.

Utilisation dans Javascript

Coté Javascript, on peut également exploiter l’AppCache, d’une part pour savoir si il est disponible (avec le booléen window.applicationCache), mais également pour faire un rafraîchissement de celui-ci (integer window.applicationCache.status pour connaître l’état du cache, méthode window.applicationCache.update() pour mettre à jour le cache et Window.applicationCache.swapCache() pour utiliser la nouvelle version mise à jour).

Il est également possible de gérer les évènements liés au cache.

Demo

Un exemple de site utilisant le AppCache, créé par Peter Lubbers, peut être télécharger ici.

Nov 09

Eclipse Day Paris 2010

Ce vendredi 05/11/2010 à eu lieu, au Pavillon Royal (Bois de Boulogne), l’Eclipse Day Paris, qui est une journée de conférences sur l’IDE Eclipse, ses nouveautés et avancées, ainsi que l’écosystème des applications qui gravitent autour.

Les conférences auquelles j’ai assisté sont les suivantes :

  • Discours d’ouverture du CEO de la Fondation Eclipse, Mike MilinKovich;
  • Retours d’expériences par des consultants de Zenika et ProxiAD sur la mise en place des technologies Eclipse chez des clients;
  • Les nouveautés et prévisions pour le système de persistence EclipseLink, par Doug Clarke;
  • Utilisation de Git avec Eclipse, par Chris Aniszczyk;
  • Les projets Virgo et Gemini, par Steve Powell;
  • Solution de génération de rapport OpenDocument à partir de multiples sources (Sodius);
  • Sonatype : Maven, m2eclipse, Nexus & Hudson;
  • Framework Eclipse Scout.

Les choses que j’ai à retenir de ces présentations :

– L’écosystème d’Eclipse est constitué de milliers de projets, dans des domaines variés, et beaucoup de ces projets profiteraient de nouveaux développeurs / commiters.

– Deux API, Eclipse RCP et Eclipse RAP, sont deux API graphiques (le premier se basant sur SWT, le second sur un affichage web standard HTML/Javascript), se basant sur (quasiment) les même principes d’affichage, rendant le développement des plugins assez similaire.

– Montée en force du système de versioning GIT, et intégration de celui-ci dans Eclipse à travers EGIT et JGIT.

– L’architecture d’Eclipse évolue avec le système Virgo et les composants Gemini.

– Sonatype a annoncé le sortie imminente du plugin Eclipse pour Maven M2Eclipse en version 1.0.

Nov 08

Lego Mindstorm animé par du Java

J’ai eu l’occasion récente d’acquérir le fabuleux set de Lego « Mindstorm NXT 2 ».

Pour ceux qui ne le savent pas, il s’agit d’un coffret de Lego Technic contenant un bloc programmable, des moteurs (trois éléments qui peuvent tourner, afin d’animer roues, bras et autres), et des capteurs (deux de toucher, un de distance et un de lumière).

Rien de mieux pour réveiller en moi les joies de la construction improbable et de pouvoir leur donner vie !

Les avantages du Lego Mindstorms NXT sont nombreux : c’est un kit d’apprentissage à la robotique à moindre frais (~300€), il est fait en Lego (donc très simple pour l’assemblage, et la nostalgie empêche de baisser les bras trop vite), mais surtout, on peut faire du développement en Java !

Pour cela, il existe une API très bien faite, dénommé « LeJOS« , et qui fonctione de la manière suivante :

  • En premier lieu, on flashe le bloc programmable avec les outils fournis. Cela passe par un outil très simple qui prend toute l’opération en charge.
  • Ensuite, il suffit de développer une application avec les JAR fournis avec l’API (qui regroupe une JVM simplifiée et l’API d’accès aux moteurs et capteurs).
  • Il n’y a plus qu’à compiler avec les outils donnés et à faire le push du programme sur le bloc programmable.

L’API est très bien documentée, ainsi que tous les outils de compilation / publication.

Pour vous montrer la simplicité du développement, voilà un exemple de code avec la machine qui va avec :

La machine :

Deux moteurs sont utilisés pour l’avancement de la voiture, et le troisième est utilisé pour la direction des roues avant. Le capteur d’ultrason est mis à l’avant de la voiture pour éviter les colisions sur les murs et les objets.

Pour activer cette petite voiture, un programme simple va la faire avancer, sauf si il y a un objet devant, auquel cas elle va reculer et changer de direction.

Le code pour cela est le suivant :

import lejos.nxt.Button;
import lejos.nxt.Motor;
import lejos.nxt.MotorPort;
import lejos.nxt.SensorPort;
import lejos.nxt.UltrasonicSensor;

/** Programme pour la voiture Lego. */
public class Car {

  //Les deux moteurs pour les roues arrières.
  private static Motor back1 = new Motor(MotorPort.A);
  private static Motor back2 = new Motor(MotorPort.B);

  //Le moteur utilisé pour la direction avant.
  private static Motor direction = new Motor(MotorPort.C);

  //Le capteur d'ultrason.
  private static UltrasonicSensor sonic = new UltrasonicSensor(SensorPort.S1);

  //La boucle principale.
  public static void main(String[] args) throws Exception {

    //Boucle jusqu'à ce qu'on presse le bouton d'échappement.
    while (!Button.ESCAPE.isPressed()) {
      //Récupère la distance en CM.
      int distance = sonic.getDistance();
      if (distance <10) {
        changeDirection();
      } else {
        moveForward();
      }
    }
  }

  //Fait tourner les roues avant et recule.
  private static void changeDirection() {
    direction.rotate(35, false);
    moveBackward();
    direction.rotate(-35, false);
  }

  //Avance.
  private static void moveForward() {
    back1.rotate(360, true);
    back2.rotate(360, true);
  }

  //Recule.
  private static void moveBackward() {
    back1.rotate(-360, true);
    back2.rotate(-360, true);
  }
}