L’histoire du lombric

La première fois que j'ai dû entendre parler d'Android remonte à environ un an et demi en lisant un article de Techpaf, blog d'un gars de l'IUT. À ce moment là, j'étais loin d'imaginer le potentiel d'une telle plateforme pour mobiles. Faut dire,  j'avais à peine toucher à un Iphone dans ma vie par le biais d'amis et encore... pour moi, les applications mobiles se résumaient aux fameux jeux à 5 euros qu'on télécharge au 68xxx par SMS et basta. J'étais donc à trois années lumière de ce monde là. Et je suis sûre que pleins de gens l'ignorent encore (bon certes, moins à présent, il faut commencer à le faire exprès mais tout de même tout le monde ne respire pas dans la technologie...) , la liberté de pouvoir télécharger des milliers et des milliers d'applications librement pour tout et pour rien. Et de pouvoir y contribuer.

Peu de temps après, un ami s'est acheté un téléphone sous Android justement et c'était assez difficile de l'ignorer parce qu'il ne parlait que de ça (^^) . C'était comme...je sais pas... le saint Graal. Android par-ci par-là. Pourquoi un tel engouement ?  "Trop cool", on peut le rooter et puis modifier la ROM et tout... le personnaliser à 100% et puis c'est Android quoi. Ah-Ah. Personnellement, une seule chose m'intéréssait sur son Samsung Spica... un petit jeu tout bête qui utilise l'accéléromètre : Le principe est de diriger un petit lombric à travers des tunnels sous la terre... débile mais addictif. Je vous invite à le télécharger sous Android Market si c'est pas déjà fait, c'est juste génial non ? Enfin sur le coup, ouais. Ca valait quand même le coup de lui battre son score même si il gagne toujours à la fin (ça c'est une autre histoire...). Et puis à partir de là, j'ai commencé à aimer le principe d'Android. Et d'en vouloir un à mon tour.

J'ai pas fait semblant puisque  j'ai fini par m'acheter le HTC désire. LE téléphone Android du moment (avril 2010).  La durée de vie d'un smartphone ça va très vite et il est déjà obsolète aujourd'hui mais je ne regrette pas mon choix. Je l'aime bien mon téléphone. Le Désire HD sorti après par exemple est beaucoup trop grand (Charles si tu passes par là, dédicace ;) ). Et bien que, je n'ai jamais croisé quelqu'un avec un Galaxy S, si l'on en croit les statistiques de notre SUPER application publiée sur le Market, la majorité des gens qui la télécharge en ont un...bref, j'ai commencé à être une sérieuse addicte à mon tour.

Après c'est simple, j'ai voulu faire mon projet tuteuré sous Android, mon prof d'anglais très open-source est tout aussi fan de la philosophie Android, et devinez dans quoi j'ai fait mon stage ? même que juste après je vais en licence embarquée mobile. Youhou, la totale \O/ .

Donc, imaginez bien que quand mon patron m'a annoncé aujourd'hui qu'on allait devoir passer sous développement iPhone sous peu, et ben pour ce soir j'avais juste envie de rejouer à Lumby. Non pas que je sois triste, mais j'avais envie. Parce que ce jeu, c'est comme dans la vie. On essaye de suivre son chemin et de ne pas dévier de la route.  Mais on finit quand même par dévier, malgré nous... et plouf, on se noie.

Construire simplement du JSON sur Android/en JAVA

Il est possible que vous ayez besoin d'encoder vos données en JSON pour les envoyer à un Web-service en requête HTTP. Pour Facebook par exemple, vous aurez besoin de construire du JSON pour pouvoir publier sur le mur de vos utilisateurs.

Supposons que je veuille encoder :

{
 "name": "Mon titre",
 "href": "http://www.monsite.com/",
 "description":"Ceci est la description",
 "media": [
   {
     "type": "image",
     "src": "http://monsite.com/page",
     "href": "http://monsite.com/image.jpg"
   }
 ]
}

Dans un premier temps, je créer un JSONObject :

JSONObject jsonObject = new JSONObject();

À partir de là c'est tout simple, il suffit d'utiliser la méthode put pour insérer le champ/valeur :

jsonObject.put("name", "mon titre");
jsonObject.put("href", "http://www.monsite.com/");
jsonObject.put("description", "Ceci est la description");

Il faut savoir que la méthode put possède une surcharge pour à peu près tout les types String, int, float... et notamment les maps, JSONObject et JSONArray...
Pour media par exemple, j'ai besoin d'insérer un JSONArray qui contient lui même un JSONObject. Pas de panique, je vais créer un JSONObject pour média que j'insérerais ensuite dans le principal. Dans un même temps, je vais pouvoir vous illustrer l'utilisation simple d'une Map pour créer un jSONObject :

Map<String,String> mediaMap = new HashMap<String,String>();
mediaMap.put("type", "image");
mediaMap.put("src", "http://monsite.com/page");
mediaMap.put("href", "http://monsite.com/image.jpg");
JSONObject jsonMedia = new JSONObject(mediaMap);

Mettons à présent mon JsonMedia dans mon JsonObject :

jsonObject.put("media", new JSONArray().put(jsonMedia));

Voilà. Et last but not least, il vous faut convertir cet objet JSON en String :

String stringEntity = new String(jsonObject.toString());

C'est prêt à être envoyé !

Sauvegarder et restaurer des images sous Android

Je charge des images dans mon application à partir d'une URL et j'aimerais pouvoir les stocker en cache pour ne pas les recharger sans arrêt ( par exemple quand l'utilisateur n'aura plus accès à internet ).

Quelle est la meilleure façon de pouvoir sauvegarder ces images ? Utiliser une Base SQLite ? Dans ce cas, je pourrais utiliser Blob ou bien les convertir en binaire pour les insérer mais bon, c'est pas très conseiller de charger du contenu  "lourd" dans une base SQLite sous Android (d'où son nom) .
La meilleure solution qui s'offre à moi est sans doute de les sauvegarder dans la mémoire interne du téléphone. Pas de secret, on procède comme en Java pour la Sérialization. Voici grossièrement comment je procède :

- Pour Sauvegarder l'image

// Je charge la photo depuis le web par son URL et la convertit en bitmap (que je pourrais insérer dans une ImageView)
URL pictureURL = new URL(article.getPhoto());
Bitmap bitmap = BitmapFactory.decodeStream(pictureURL.openStream());

//Je donne un nom que je pourrais retrouver à ma photo (ici l'id de l'article)
String FILENAME = String.valueOf(article.getId_article());

 

// Je sérialize...  MODE_PRIVATE correspond à la mémoire interne / Le format de compression de mon bitmap est PNG
FileOutputStream fos = openFileOutput(FILENAME, this.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();

- Pour charger l'image et l'insérer dans une ImageView :

//Je cherche mon ImageView par son XML
ImageView image = (ImageView)findViewById(R.id.dImage);

//J'ouvre le fichier que je trouve grâce à son ID et je décode
FileInputStream ins;
ins = openFileInput(String.valueOf(article.getId_article()));
Bitmap bitmap = BitmapFactory.decodeStream(ins);
ins.close();

// J'insère dans l'ImageView
image.setImageBitmap(bitmap);

- Pour la supprimer :

//J'appelle deleFile
deleteFile(String.valueOf(article.getId_article()));

 

Normalement, c'est tout bon. J'espère que cela vous a aidé ^^

 

Base 64 encode decode Android

Il semble que pour décoder ses données en base 64, Android ne propose les utilitaires qu'à partir de l'API 8. C'est bien sympa mais moi qui bosse en API 3...*ah-ah* comment je fais ?

Heureusement, toujours merci Google, de bons programmeurs proposent des classes pour pallier à ce manque, par exemple ici . Il suffit d'inclure la classe à son projet dans src, un petit rafraîchissement et voilà. Ni vu, ni connu. :)

En général, le décode vous renvoie un byte[] , alors que vous souhaitez le convertir en String.
Pour convertir proprement en String, on pourra procèder comme ceci, où buffer contient vos données à décoder :

byte[] decode = Base64.decode(buffer,Base64.URL_SAFE | Base64.DO_BREAK_LINES);

String str = new String(decode, "utf-8");

Evidemment, en instanciant le nouveau String vous remplacez par le charset approprié : UTF-8, latin-1...

Faire passer un type personnalisé par les intents

En programmation Android, si vous souhaitez véhiculer vos données d'une activité à une autre, vous utilisez sans doute les Bundles des Intents . Grâce aux méthodes putExtras et getExtras, vous passez ainsi vos données de types primitifs tels que Int, Float, String, etc. Mais comment faire lorsque l'on souhaite passer un type personnalisé, un objet métier par exemple ?

C'est simple. Il suffit de rendre sa classe serializable : en effet, putExtras et getExtras possèdent une surchage pour les objets de type sérializable. Rien de plus à faire.  Encore faut il le savoir. ;)

Maclasse monobjet = new Maclasse();
....
Intent intent = new Intent(this, MonActivity.class);
intent.putExtras("Objet",monobjet);

Remplacer les espaces d’une chaine de caractères en JAVA

Aujourd'hui en cherchant à envoyer une requête de type GET depuis une application Android , j'ai voulu gérer les problèmes d'espaces. En effet, on ne peut pas envoyer une requête du type :

http://mondomaine.org/search.php?query=vive le vent

D'où l'intérêt de faire remplacer les espaces par un autre caractère (généralement peu utilisé comme %) pour contourner le problème. Oui mais euh? qu'est ce qui représente le caractère "espace" en JAVA et comment je gère plusieurs espaces moi ? C'est là que les expressions régulières interviennent. On va pour cela se servir de la classe java.util.regex.Pattern (amusez-vous à lire la Doc..). En gros une expression régulière c'est une expression construite à partir de constantes et d'opérateurs.

Justement ça tombe bien, " \s" représente " any whitespace character ".  L'opérateur " + " quant à lui nous permettra de remplacer pour un ou plusieurs espaces. Ainsi on pourra aussi bien entrer "vive le vent" que "vive       le         vent", cela donnera toujours "vive%le%vent". Pratique non ?

Concrètement je devrais pouvoir gérer les espaces avec "\s+" mais pour bien faire comprendre à JAVA -qui est littéralement bête- que  nous voulons l'antislash il faut le doubler DONC on écrira  "\\s+".

Finalement pour pouvoir remplacer mes espaces, j'utilise la fonction replaceAll de String :

1. String rq = "vive le vent";
2. rq = rq.replaceAll("\\s+", "%");
3. url = "http://mondomaine.org/search.php?query="+rq;

Et voilà. :)

Le commencement en 5 fausses minutes.

Ayant décidée d'installer WordPress 3 sur Free, histoire d'écrire des choses un peu plus sérieuses et UTILES -parce que mylife.com... vous comprenez ;) -, j'aurais du boucler le tout en  5 minutes comme d'habitude hop, hop, hop (selon le readme, montre en main) . Oui, oui.

C'est sans compter les fatal error faussement sympa de la base de données, et j'en passe avec leur fameuse installation "automatique" :

Fatal error: mysql_num_fields(): supplied argument is not a valid MySQL result resource in /mnt/136/sdd/e/4/myfamouslife/wp-includes/wp-db.php  on line 1112

Et donc après avoir supprimer et recréer cinq bonnes fois les bases MySQL et cherchant la petite bête là où elle n'est pas, je consens à résoudre le problème grâce à ceux qui l'ont déjà rencontré : Google.

Fort heureusement, il suffit de créer un .htacess à la racine de son dossier WordPress  en prenant soin d'y écrire :

php 1
ErrorDocument 404 /index.php

et bien entendu ne pas oublier de modifier votre fichier wp-admin\includes\misc.php à la ligne :

return insert_with_markers( $htaccess_file, ‘WordPress’, $rules )

par un simple :

return true;

J'aurais du y penser plus tôt. Mais quelqu'un l'a pensé pour moi. Donc à lui, merci.
Je peux dormir en paix à présent.