Wednesday, December 2, 2009

Les binaires Java ME

Toute application Java ME est composée de deux fichiers avec les extensions .jar et .jad. La compréhension du processus de fabrication et des contenus de ces fichiers est primordiale.

JAD: Java Application Descriptor

JAD, pour Java Application Descriptor, est un fichier texte qui contient des informations sur l’application. Plusieurs règles sont à respecter lors de l’écriture de ce fichier. Comme il existe plusieurs configurations et profils, il serait dommage qu’après avoir téléchargé un programme, on se rende compte qu’il ne peut pas fonctionner sur le téléphone à cause d'un problème de compatibilité de configuration ou de profil ou encire qu’il n’y ait pas assez d’espace mémoire libre pour l’installer. Grâce au JAD, le téléphone peut connaître à l’avance les spécificités du programme que l’on aimerait télécharger.

C’est un fichier qui contient toutes les informations utiles concernant la MIDlet (taille du JAR, version de MIDP, version de CLDC, …). Il est généralement téléchargé avant le programme, ce qui permet de s’assurer de la compatibilité complète du terminal hôte.

Il contient des attributs obligatoires qui commencent tous par "MIDlet-" et qui sont séparés par “:” de leurs valeurs. Exemple:

MIDlet-Vendor : Y2R

Les attributs obligatoires sont:
  • MIDlet-Name 
  • MIDlet-Version 
  • MIDlet-Vendor 
  • MIDlet-Jar-URL
  • MIDlet-Jar-Size
  • MIDlet-: MIDletName , [IconPathname] , ClassName
  • MicroEdition-Profile 
  • MicroEdition-Configuration

Sans ces attributs le Application Management Software refusera d'installer l'application.

Un bionaire Java ME (jar) peut contenir une ou plusieurs MIDlet, ceci est spécifié grâce à l''attribut MIDlet- qui se remplie comme suit:

  • n: correspond au numero de la MIDlet, il commence à 1 et est incrémenté de 1 pour chaque MIDlet supplémentaire dans le cas d'une MIDlet Suite.
  • MIDletName:  nom de la MIDlet et équivalent à la valeur de l'attribut MIDlet-Name
  • IconPathname: chemin vers le fichier image de l'icone de l'application, peut rester vide
  • ClassName: nom de la classe de la MIDlet

Voici quelques attributs optionnels:

  • MIDlet-Description 
  • MIDlet-Icon 
  • MIDlet-Info-URL 
  • MIDlet-Data-Size 
  • MIDlet-Permissions
  • MIDlet-Permissions-Opt 
  • MIDlet-Push-
  • MIDlet-Install-Notify 
  • MIDlet-Delete-Notify 
  • MIDlet-Delete-Confirm

Il est possible d'accéder à ce fichier, à partir du programme Java ME, pour récupérer les valeurs des attributs renseignés. Ceci se fait grâce à la méthode (classe MIDlet):

    String getAppProperty(String propertyName)

Ceci peut être util si jamais on souhaiterai modifier des informations utilisées par l'application sans avoir à changer le code et regénérer les binaires. Par exemple, imaginons que notre application accède à un site Internet et pendant la phase de développement nous ne disposons pas de l'adresse finale sur laquelle pointera le lien donc on pourra le spécifier dans la jad avec un attribut (exemple: URL) et récupérer sa valeur directement dans le code.

Les spécifications MIDP 2.0 introduisent le concept de domaine d'installation. En fonction de ce domaine l'AMS (Application Management Software) récupère l'information du fichier manifest.mf ou du fichier Jad pour permettre ou pas l'installation de l'application.

Voici ci-dessous le contenu d'un fichier JAD :


MIDlet-<1>: nom de la midlet, chemin vers l'icone, nom de la classe qui étend MIDlet
MIDlet-Description: une rapide description du programme
MIDlet-Icon: icône de l’application qui sera affichée dans le menu du téléphone
MIDlet-Jar-Size: taille en octet du fichier jar
MIDlet-Jar-URL: adresse à laquelle se trouve le fichier jar
MIDlet-Name: nom de la MIDlet
MIDlet-Vendor: fournisseur de la MIDlet
MIDlet-Version: 1.0
MicroEdition-Configuration: configuration
MicroEdition-Profile: version de MIDP


Exemple:
MIDlet-<1>: myMidlet,/res/icone.png, myMidlet
MIDlet-Description:  Ma MIDlet qui affiche du texte et des images
MIDlet-Jar-Size: 1234567
MIDlet-Jar-URL: myMidlet.jar
MIDlet-Name: myMidlet
MIDlet-Vendor: Y2R
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.0


Quelques remarques:

  • Même si le JAD permet de s’assurer de certaines compatibilités entre le mobile et l’application, il ne permet pas de prévenir de l’utilisation d’une API non supportée par le mobile.
  • l’ordre des attributs dans le Manifest n’a pas d’importance
  • “:” sépare l’attribut de sa valeur
  • les espaces entres l’attribut et sa valeur sont ignorés
  • un seul attribut par ligne (cette ligne doit se terminer par un retour chariot)
  • le développeur peut utiliser un attribut personnel à condition qu’il ne commence pas par MIDlet- ou MicroEdition-
  • il faut respecter la casse pour l’écriture des attributs
  • les attributs ne doivent pas être dupliqués dans le Manifest
  • Le JAD est utilisé pour valider que l'application peut être installée sur le téléphone. Mais une fois l'application installée, il n'est pas conservé. Au contraire, le Manifest est utilisé par l'AMS pour toute la durée de vie de l'application. C'est la raison pour laquelle le JAD et le Manifest sont si similaires tout en étant indispensables tous les deux.
  • Certains opérateurs ou constructeurs ont leurs propres attribues. Exemples:
    •  Nokia 
      •  Nokia-MIDlet-Category
      • Nokia-Scalable-Icon
    • Vodafone 
      •  MIDxlet-ScreenSize
      • MIDxlet-Application-Range
      • ...
 
JAR: Java Archive

    Il s’agit d’un simple fichier archive avec :l’extension .jar : il contient les classes de l’application et tous types de fichiers nécessaires pour l’exécution (images, sons, textes…). Cette archive contient un répertoire « META-INF» qui, lui-même, contient un fichier « MANIFEST.MF ». Ce dernier est indispensable à l’installation et l’exécution de la MIDlet sur le téléphone : sans celui-ci l’installation sera impossible. Ce fichier ressemble beaucoup au fichier JAD. Sun a défini des règles très strictes à respecter lors de la génération de ce fichier (cf. Remarques dans le paragraphe précédent).

A l'exception des fichiers .class, il est possible d'accéder à des ressources stockées dans le Jar (divers types de fichiers...). Ceci se fait grâce à la méthode java.lang.Class.getResourceAsStream(String) qui renvoie la ressource en sous la forme d'un java.io.InputStream.

Exemples

Lire le fichier res.txt qui se trouve dont le chemin dans le jar est /res/txt/res.txt
    InputStream is = getClass().getResourceAsStream(/res/txt/res.txt );

On peut aussi lire une image grâce à la méthode suivante:
    Image img = Image.createImage("/PATH");   

La génération du Jar est semblable à celle d'un programme Java standard mais avec une phase supplémentaire (la pré-vérification).

Etape 1: Pre-processing
Dans le monde de la programmation Java ME, souvent les développeurs ont recours à l'utilisation d'un pré-processeur afin de faire face à la problématique de portabilité des applications sur les différents mobiles que l'application doit couvrir. Le préprocesseur prend en entrée un fichier Java avec des directives de précompilation (#if, #else...) et fournit en sortie un fichier Java standard.

Exemple
Voici un bout de programme Java qui contient des directives de pré-compilation. En fonction du choix du développeur, on affectera à la variable message soit "Bonjour le monde!" soit "Hello World!":

    String message = null;
#if FR
    message = "Bonjour le monde!";
#elif EN
    message = "Hello World!";
#endif

Utilisation sous Linux:
        Pour que le message soit en français ou en anglais, il faudra utiliser respectivement soit l'option -DFR soit -DEN

$ cpp -P -DFR MyClass.java.c -o MyClass.java


Notes
Sous Netbeans, un pré-processeur est intégré au module Java ME, on peut l'utiliser directement dans le code (réf. Netbeans et Java ME).
Autres méthodes similaires au preprocesseur pourraient être utilisées (m4, conditionnement Java...)

Etape 2: Compilation
La compilation d'un programme Java se fait avec la commande javac, il suffit d'utiliser l'option -bootclasspath pour dire au compilateur que les fichiers .class resultantes seront executées dans un environnement MIDP/CLDC. Le compilateur prend en entrée un fichier .java et fournie en sortie un fichier .class.

Exemple
$ javac -bootclasspath myMidlet.java /home/ry/lib/midpapi10.jar:/home/ry/lib/cldcapi10.jar

Etape 3: Obfuscation

L'obfuscation est une action sur un programme généré (ici les fichiers .class) qui sert essentiellement à:
  • protéger le code du reverse engineering
    • renommage des identifiants
    • modification de la visibilité des variables
    • renommage des classes
    • ...
  • optimiser les binaires générés
    • suppression du code inutil 
    • suppression des commentaires 
    •  ...

    L'outil le plus utilisé dans le monde Java ME est Proguard (http://proguard.sourceforge.net/). Il s'agit d'un programme Java qui permet d'obfusquer un autre programme Java. Il possède différents niveaux d'obfuscation.

Exemple :

            On pourrait lancer Proguard avec les options suivantes pour obfusquer une application (Pour plus de détail cf. http://proguard.sourceforge.net/).

-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
-libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-microedition
-keep public class mypackage.MyMIDlet

Remarques:
  • Ne jamais utilisé l’obfuscateur lors de la phase de développement (surtout débogage) parce que javac ne saura pas vous donnez la bonne ligne qui génère l’erreur vu que ce type d'information est aussi supprimé par l'obfuscateur.
  • Certaines options de Proguard ne sont pas acceptées par quelques mobiles (BlackBerry)
  • L'obfuscation agit sur tout le code sauf la classe qui étend MIDlet d'où l'intérêt de mettre le minimum d'information dans celle ci (protection contre le reverse engineering).
  • L'obfuscation ne supprime pas les ressources non utilisées (images, son, fichiers...)


Etape 4: Pré-verification

    Il s'agit d'une étape spécifique au monde Java ME (cette phase se fait à l'exécution pour un programme Java SE). Elle permet de s'assurer que le bytecode Java est conforme à une liste de règles et introduit des annotations, dans les bytecode, indispensables à l'execution de la MIDlet par la VM. Sun fournit un outil pour effectuer cette étape, il s'agit de l'exécutable "preverify". Proguard permet aussi de le faire grâce à l'option (-microedition).

Exemple:
$ preverify -classpath /home/ry/lib/midpapi10.jar:/home/ry/lib/cldcapi10.jar  -d . myMidlet
 
Etape 5: Packaging

    La phase finale est la génération des fichiers finaux indispensables pour l'installation et l'exécution sur mobile. Il s'agit du fichier de description .jad et du fichier archive .jar (cf. Jar & Jad). Le fichier Jad est un simple fichier texte qu'on peut créer à la main alors que je fichier .jar doit être créé avec l'utilitaire de Sun "jar".

Exemple:
$ jar cvmf manifest.mf myJar.jar myMidlet.class

No comments:

Post a Comment