La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Java mobile Hugues Sansen Formation ITIN.

Présentations similaires


Présentation au sujet: "Java mobile Hugues Sansen Formation ITIN."— Transcription de la présentation:

1 Java mobile Hugues Sansen Formation ITIN

2 Hugues Sansen Fondateur de la société Peer2Phone, éditeur du logiciel de convergence fixe mobile GoSIP et du portail de téléphonie éponyme ( Fondateur et CEO de SHANKAA, opérateur télécoms, Secrétaire général du club des utilisateurs Java. Conseil en stratégie et en stratégie d’innovation. Formation ITIN

3 Objectif de ce cours à la fin de ce cours :
vous connaîtrez les solutions pour développer des applications Java sur les mobiles, l’architecture de la technologie Java Micro Edition et l’API de base MIDP. Vous explorerez les possibilités de MIDP au cours du développement d’une MIDlet, application Java ME pour mobile . Formation ITIN

4 Agenda Quelles sont les performances Java de votre téléphone : TastePhone notre première MIDlet, Hello world. les solutions pour développer en Java sur mobile, J2ME : CLDC CDC la machine virtuelle CLDC HotSpot MIDP Faisons évoluer notre application. Formation ITIN

5 Testez les capacités java de votre téléphone
TastePhone de Thibaut Régnier : L’application de référence mondiale pour tester les capacités Java de votre téléphone : sur directement sur wap.club-java.com ou ou recherchez votre mobile sur : Formation ITIN

6 Notre première application J2ME Hello World
Chargez J2ME et la documentation des APIs correspondantes Chargez NetBeans, avec l’extension pour mobile. Chargez le Wireless Toolkit : WTK… Créez un « projet mobile » et une « application mobile ». Regardez le programme Hello proposé en exemple. Testez votre application dans l’émulateur. Chargez la MIDlet sur votre mobile. Formation ITIN

7 Notre première application J2ME Hello World
examinons le code Formation ITIN

8 * * HelloMidlet.java * Created on 1 octobre 2006, 12:09 */ package hello; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; /** Hugues Sansen public class HelloMidlet extends MIDlet implements CommandListener { /** Creates a new instance of HelloMidlet */ public HelloMidlet() { } private Form helloForm; private StringItem helloStringItem; private Command exitCommand; /** This method initializes UI of the application. private void initialize() { // Insert pre-init code here getDisplay().setCurrent(get_helloForm()); // Insert post-init code here /** Called by the system to indicate that a command has been invoked on a particular displayable. command the Command that ws invoked displayable the Displayable on which the command was invoked */ public void commandAction(Command command, Displayable displayable) { // Insert global pre-action code here if (displayable == helloForm) { if (command == exitCommand) { // Insert pre-action code here exitMIDlet(); // Insert post-action code here } // Insert global post-action code here /** * This method should return an instance of the display. public Display getDisplay() { return Display.getDisplay(this); * This method should exit the midlet. public void exitMIDlet() { getDisplay().setCurrent(null); destroyApp(true); notifyDestroyed(); Formation ITIN

9 /** This method returns instance for helloForm component and should be called instead of accessing helloForm field directly. Instance for helloForm component */ public Form get_helloForm() { if (helloForm == null) { // Insert pre-init code here helloForm = new Form(null, new Item[] {get_helloStringItem()}); helloForm.addCommand(get_exitCommand()); helloForm.setCommandListener(this); // Insert post-init code here } return helloForm; /** This method returns instance for helloStringItem component and should be called instead of accessing helloStringItem field directly. Instance for helloStringItem component public StringItem get_helloStringItem() { if (helloStringItem == null) { helloStringItem = new StringItem("Hello", "Hello, World!"); return helloStringItem; /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. Instance for exitCommand component */ public Command get_exitCommand() { if (exitCommand == null) { // Insert pre-init code here exitCommand = new Command("Exit", Command.EXIT, 1); // Insert post-init code here } return exitCommand; public void startApp() { initialize(); public void pauseApp() { public void destroyApp(boolean unconditional) { Formation ITIN

10 Regardons les exemples
Créez un projet, importez un WT project Formation ITIN

11 Regardons les exemples
Dans le WTK choisissez l’application BluetoothDemo Formation ITIN

12 Regardons les exemples
lancez l’application deux fois, en mode serveur et en mode client dans le serveur, sélectionnez les images à publier, dans le client, lancez une recherche, acceptez une des images proposées. Formation ITIN

13 Regardons les exemples
Chargez l’exemple 3D demo lancez le jeux de la vie Formation ITIN

14 Java mobile, introduction
Il existe plusieurs options pour déployer du JAVA embarqué: J2ME : SUN, Esmertec etc.. votre machine virtuelle ex : ewe ( machine virtuelle opensource utilisée dans les ordinateurs de voiture (GM) et dans Peer2Phone (même environnement sur PC, Mac, Linux, Windows mobile), permet d’utiliser des dll. Mysaifu JVM (windows mobile), GPLv2 IST ( : fournit des micro JVM personnalisées, XML est intégré dans la VM pour de meilleures performances. Formation ITIN

15 Java Mobile Edition, SUN
Formation ITIN

16 Java Mobile Edition Java ME a été conçu par SUN pour fonctionner dans les contraintes imposées par les petits appareils et les mobiles. Il retient les bases de Java et permet de développer des applications sur des appareils limités en taille mémoire, en capacité de calcul, de visualisation et de batterie. La plate-forme Java ME regroupe des technologies et des spécifications afin de construire un environnement d’exécution pour répondre aux besoins d’appareils ou de marchés particuliers. Ceci permet la diffusion du même environnement sur différentes plates-formes afin de permettre une industrialisation du déploiement d’applications dans des environnements différents. Formation ITIN

17 Java Mobile Edition La technologie Java Mobile Edition repose sur trois éléments : Une configuration offre un ensemble de base de librairies et de capacité de machine virtuelle pour une large gamme d’appareils. un profile est un ensemble d’API qui s’applique à une gamme plus étroite d’appareils. des paquetages optionnels, qui regroupent un ensemble d’API spécifiques à une technologie. Formation ITIN

18 Java Mobile Edition La plate-forme Java ME a été divisée en deux types de configurations : l’une pour les petits appareils mobiles, appelée « Connected Limited Device Configuration » (CLDC) et l’autre pour des appareils mobiles plus évolués comme les smart phones et les set-top box (boîtier canal plus) appelée « Connected Device Configuration » (CDC). Formation ITIN

19 Java Mobile Edition, CLDC
La configuration pour les appareils mobiles à ressources réduites est appelée Connected Limited Device Configuration (CLDC). Elle a été spécifiquement conçue pour remplir les besoins d’exécution d’applications sur les appareils limités en mémoire, capacité de calcul et capacité graphique. Sur les mobiles on associe généralement le Mobile Information Device Profile (MIDP) qui fournit un environnement complet au développement d’applications pour les téléphones mobiles. Les applications reposent ainsi sur la configuration et le profile. CLDC et MIDP représentent l’environnement le plus courant et les applications de cet environnement sont appelées MIDlet. Une MIDlet est une application Java dont le champ peut couvrir les jeux, les applications métier comme d’autres domaines (plan de métro interactif, calcul de marée, interaction avec un serveur Bluetooth etc.). Ces applications peuvent ainsi être exploitée sur toutes les plates-formes qui respectent les spécifications Java ME. Une MIDlet peut-être téléchargée depuis un serveur accessible par WAP, Bluetooth etc. wap.club-java.com les bornes Velib munies de Bluetooth. Formation ITIN

20 Java Mobile Edition, CLDC
La technologie J2ME est délivrée en API appelée configurations, profils et paquetages optionnels. L’environnement d’une application J2ME comprends à la fois : une configuration comme CLDC et un profil comme Mobile Information Device Profile (MIDP). De plus des paquetages additionnels apportent des fonctionnalités spécifiques supplémentaires comme le wireless messaging, la capture multimédia et le playback. La possibilité de choisir parmi différentes API permet aux concepteurs et aux développeurs d’applications d’adapter les capacités de leur logiciels à celles des machines cibles. Ils peuvent utiliser des API qui leur donnent un accès facilité aux composants de certains types d’appareils, sans la surcharge d’API conçues pour des fonctionnalités que l’appareil ne supporte pas. Formation ITIN

21 Java Mobile Edition, CLDC
La configuration CLDC Une configuration apporte les librairies de base et les fonctionnalités de la machine virtuelle nécessaire à l’implantation de chaque environnement J2ME. Quand il est couplé à un ou plusieurs profils, le « Connected Limited Device Configuration » donne au développeur une plate-forme solide pour la création d’applications d’électronique grand public et d’applications embarquées. Profils Un profil est une ensemble d’API standard qui supportent une catégorie déterminée d’appareils à l’intérieur d’une configuration donnée. Un profil spécifique est couplé à une configuration comme CLDC pour apporter un environnement Java pour une classe donnée d’appareil. MIDP est un profil pour mobile qui avec CLDC apporte un environnement parfaitement adapté au développement d’applicaiton sur mobile. Paquetages Optionnels Un paquetage optionnel est un ensemble d’APIs adapté à une technologie spécifique qui étendent les fonctionnalités. CLDC supporte un certain nombre de paquetages optionnels qui permettent au concepteur d’applications d’adapter précisément les besoins de son application aux ressources physiques disponibles. Les paquetages optionnels de CLDC incluent : Wireless Messaging API (WMA) et Mobile Media API (MMAPI). Formation ITIN

22 Java Mobile Edition, CLDC
Objectifs La spécification CLDC a pour but de standardiser une plate-forme Java hautement portable avec une empreinte minimale pour les appareils connectés à ressources contraintes. Il est développé au travers du « Java Community Process (JCP) » qui regroupe 500 membres dont des opérateurs de téléphonie mobile, des constructeurs de téléphones mobiles et des éditeurs de logiciels. CLDC a été conçu en gardant les objectifs suivant à l’esprit : La réduction de l’empreinte à un niveau acceptable pour un déploiement mass-market, La facilitation de la portabilité par l’abstraction des opérations natives du système au travers d’API standardisées. Étendre les fonctionnalités en permettant un téléchargement dynamique d’applications. Formation ITIN

23 Java Mobile Edition, CLDC
Target Devices La configuration CLDC est conçue pour apporter les avantages de la plate-forme Java aux appareils connectés dotés de capacités de calcul et graphiques limités : les téléphones mobiles, les pageurs, les organiseurs personnels de base et les équipement machine-to-machine. De plus la configuration CLDC peut aussi être déployée sur les appareils de maisons comme les set-top boxes TV et les terminaux point de vente. Les cibles ont généralement les capacités suivantes : un processeur 16-bit or 32-bit cadencés à 16MHz ou plus, au moins 160kB de mémoire non volatile dédiée aux librairies CLDC et à la machine virtuelle au moins 192kB de mémoire disponible pour la plate-forme Java, une consommation électrique faible, généralement alimenté par batterie, une connectivité à un type donné de réseau, généralement sans fil et intermittente avec une bande passante limitée. Formation ITIN

24 L’implantation CLDC HotSpot de SUN
La première génération de machines virtuelles du CLDC et dont les développement se poursuivent, était la KVM (Kilo Virtual Machine). Sun a développé une nouvelle machine virtuelle optimisée pour les déploiement commerciaux appelée la Sun CLDC HotSpot Virtual Machine. Elle a pour objectif d’améliorer les performances en minimisant l’empreinte mémoire. Elle apporte un gain en performance doublé par rapport à la KVM tout en réduisant l’empreinte mémoire. Elle respecte les spécification CLDC et inclut un certain nombre de fonctionnalités brevetées qui accélèrent l’exécution et utilise les ressources plus efficacement. Elle est disponible sur un certain nombre de machines ce qui permet aux fabricants de matériels de réduire substantiellement les délais de mise sur le marché. Formation ITIN

25 CLDC HotSpot Implementation de SUN
J2ME s’inscrit dans la famille des éditions Java comme J2SE et J2EE. La KVM (kilo VM) est la machine virtuelle originellement déployée sur les petits appareils à batterie. La KVM supportait le « Mobile Information Device Profile (MIDP) » Formation ITIN

26 Les challenges de la VM CLDC HotSpot de SUN
Vitesse contre empreinte. Il y a un conflit entre la vitesse d’exécution et les besoins en mémoire (empreinte mémoire). Comment concevoir un compilateur dynamique rapide sans faire exploser les coûts de mémoire? Le portage tel quel de la technologie HotSpot disponible sur les PC auraient résulté en une empreinte mémoire trop importante pour les appareils grand public à batterie. De la bonne gestion du cache. La mémoire augmente le coût des appareils tandis que la loi de Moore tente les développeurs à gaspiller de la mémoire. Plus de mémoire augmente aussi la consommation des appareils avec un impact important sur la batterie. L’implantation du CLDC HotSpot a eu pour principal objectif de conception de garantir une utilisation optimale du cache de telle façon que la pile puisse tenir dans le cache primaire (dans le processeur) ou additionnel. Cette disposition améliore la tenue de la batterie en évitant les écritures et lectures sur la mémoire principale. Les objectifs de conception d’une bonne gestion du cache impliquent les stratégies suivantes: concevoir une machine virtuelle avec des objets les plus compacts possibles, l’utilisation d’un ramasse-miettes générationnel qui ne touche la mémoire que localement, garder le code compilé dans le tas des objets ou il sera facilement repositionné et effacé Améliorer la durée de la batterie. L’amélioration de la vitesse d’exécution de la machine HotSport du CLDC a un impact direct sur la durée de la batterie : une exécution plus rapide consomme moins d’énergie. Le besoin d’adapter les paramètres. Une conception de haut niveau doit se faire en considérant les appareils réels: Le comportement du cache varie énormément d’un appareil à l’autre, La conception de la machine HotSpot du CLDC permet un réglage par famille d’appareil. Formation ITIN

27 L’implémentation de la VM CLDC HotSpot de SUN
Une véritable machine virtuelle 32 bits Ce qui lui procure un espace d’adressage important et évolutif et une architecture bien adaptée aux téléphones depuis le milieu de gamme jusqu’au haut de gamme. Une organisation compacte des objets L’implantation de la machine virtuelle HotSpot supporte une organisation compacte des objets ce qui diminue la consommation mémoire. Un objet est composé : d’une entête qui donne les informations de réflexivité, le hashcode et les statuts de verrouillage, d’un corps qui contient les champs de l’objet. La plupart des machines virtuelles utilisent des entêtes de deux mots. Mais comme la taille moyenne des objets est faible, l’entête occupe un pourcentage important de son empreinte mémoire. La machine HotSpot CLDC n’utilise qu’un seul mot. L’empreinte des objets est non seulement plus faible mais cette approche permet aussi des allocations mémoires plus rapides. Une gestion unifiée des ressources Toutes les données allouées résident dans le tas dont : Les objets Java les objets réflectifs comme les méthodes et les classes, le code généré par le compilateur, Les structures de données internes à la machine virtuelle. L’unification des ressources a pour avantage de permettre au ramasse-miettes de nettoyer toutes les ressources allouées et même le code compilé. A l’opposée, la plupart des machines virtuelles désignent des espaces pour les objets, les données réflectives, les données temporaires et le code généré. Ceci résulte dans une fragmentation de la mémoire, des stratégies de nettoyage multiple etc. La machine virtuelle HotSpot CLDC résout ce point par l’utilisation d’un ramasse-miettes unique qui marque, nettoie et compacte. L’espace du code compilé peut aussi être récupéré dynamiquement pour y allouer des objets créés par l’utilisateur. Formation ITIN

28 L’implantation de la VM CLDC HotSpot, le ramasse-miette
Un ramasse-miettes libère automatiquement la mémoire des objets qui ne sont plus pointés pour de nouvelles allocations. La machine HotSpot de CLDC utilise un ramasse- miettes qui marque, nettoie et compacte avec pour résultat : une allocation de mémoire plus rapide, des pauses nettoyage courtes, pas de fragmentation de la mémoire. Précision Un ramasse-miettes précis mémorise tous les pointeurs au moment du nettoyage : La récupération de la mémoire des objets inaccessibles est fiable, Tous les objets peuvent être repositionnés, ce qui permet de compacter la mémoire et élimine la fragmentation. La fragmentation sur des espaces mémoire contraints peut conduire à des fuites mémoire imprévisibles. Un ramasse-miettes qui marque, nettoie et compacte La VM HotSpot utilise une ramasse-miettes bi-générations. Le tas des objets est divisé en génération ancienne, nouvelle génération et mémoire libre. La génération ancienne contient les objets qui ont été gardés lors du précédent nettoyage/compactage. Les nouveaux objets sont alloués dans le segment de la nouvelle génération, généralement plus petit. Le ramasse-miettes se lance quand le segment de la nouvelle génération est complet et récupère la mémoire disponible. Quand toute la mémoire du tas est occupée, la ramasse-miettes passe sur tout le tas et compacte les objets pointés dans une « nouvelle » ancienne génération. Ce nettoyage complet induit une pause notable mais peu fréquente. Cette approche repose sur la remarque que la plupart des objets sont à vie courte. Comme la plupart des objets sont à vie courte, seule une faible portion des objets sont promus dans l’ancienne génération. La plupart des passages du ramasse-miettes ne se font que sur la nouvelle génération résultant dans des pauses courtes. de Wikipedia : allocation mémoire Allocation sur la pile L'exécution d'un programme est généralement structurée autour d'une pile contenant les cadres d'appel à des fonctions (ou procédures) du langage de programmation utilisé. Schématiquement, les variables lexicales, c'est-à-dire les variables définies dans la portée textuelle d'une fonction, sont donc allouées lors de l'entrée dans la fonction, et désallouées automatiquement lors de la sortie (du retour) de la fonction. Un segment mémoire, dit segment de pile, est utilisé pour ces allocations/désallocations. Aucun mot clef n'est nécessaire dans le code source d'un langage supportant la notion de variable lexicale : celles-ci sont allouées et libérées selon la discipline de pile par définition. Certains langages, comme C ou C++, parlent de variables locales ou automatiques au lieu de variables lexicales, mais il s'agit de la même chose. Allocation sur le tas La plupart des programmes ayant des besoins en mémoire dépendant de l'usage qu'on en fait, il est nécessaire de pouvoir, à des moments arbitraires de l'exécution, demander au système l'allocation de nouvelles zones de mémoire, et de pouvoir restituer au système ces zones (désallouer la mémoire). Dans ce cas, l'allocation et la libération de la mémoire sont sous la responsabilité du programmeur. Les fuites de mémoire, ainsi que d'autres erreurs fréquentes dans les programmes à gestion manuelle de la mémoire, ont leur source dans les erreurs d'allocation mémoire sur le tas. Classiquement, les fonctions de la bibliothèque standard de C malloc et free, les opérateurs du langage C++ new et delete permettent, respectivement, d'allouer et désallouer la mémoire sur le tas. Les langages de programmation dotés de ramasse-miettes utilisent, mais de façon transparente pour le programmeur, l'allocation sur la pile et les primitives alloc/free. Dans ce dernier cas, le ramasse-miette permet d'éviter les erreurs liées à l'allocation sur le tas, à l'exception de certaines fuites de mémoire... Comparaison L'allocation statique est la méthode la plus sûre dans le sens où : la quantité consommée est constante et complètement connue avant l'exécution, elle est généralement accessible exclusivement en lecture seule (non modifiable). C'est toutefois une méthode très inflexible et insuffisante pour les programmes dont les besoins peuvent varier de façon imprévisible : pour un programme ayant des besoins potentiels de mémoire importants, l'allocation statique conduirait à un gaspillage. Elle est finalement essentiellement utilisée pour stocker des constantes ou des valeurs calculées et disponibles au moment de la compilation. L'allocation sur la pile représente un bon compromis : la quantité consommée est proportionnelle aux paramètres d'entrées du programme, qui déterminent la profondeur de la pile et donc la quantité allouée ; elle peut être connue avant l'exécution par une analyse de la complexité algorithmique, il n'y a pas de fuite de mémoire, du fait de la libération implicite (respectant la discipline de pile). L'allocation sur la pile doit être choisie en priorité lorsque les besoins mémoires sont connus à l'avance et sont proportionnels à certains paramètres d'entrée du programme. L'allocation et la libération consécutives, selon une discipline de pile, de grosses quantités de mémoire peuvent toutefois poser des problèmes de performance et de lisibilité du source (explosion du nombre de paramètres passés aux fonctions) ; ces problèmes sont à mettre dans la balance contre l'assurance d'une libération correcte des ressources mémoire. L'allocation sur le tas, puisqu'elle permet le contrôle complètement arbitraire de l'allocation et de la libération, offre le plus de possibilités. Les ressources allouées manuellement ont cependant une durée de vie indéfinie, c’est-à-dire que le programmeur a la responsabilité de la libération (et doit éviter de tomber dans les pièges de la double libération, etc.). La mémoire allouée sur le tas peut également être référencée par des variables globales (de préférence confinées dans un espace de noms), ce qui peut aider à délester un groupe de fonctions de paramètres communs. En pratique, on préfèrera le mode d'allocation le plus simple. La plupart du temps, l'allocation sur la pile est suffisante. On n'utilise l'allocation sur le tas qu'en dernier recours, pour manipuler des structures de données complexes et/ou dont l'évolution ne suit pas la discipline de pile. Dans les langages à ramasse-miettes, le choix du mode d'allocation est réalisé par le compilateur, en fonction d'une analyse des patterns d'utilisation des variables dans le code source. Formation ITIN

29 L’implémentation de la VM CLDC HotSpot de SUN
Tracer les pointeurs entre générations Les ramasse-miettes générationnels doivent garder la trace des références des générations anciennes jusqu’à la nouvelle génération de telle façon que les jeunes générations puissent être nettoyées sans avoir à inspecter chaque objet des anciennes générations. L’ensemble de localisations contenant potentiellement de nouveaux objets est souvent appelé « remembered set ». A chaque nouvel enregistrement, le système doit garantir que le nouvel espace est bien alloué dans le « remembered set » si un objet ancien référencie un nouvel objet. Ce mécanisme est appelé barrière d’écriture (write barrier). Allocation Rapide Le compactage permet d’allouer de nouveaux objets de manière contiguë comme dans une pile. L’allocation de mémoire se réduit à augmenter un pointeur. Formation ITIN

30 La VM CLDC HotSpot de SUN, la machine d’éxecution
En général, les machines virtuelles Java à compilateur sont plus rapides que celles n’utilisant qu’un interpréteur. Aussi la VM HotSpot CLDC comporte-t-elle un compilateur dynamique qui apporte une exécution rapide du bytecode. La compilation de bytecode en instruction native prend entre 4 et 8 fois l’espace du bytecode originel. La compilation adaptative contourne ce problème en compilant uniquement les méthodes les plus utilisées : les hotspots. La VM identifie les hotspots avec un profileur statistique. Pour minimiser la quantité de code compilé, la VM HotSpot utilise un interpréteur optimisé pour les méthodes peu utilisées. Le compilateur de la VM HotSpot optimise le code en une simple passe en recourant : au précalcul des constantes (constant folding), la propagation des constantes, l’éclatement des boucles. In compiler theory, constant folding and constant propagation are related optimization techniques used by many modern compilers. A more advanced form of constant propagation known as sparse conditional constant propagation may be utilized to simultaneously remove dead code and more accurately propagate constants. Constant folding is the process of simplifying constant expressions at compile time. Terms in constant expressions are typically simple literals, such as the integer 2, but can also be variables whose values are never modified, or variables explicitly marked as constant. Constant propagation is the process of substituting the values of known constants in expressions at compile time. Such constants include those defined above, as well as intrinsic functions applied to constant values. Loop splitting (or loop peeling) is a compiler optimization technique. It attempts to simplify a loop or eliminate dependencies by breaking it into multiple loops which have the same bodies but iterate over different contiguous portions of the index range. A useful special case is loop peeling, which can simplify a loop with a problematic first (or first few) iteration by performing that iteration separately before entering the loop. Here is an example of loop peeling. Suppose the original code looks like this: p = 10; for (i=0; i<10; ++i) { y[i] = x[i] + x[p]; p = i; } In the above code, only in the 1st iteration is p=10. For all other iterations p=i-1. We get the following after loop peeling: y[0] = x[0] + x[10]; for (i=1; i<10; ++i) { y[i] = x[i] + x[i-1]; } Formation ITIN

31 La VM CLDC HotSpot, Synchronisation rapide des threads
Le langage Java offre un mécanisme de synchronisation des Threads qui permet de développer des programmes avec un verrouillage à faible granularité. La VM HotSpot utilise une variante de du mécanisme de verrouillage structuré par block. Les performances s’en trouvent tellement améliorées que la synchronisation ne représente plus un goulot d’étranglement pour les programmes Java. Formation ITIN

32 Java Mobile Edition, CDC : Connected Device Profile
Formation ITIN

33 Java Mobile Edition, CDC
La configuration Connected Device Profile (CDC) cible les appareils avec plus de capacité et doté de connexion réseau comme les PDA haut de gamme, les set-top boxes avec pour objectif de se rapprocher des possibilités de Java SE en respectant les contraintes de leur ressources. La configurations CDC apporte aux différents utilisateurs de la chaîne de valeur : Les entreprises bénéficient de l’utilisation d’applications connectées pour étendre leur capacité business aux clients, partenaires et collaborateurs mobiles, Les utilisateurs bénéficient de la compatibilité et de la sécurité apportés par la technologie Java, Les développeurs bénéficient de la productivité de Java et de ses bibliothèque d’API, La configuration CDC retient 3 profils différents: la Foundation Profile (JSR 219) , Le Personal Basis Profile (JSR 217), Le Personal Profile (JSR 216). Formation ITIN

34 A CDC Java Runtime Environment
Le standard CDC offre une grande flexibilité pour le développement d’applications. Le concepteur pour PDA peut intégrer un profil, le paquetages optionnels RMI (Remote Method Invocation) et Java Database Connectivity (JDBC™). Attention, des produits intégrant des différents produits CDC peuvent utiliser des API différentes bien que conforme au standard CDC. Les choix faits par le concepteur de produit déterminent les API à utiliser par le développeur d’applications CDC. Formation ITIN

35 CDC Technical Overview
CDC Class Library CDC contient des librairies dérivées de Java SE mais adaptées aux appareils connectés. Les librairies incluent des classes utilisées par les développeurs dans de nombreuses applications pour PC et serveurs. Certaines interfaces ont été modifiées. CDC permet ainsi un portage rapide des applications classiques sur les mobiles. CDC HotSpot™ Implementation La machine virtuelle Hotspot CDC a été développée spécialement pour les appareils connectés. Survol de l’API CDC L’examen comparatif des différents profils disponibles Foundation Profile, Personal Basis Profile, and Personal Profile est utile pour la conception d’une application CDC. Le Foundation Profile apporte un ensemble de classes de base. Les autres profils étendent le Foundation Profile avec des fonctionnalités spécifiques. Formation ITIN

36 CDC et Sécurité La sécurité est un des points essentiel de la technologie Java. Elle a guidé les évolutions de la plate-forme Java. CDC propose différents niveaux de sécurité qui apportent aux utilisateurs, aux développeurs, aux fournisseurs de services et aux entreprises un environnement particulièrement sécurisé. La sécurité de la VM inclut la vérification des classes à l’utilisation et masquent les pointeurs. Ceci a éliminé les risques de débordement de la pile. Les livraisons initiales de Java utilisaient un modèle simple de sécurité : le bac à sable, offrant une sécurité bien adaptée au browser web. Les classes signées étendent le bac à sable en vérifiant l’origine des classes Java à charger. Les politiques de sécurité ont été introduites dans J2SE 1.2. Elles apportent un meilleur contrôle de la sécurité. Une politique de sécurité est un ensemble de permissions et de politiques qui peuvent être modifiées par l’administrateur système au déploiement. Le Cryptage apporte un modèle standard de codage du logiciel et des données pour sécuriser le transfert et l’archivage. Il inclut Java Cryptography Architecture (JCA), un environnement standard de cryptage. CDC inclut le framework de cryptage de Java SE. Celui-ci est extensible car indépendant des algorithmes et inter opérable dans la mesure où il utilise différentes implantations de services de sécurité. Le Foundation Profile (JSR 219) intègre trois paquetages optionnels : Java Authentication and Authorization Service (JAAS). Offre un canevas d’authentification et d’autorisation. Le composant d’autorisation spécifie le contrôle d’accès au code, aux signatures de code dans les fichiers de politique qui peuvent être maintenus par l’administrateur système. A l’exécution, l’environnement apporte différents modules tels que le stockage de clés sans avoir à modifier l’application. Java Cryptography Extension (JCE). Étend le JCA et apporte le cryptage, la génération de clés, l’autorisation de clés et les services Messages Authentication Code (MAC) Java Secure Socket Extension (JSSE). Apporte les Secure Socket Layer (SSL). Formation ITIN

37 Java ME Platform for Converged Services
Formation ITIN

38 Java ME Platform for Converged Services
La plate-forme Java ME Platform for Converged Services permet de faire converger Java SE sur les environnements CLDC et CDC. Formation ITIN

39 Le profil MIDP, Mobile Information Device Profile
Formation ITIN

40 MIDP, Mobile Information Device Profile, pour CLDC
Le Mobile Information Device Profile (MIDP) est l’élément de base de la plate-forme Java (Java ME). MIDP apporte un environnement de base pour la plupart des téléphones mobiles et des PDA. MIDP a été défini par un Java Community Process regroupant plus de 50 sociétés (constructeurs, opérateurs mobiles et éditeurs). Il définit une plate-forme pour déployer dynamiquement et en toute sécurité des applications optimisées, graphiques et connectées. Ensemble, CLDC et MIDP apportent les fonctionnalités requises par les applications mobiles sous la forme d’API standardisées. Le développeur peut facilement déployer ses applications sur différents types de terminaux. MIDP est largement adopté pour le développement d’applications sur mobiles et PDA. Formation ITIN

41 MIDP, les spécifications
Le MIDP 1.0 (JSR 37) apporte les fonctionnalités centrales requises par les applications sur mobile avec interface utilisateur et sécurité réseau de base. MIDP 2.0 (JSR 118) étend MIDP 1.0 avec une interface utilisateur étendue des fonctionnalités multimédia et jeu étendues, une connectivité plus riche, le téléchargement d’application en ligne (OTA) et une sécurité complète. MIDP 2.0 est compatible MIDP 1.0. Formation ITIN

42 L’interface utilisateur étendu de MIDP2
MIDP 2.0 apporte : Un nouveau Popup ChoiceGroup, plus visuel, Les objets graphiques peuvent avoir leur propre ensemble de commande. Les écrans d’alerte permettent de poser des questions à l’utilisateur. Les jauges peuvent être intégrées aux écrans d’alerte. Une disposition des objets graphiques plus flexible pour une meilleure portabilité. Une extensibilité supérieure, avec la possibilité d’intégrer des objets graphiques personnalisés Custom Items, que le développeur peut utiliser pour décrire ses propres objets comme les visionneurs de cartes et autres composants d’interface utilisateur. Formation ITIN

43 Support du Multimédia de MIDP2
MIDP 2.0 intègre l’ Audio Building Block (ABB) qui fait partie du paquetage optionnel Mobile Media API (MMAPI). ABB permet au développeur d’ajouter des tonalités, des séquences de tonalités et des fichiers WAV, sans avoir à importer MMAPI. Sur les appareils intégrant MMAPI, les développeurs peuvent ajouter davantage de contenus multimédia comme des flux vidéo. Formation ITIN

44 Le support des Jeux dans MIDP2
MIDP 2.0 comprend l’API de jeux Game qui apporte les bases au développement de jeux sur mobiles. L’API MIDP Game comporte des fonctionnalités spécifiques au jeu comme les Sprites et les couches. Cette fonctionnalité apporte un meilleur contrôle du graphisme et des performances. Formation ITIN

45 Les capacité de connectivité de MIDP2
MIDP 2.0 apporte les connectivités au-delà de HTTP : HTTPS, Datagrammes, Sockets, serveur de Socket et communication par port série. Ces capacités de connectivité permettent une intégration standardisée avec les infrastructures familières aux développeurs Java. Formation ITIN

46 l’Architecture PUSH MIDP 2.0 intègre un modèle de serveurs Push auxquels les MIDlets peuvent s’enregistrer pour être activées quand le terminal reçoit des information d’un serveur. Le paramétrage de l’application est un combinaison de paramétrage par défaut du terminal et de l’utilisateur pour déterminer s’il faut avertir l’utilisateur, démarrer l’application automatiquement ou ne pas la démarrer quand une autre application est lancée. L’architecture PUSH permet aux développeurs de profiter des capacité de prise en compte des événements des terminaux et des réseaux des opérateurs mobiles. Ils peuvent facilement intégrer des alertes, de la messagerie et de la diffusion (broadcast) dans le cadre d’une approche standard de MIDP. Formation ITIN

47 Le téléchargement Over-the-air (OTA)
Une des avancées de MIDP réside dans la capacité maintenant imposée à déployer dynamiquement des applications et leurs mises à jour Over-The-Air (OTA). La spécification MIDP 2.0 définit comment les suites de MIDlets sont découvertes, mises à jour et effacée des terminaux. MIDP permet aussi au fournisseur de service d’identifier quelles suites de MIDlets fonctionnera sur un type donné de terminaux et d’obtenir un rapport à la suite d’installation, mise à jour ou de suppression. Le modèle de téléchargement OTA garantit une approche unifiée et standard de déploiement opérant sur une large gamme de terminaux. Le modèle a été défini et adopté par les principaux fabricants et éditeurs pour fournir une solution de téléchargement sure et sécurisée. Formation ITIN

48 Sécurité de bout en bout
MIDP 2.0 apporte un modèle de sécurité robuste. MIDP 2.0 supporte HTTPS et profite des standards comme SSL et WTLS pour le transfert sécurisé d’informations. La sécurité protège des accès non autorisés aux données, applications et autres ressources du réseau et du terminal. Par défaut les suites de MIDlets n’ont aucun privilège. Pour obtenir un accès, une suite de MIDlets doit être signée par une PKI X.509. Pour qu’une suite signée puisse être téléchargée, installée et munie d’autorisation elle doit être authentifiée avec succès. Formation ITIN

49 Les contraintes de la sécurité
Il est important de protéger les utilisateurs grand public des risques d’applications malveillantes : prise de contrôle de votre téléphone, usurpation d’identité et paiement par mobile. Pour des raisons de sécurité, vous ne pouvez pas faire n’importe quoi en Java ME par exemple pas de JNI. Formation ITIN

50 Les librairies de base de MIDP
Interface utilisateur javax.microedition.lcdui L’environnement de base d’interface utilisateur. javax.microedition.lcdui.game Facilite le développement de jeux sur mobile. Persistence javax.microedition.rms Un mécanisme simple et sécurisé de persistence. Application Lifecycle Package javax.microedition.midlet Définit l’interaction entre l’application est l’environnement Réseau javax.microedition.io La gestion des connexions. Audio javax.microedition.media Les outils de base pour créer un player. javax.microedition.media.control La commande du player. Public Key javax.microedition.pki Gestion des certificats utilisés en connexion sécurisée. Core Packages java.io Gestion des entrées sorties au travers des DataStreams.. java.lang Les classes de base de Java. java.util les collection classes, la date et le temps.. Formation ITIN

51 Les trucs Bien que toujours plus puissants, les mobiles n’en demeurent pas moins des appareils à ressources limitées. Sur un téléphone il est préférable de limiter le nombre de classes. Formation ITIN

52 Découverte de MIDP par l’exemple
Formation ITIN

53 Notre application : un chat Bluetooth en mode adhoc
Objectif : développer un logiciel de chat sur téléphone mobile. Les téléphones seront chacun connectés à deux autres téléphones. Les téléphones propageront les pseudos des utilisateurs connectés de telle façon que chacun puisse connaître les présents. Un message envoyé à un destinataire quelconque des connectés sera propagé de proche en proche jusqu’au destinataire. Un message ne peux pas être envoyé à celui qui l’a envoyé ou celui qui l’a relayé afin d’éviter les boucles. Formation ITIN

54 Etape 1 : création du projet HadHocChat
Dans le menu « File », créez un nouveau projet Mobile Application mobile Formation ITIN

55 Etape 1: création du projet HadHocChat
Ne cochez pas la case « create HelloMidlet », Nous nous servirons du canevas fourni par cette exemple. Formation ITIN

56 Etape 1: création du projet HadHocChat
renommez le paquetage « hello » en « adhoc » validez la propagation du changement renommez votre classe en « HadHocChat » modifiez les propriétés de votre projet: Dans Midlets, retirez la référence au projet HelloWorld, ajoutez votre classe HadHocChat Formation ITIN

57 Etape 2 : notre première interface de saisie
Formation ITIN

58 Etape 2 : écran d’accueil, saisie du pseudo
A l’aide de l’interface « screen design » de Netbeans : renommez le StringItem Hello retirez le texte remplacez le label avec notre message de bienvenue. renommez l’objet (Instance Name) par exemple « welcomeStringItem » ajoutez une barre de séparation : Spacer ajoutez un TextField qui sert à la saisie du pseudo, donnez un label nommez votre objet (Instance Name) ajoutez une ItemCommand pour sauver votre pseudo. glissez votre commande sur l’objet que vous souhaitez commandez nommez cette commande Label ex : save pseudo Instance name ex : savePseudoCommand testez votre application en lançant « run Project » dans la menu de votre projet Formation ITIN

59 Etape 2 : déployons notre application sur les mobiles
Netbeans enregistre les fichiers de déploiement dans le dossier dist (distribution). Notre application comprend deux fichiers : le .jad : java description, qui contient les paramètres de description de notre application accessibles dans Netbeans dans les propriétés du projet sous application descriptor, le .jar : java archive, qui contient notre exécutable. Ce sont ces deux fichiers que vous devez charger sur votre mobile. Formation ITIN

60 La persistence en MIDP : le RecordStore
Formation ITIN

61 Etape 3 : sauver le pseudo dans un RecordStore
Un RecordStore consiste en un ensemble d’enregistrements persistants. La plate-forme garantit l’intégrité des record stores des au travers des redémarrage, changements de batterie etc. Les record stores sont créés à des emplacements dépendants de la plate-forme et ne sont pas directement accessibles par les MIDlets. L’espace de nommage des record stores est contrôlé par la suite de MIDlets. Les MIDlets d’une suite peuvent créer autant de record stores que nécessaire pour autant qu’ils portent un nom différent. Quand une suite est détruite, les record stores associés le sont aussi. Les MIDlets d’une même suite peuvent accéder directement aux record stores créés par les MIDlet de la même suite. Pour des raisons évidentes de sécurité, une MIDlet ne peut accéder au record stores d’autres suites que si celles-ci l’ont explicitement autorisé. Un record store possède un nom unique donné par le nom de la suite et le nom donné explicitement dans le programme. Une suite est identifiée par le nom de l’éditeur et les attributs de nommage de la MIDlet définis dans le descripteur de l’application. Formation ITIN

62 Etape 3 : sauver le pseudo dans un RecordStore
Le contrôle d’accès d’un record store est défini à sa création. Il est vérifié à l’ouverture du record store. Le mode d’accès permet une utilisation privée ou partagée avec les MIDlet d’autres suites. La taille des noms des record stores va de 1 à 32. Ils différencient minuscules et majuscules. Il ne peut pas y avoir deux record store de même nom au sein de la même suite. Deux record stores de même nom dans deux suites différentes sont différents. RecordStore est un modèle simpliste de persistance. Il stocke des tableaux d’octets. Il ne possède pas de mécanisme de verrouillage. Si dans votre MIDlet plusieurs thread accèdent à la même donnée, il est de votre ressort d’en assurer l’intégrité. Vous pouvez réserver une partie de votre champ pour placer les informations de verrouillage qui vous sont nécessaires. Formation ITIN

63 Etape 3 : créer un RecordStore
/* la création et/ou l’ouverture la plus simple consiste à utiliser RecordStore.openRecordStore(« monRecordStore »,   true ) ce recordStore n’est pas partagé avec d’autres suites.*/ openRecordStore public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) throws RecordStoreException, RecordStoreFullException, RecordStoreNotFoundException Open (and possibly create) a record store associated with the given MIDlet suite. If this method is called by a MIDlet when the record store is already open by a MIDlet in the MIDlet suite, this method returns a reference to the same RecordStore object. Parameters: recordStoreName - the MIDlet suite unique name for the record store, consisting of between one and 32 Unicode characters inclusive. createIfNecessary - if true, the record store will be created if necessary Returns: RecordStore object for the record store Throws: RecordStoreException - if a record store-related exception occurred RecordStoreNotFoundException - if the record store could not be found RecordStoreFullException - if the operation cannot be completed because the record store is full IllegalArgumentException - if recordStoreName is invalid Formation ITIN

64 Etape 3 : créer un RecordStore
/*Enrichit le précédent. si authmode == AUTHMODE_PRIVATE, le record store est visible uniquement au sein de la même suite si authmode == AUTHMODE_ANY, le record store est visible par des MIDlet d’autres suites. si writable == true, les MIDlets d’autres suites peuvent aussi modifier le record store.*/ openRecordStore public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary, int authmode, boolean writable) throws RecordStoreException, RecordStoreFullException, RecordStoreNotFoundException Returns: RecordStore object for the record store Throws: RecordStoreException - if a record store-related exception occurred RecordStoreNotFoundException - if the record store could not be found RecordStoreFullException - if the operation cannot be completed because the record store is full IllegalArgumentException - if authmode or recordStoreName is invalid Since: MIDP 2.0 Formation ITIN

65 Etape 3 : créer un RecordStore
/*Enrichit le précédent. Permet d’ouvrir un record store créé par une MIDlet d’une autre suite. Si une MIDlet de la même suite a déjà ouvert le record store, les deux MIDlets se partagent le même objet Java. .*/ openRecordStore public static RecordStore openRecordStore(String recordStoreName, String vendorName, String suiteName) throws RecordStoreException, RecordStoreNotFoundException Parameters: recordStoreName - the MIDlet suite unique name for the record store, consisting of between one and 32 Unicode characters inclusive. vendorName - the vendor of the owning MIDlet suite suiteName - the name of the MIDlet suite Returns: RecordStore object for the record store Throws: RecordStoreException - if a record store-related exception occurred RecordStoreNotFoundException - if the record store could not be found SecurityException - if this MIDlet Suite is not allowed to open the specified RecordStore. IllegalArgumentException - if recordStoreName is invalid Since: MIDP 2.0 Formation ITIN

66 Etape 3 : créer un enregistrement
Un record store enregistre des tableaux d’octets ex : monRecordStore.addRecord(« maChaîne ».getBytes(),0, « maChaîne ».length) addRecord public int addRecord(byte[] data, int offset, int numBytes) throws RecordStoreNotOpenException, RecordStoreException, RecordStoreFullException Adds a new record to the record store. The recordId for this new record is returned. This is a blocking atomic operation. The record is written to persistent storage before the method returns. Parameters: data - the data to be stored in this record. If the record is to have zero-length data (no data), this parameter may be null. offset - the index into the data buffer of the first relevant byte for this record numBytes - the number of bytes of the data buffer to use for this record (may be zero) Returns: the recordId for the new record Throws: RecordStoreNotOpenException - if the record store is not open RecordStoreException - if a different record store-related exception occurred RecordStoreFullException - if the operation cannot be completed because the record store has no more room SecurityException - if the MIDlet has read-only access to the RecordStore Formation ITIN

67 Etape 3 : lire un enregistrement
On accède à un enregistrement en indiquant sont index dans le record store. Le premier enregistrement est à l’index 1 : byte[] enregistrement = monRecordStore.getRecord(1); accède au premier enregistrement de mon record store Il est possible de définir les octets auxquels on souhaite accéder ex : byte[] enregistrement = monRecordStore.getRecord(1,0,1); accède au premier octet d’un enregistrement dans lequel on peut mettre une indication de verrouillage par exemple. Formation ITIN

68 Etape 3 : modifier un enregistrement
pour modifier un enregistrement donné dans un record store, on spécifie son index et on modifie les octets voulus : byte[] bytes = monRecordStore. getRecord (1); bytes[0] = byte(1); monRecordStore.setRecord(1,bytes,0,bytes.length(); Cet exemple permet par exemple d’indiquer que cet enregistrement est verrouillé. Formation ITIN

69 Etape 3 : lire le pseudo précédemment enregistré
Au lancement de notre application nous récupérons le pseudo enregistré précédemment. Cette opération peut se faire dans la méthode initialize() après la création de la page d’accueil. On peut créer une variable globale (pseudoStore) pour le recordStore et pour une variable autre pour le pseudo (pseudo). Formation ITIN

70 Etape 3 : lire le pseudo précédemment enregistré
private void initialize() { // Insert pre-init code here try { pseudoStore = RecordStore.openRecordStore(pseudoStoreName,true); // sort en exception si pas de d’enregistrement byte[] pseudoBytes = pseudoStore.getRecord(1); if(pseudoBytes != null){ pseudo = new String(pseudoBytes); } } catch (RecordStoreException ex) { ex.printStackTrace(); getDisplay().setCurrent(get_helloForm()); // Insert post-init code here if(pseudo != null){ TextField pcf = get_pseudoCaptureField(); pcf.setString(pseudo); Formation ITIN

71 Etape 3 : sauvegarder un nouveau pseudo
la sauvegarde du nouveau pseudo se fera dans la méthode commandAction(Command command, Item item). Formation ITIN

72 Etape 3 : sauvegarder un nouveau pseudo
public void commandAction(Command command, Item item) { if (item == pseudoCaptureField) { if (command == savePseudoCommand) { try { // get the pseudo from the pseudoCaptureField pseudo = pseudoCaptureField.getString(); // record the new pseudo in the pseudo recordStore if(pseudoStore.getNumRecords() == 0){ pseudoStore.addRecord(pseudo.getBytes(),0,pseudo.length()); } else { pseudoStore.setRecord(1,pseudo.getBytes(),0,pseudo.length()); } } catch (RecordStoreNotOpenException ex) { ex.printStackTrace(); } catch (InvalidRecordIDException ex) { } catch (RecordStoreException ex) { Formation ITIN

73 Etape 3 : testez Lancez votre application dans le simulateur,
enregistrez votre pseudo. arrêtez l’application, relancez-la, votre pseudo doit apparaître Formation ITIN

74 RecordStore : les autres méthodes
 void addRecordListener(RecordListener listener)           ajoute un listener qui sera averti des modifications du record store.  void closeRecordStore()           appelé à la fermeture de la MIDlet void deleteRecord(int recordId)           efface une enregistrement à un index donné static void deleteRecordStore(String recordStoreName)           détruit le recordStore d’un nom donné RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated)           monte en mémoire les enregistrements du recordStore dans un RecordEnumerator long getLastModified()           donne l’instant de la dernière modification en millisecondes  String getName()           le nom de ce RecordStore.  int getNextRecordID()           donne l’index du prochain enregistrement  int getNumRecords()           le nombre d’enregistrements.  Formation ITIN

75 RecordStore : les autres méthodes
byte[]getRecord(int recordId)           retourne l’enregistrement à un index donné int getRecord(int recordId, byte[] buffer, int offset)           int getRecordSize(int recordId)           retourne la taille d’un enregistrement int getSize()           retourne la taille occupé par le recordStore en octets int getSizeAvailable()           la taille disponible en octets int getVersion()           la version du recordstore (incrémenté à chaque modification) static String[] listRecordStores()           tableau des noms de tous les RecordStores accessibles par la MIDlet. Formation ITIN

76 RecordStore : les autres méthodes
void removeRecordListener(RecordListener listener)           déconnecte un listener  void setMode(int authmode, boolean writable)           change le mode d’accès à ce recordstore void setRecord(int recordId, byte[] newData, int offset, int numBytes)          modifie les données d’un enregistrement donné. Formation ITIN

77 Etape 4 : le splash screen
Créez un splash screen avec l’image de votre choix. Affichez ce splash screen au lancement de l’application. Attention le générateur d’écran peut créer des erreurs… Formation ITIN

78 JavaTM APIs for BluetoothTM Wireless Technology (JSR 82)
L’API Bluetooth de MIDP 2 correspond au JSR 82. Vérifiez que votre téléphone est compatible JSR 82. Formation ITIN

79 Etape 5 : Bluetooth Rechercher les téléphones accessibles en Bluetooth. Récupérer les pseudo de tous les téléphones connecté sur notre réseau adhoc, placer les pseudos dans une liste Formation ITIN

80 Architecture de notre application
Chat Midlet Bluetooth Client Server Chat Midlet Bluetooth Client Server Hello Chat Midlet Bluetooth Client Server Hello send message Chat Midlet Bluetooth Client Server Chat Midlet Bluetooth Client Server send message Formation ITIN

81 Introduction à Bluetooth La pile du protocole Bluetooth
La couche radio : la couche physique dans la bande des 2.4 GHz sur 79 canaux de 1 MHz. Le protocole permet de passer d’un canal à l’autre, jusqu’à 1600 fois par seconde. La portée varie de 10cm à 10m voire plus en augmentant la puissance. La couche de bande de base : responsable du contrôle et de l’émission de paquets sur le lien radio. Le transport de la voix est en mode synchrone SCO (Synchronous Connection Oriented), celui de la donnée en mode asynchrone ACL (Asynchronous ConnectionLess). Les liaisons SCO sont des connections symétriques point à point. Les liaisons ACL sont établis sur la base d’allocation de fenêtre et peuvent être point à multipoint. Le Protocole de Gestion de Liaison utilise les liaisons établies par la couche de bande de base pour établir les connections et gérer les pico-réseaux. Il gère l’authentification, la sécurité des services et la qualité de service. L’interface de contrôle de la plate-forme sépare logiciel et matériel. Les couches supérieures sont généralement logicielles, les couches inférieure matérielles. Cette couche est optionnelle. Le protocole de commande et d’adaptation de la liaison logique reçoit les données applicatives et les formate au standard Bluetooth. Les paramètres de Qualité de Service sont échangés à ce niveau. Formation ITIN

82 Java ME et Bluetooth Le JSR 82 définit un standard non propriétaire pour le développement d’application Java utilisant Bluetooth. Il masque la complexité de la pile Bluetooth. Le JSR 82 consiste en deux paquetages optionnels : l’API Bluetooth de base et lAPI Object Exchange (OBEX) indépendant de la couche transport il peut être utilisé sans la couche Bluetooth. Formation ITIN

83 Les pré requis de l’utilisation de Bluetooth
La plate-forme doit être qualifiée par le Bluetooth Qualification Program et inclure au minimum : Generic Access Profile, Service Discovery Application Profile et Serial Port Profile. Les API du constructeur doivent pouvoir accéder au : Service Discovery Protocol (SDP), Radio Frequency Communications Protocol (RFCOMM) et au Logical Link Control and Adaptation Protocol (L2CAP). Le système doit comporter un panneau de contrôle Bluetooth :Bluetooth Control Center (BCC). Formation ITIN

84 Les paquetages Bluetooth
Les API Bluetooth Java définissent deux paquetages positionné au niveau du paquetage CLDC javax.microedition.io : javax.bluetooth: core Bluetooth API javax.obex: APIs pour le protocole Object Exchange (OBEX) Une implémentation CLDC peut comprendre l’une ou l’autre des APIs ou les deux. Formation ITIN

85 Utilisation de Bluetooth
Une application Bluetooth peut être ou cliente ou serveur et peut se comporter en pur peer to peer. Une application Bluetooth tombe dans une des trois catégories d’usage: Initialisation – Toute application doit initialiser la pile Bluetooth. Client – Un client consomme des services distants. Il commence par découvrir les appareils à sa portée pour les services qui Serveur – Un serveur met des services à disposition des clients. Il les enregistre dans une base de données de découverte de services. Il attend ensuite les connexions et sert ses clients. Formation ITIN

86 Diagramme d’activité Bluetooth
Client et serveur comment par initialiser la pile Bluetooth. Le serveur prépare les services et attend les connexions. Le client découvre les appareils Bluetooth et se connecte un appareil donné pour accéder à un service. Formation ITIN

87 L’initialisation Bluetooth
L’application récupère une référence sur le manager Bluetooth sur l’hôte. L’application cliente récupère une référence sur l’agent de découverte (Discovery Agent) qui fournit tous les services de découverte. L’application serveur rend l’appareil découvrable. Dans le code suivant la méthode d’initialisation btInit() fait une initialisation pour le client et le serveur : ... private LocalDevice localDevice; // local Bluetooth Manager private DiscoveryAgent discoveryAgent; // discovery agent /** * Initialize */ public void btInit() throws BluetoothStateException { localDevice = null; discoveryAgent = null; // Retrieve the local device to get to the Bluetooth Manager localDevice = LocalDevice.getLocalDevice(); // Servers set the discoverable mode to GIAC localDevice.setDiscoverable(DiscoveryAgent.GIAC); // Clients retrieve the discovery agent discoveryAgent = localDevice.getDiscoveryAgent(); } Formation ITIN

88 L’initialisation Bluetooth
Toutes les applications ne sont pas serveur et client en même temps. Leur rôle dépend des besoins de votre application. Les applications serveur se déclarent découvrable tandis que les applications clientes récupèrent une référence auprès du « Discovery Agent » pour le service de découverte. En déclarant un appareil découvrable, par l’appel de LocalDevice.setDiscoverable(), il faut spécifier le code de requête d’accès (inquiry access code, IAC). JABWT supporte deux modes d’accès : DiscoveryAgent.LIAC définit le Limited Inquiry Access Code. Le service sera découvrable pour durée limitée de temps, généralement 1mn. Ensuite l’appareil se met en mode non découvrable. DiscoveryAgent.GIAC définit le General Inquiry Access Code. Il n’y a pas de limite de durée du mode découvrable. Formation ITIN

89 CAVEAT Pour replacer un appareil en mode discret, il suffit d’appeler
LocalDevice.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE) Note: Au dessous, le Centre de Commande Bluetooth (BCC) sert d’autorité pour tous les paramétrages. Le BCC permet à l’utilisateur de prendre la main sur les mode de découverte et les autres paramétrages. Le BCC permet aussi d’empêcher que des applications en affecte d’autres. Par simplicité dans notre application nous utiliserons le mode GIAC. Cependant, dès qu’un appareil est découvrable, il est visible par tous les autres appareils Bluetooth et donc non protégé contre les attaques. Aussi, bien que le GIAC soit le mode le plus utilisé, il sera préférable dans vos applications professionnelles d’utiliser le mode LIAC. Formation ITIN

90 Le serveur Bluetooth Formation ITIN

91 Créer un serveur Bluetooth
La création d’un serveur Bluetooth se fait en 4 étapes: Créer le service à distribuer, Ajouter le nouvel enregistrement de service à la base de données du service de découverte (SDDB), Enregistrer le service, attendre la connexion de clients, Traiter les demandes Deux opérations sont également importantes : Modifier un enregistrement de service si les attributs de ce service ont été changés, Retirer un enregistrement de service de la base de données du service de découverte (SDDB). Formation ITIN

92 Créer un enregistrement de service
L’implantation Bluetooth crée automatiquement un enregistrement de service quand l’application crée un notifiant de connexion : un StreamConnectionNotifier ou un L2CAPConnectionNotifier. Chaque service Bluetooth et attribut de service possède son propre UUID (Identifiant Unversel Unique) sur 16, 32 ou 128 bits. ... // Bluetooth Service name private static final String myServiceName = "MyBtService"; // Bluetooth Service UUID of interest private static final String myServiceUUID = "2d fb47c28d9f10b8ec891363"; private UUID MYSERVICEUUID_UUID = new UUID(myServiceUUID, false); // Define the server connection URL String connURL = "btspp://localhost:"+MYSERVICEUUID_UUID.toString()+";name="+myServiceName; // Create a server connection (a notifier) StreamConnectionNotifier scn = (StreamConnectionNotifier) Connector.open(connURL); Formation ITIN

93 Création de UUID génèrent des UUID
uuidgen –t (Linux) uuidgen (dans le SDK de Windows) génèrent des UUID retirer les caractères non numériques Formation ITIN

94 Enregistrer le service, attendre les connexions
Une fois le notifiant de connexion et l’enregistrement de service créés, le serveur est prêt pour enregistrer le service et en attente pour les clients. L’invocation de la méthode acceptAndOpen() du notifiant fait insérer l’enregistrement de service pour la connexion associé dans le SDDB, rendant le service visible. La méthode bloque et se met ensuite en attente de clients entrants. Ici on lit une chaîne de caractère… c’est un chat. // Insert service record into SDDB and wait for an incoming client StreamConnection sc = scn.acceptAndOpen(); ... // New client connection accepted; get a handle on it RemoteDevice rd = RemoteDevice.getRemoteDevice(conn); System.out.println("New client connection... " + rd.getFriendlyName(false)); // Read input message, in this example a String DataInputStream dataIn = conn.openDataInputStream(); String s = dataIn.readUTF(); // Pass received message to incoming message listener Formation ITIN

95 Mise à jour de l’enregistrement de service
Dans certains cas, il faut modifier les attributs d’un enregistrement de service. Le Bluetooth Manager permet de modifier les enregistrement dans le SDDB. Un enregistrement se récupère par l’appel de LocalDevice.getRecord(). La modification se fait par l’appel de ServiceRecord.setAttributeValue(), L’enregistrement dans le SDDB par LocalDevice.updateRecord(). ... try { // Retrieve service record and set/update optional attributes, // for example, ServiceAvailability, indicating service is available sr = localDevice.getRecord(streamConnectionNotifier); sr.setAttributeValue(SDP_SERVICEAVAILABILITY, new DataElement(DataElement.U_INT_1, 0xFF)); localDevice.updateRecord(sr); } catch (IOException ioe) { // Catch exception, display error } Formation ITIN

96 Clôturer une connection, retirer un enregistrement de service
Quand un service est obsolète, il est retiré du SDDB en clôturant le notifiant de connexion. ... streamConnectionNotifier.close(); Formation ITIN

97 Logical Link Control and Adaptation Protocol (L2CAP)
L2CAP est le protocole utilisé dans MIDP. L’API fonctionne en mode connecté. Un L2CAPConnectionNotifier notifie le serveur quand une client initie une connexion. Quand la connexion est établie elle retourne un objet L2CAPConnection. L’interface L2CAPConnection et L2CAPConnectionNotifier étendent l’interface Connection. Cette interface L2CAPConnection peut être utilisée pour envoyer des données et en recevoir d’un appareil distant en utilisant le protocole L2CAP. Formation ITIN

98 Le client Bluetooth Formation ITIN

99 Découvrir les appareils et les services
Pour accéder à un service, un client doit le trouver. Le cycle de recherche consiste à : découvrir les appareils voisins, ensuite pour chaque appareil trouvé rechercher les services qui l’intéressent, La recherche d’appareils coûte cher et prend du temps. Le client peut éviter cet effort s’il connaît déjà ses voisins et leur services. Il ne fait alors une recherche que s’il ne connaît pas un voisin. Formation ITIN

100 Découvrir les appareils et les services
La découverte est de la responsabilité du DiscoveryAgent. Cette classe permet au client d’initier et d’annuler la découverte des appareils et des services. Le DiscoveryAgent notifie l’application cliente des appareils et services découverts au travers du DiscoveryListener. Formation ITIN

101 Découvrir les appareils et les services
Pour retrouver des terminaux précédemment connus ou en cache le client demande au DiscoveryAgent d’appeler retrieveDevices(). RemoteDevice[] retrieveDevices(int option); ...où option est soit : DiscoveryAgent .CACHED pour les terminaux précédemment découverts, DiscoveryAgent .PREKNOWN pour les terminaux déjà connus, Le client initie un cycle de découverte par l’appel de startInquiry(): boolean startInquiry(int accessCode, DiscoveryListener listener); ...où accessCode est : soit DiscoveryAgent.LIAC ou DiscoveryAgent.GIAC, comme nous l’avons vu pour le serveur listener est un objet dont la classe implante l’interface DiscoveryListener. (slide suivante) Formation ITIN

102 Découvrir les appareils et les services
Pour recevoir les notifications du DiscoveryAgent, l’application cliente doit implanter l’interface DiscoveryListener et les méthodes rattachées: deviceDiscovered(), reçu par l’abonné quand un nouveau serveur est découvert. inquiryCompleted(), reçu par l’abonné quand le DiscoveryAgent a fini d’interroger les terminaux à sa portée servicesDiscovered(), reçu par l’abonné quand le DiscoveryAgent a découvert un service serviceSearchCompleted(). reçu par l’abonné quand le DiscoveryAgent a fini d’interroger les serveurs sur les services disponibles. Formation ITIN

103 Notre exemple Formation ITIN

104 L’interface IBlueChat
package hadhoc; import javax.bluetooth.UUID; /** * stores the UUID used by both BluetoothServer and BluetoothClient. * Both BluetoothServer and BluetoothClient should implement IBlueChat interface Hugues Sansen */ public interface IBlueChat { /** The standard L2CAPP UUID, used by our application to reduce the scope of the search to server that support L2CAPP protocole*/ static UUID L2CAPUUID = new UUID(0x0100); /** Supposed to be a uuidgen generated UUID to have a UUID deployed uniquely in our * application. * This facilitates the scope of the service search static UUID BLUECHATUUID = new UUID(" d a1b121d1e1f100",false); } /* * BlueChat.java * * Created on 3 novembre 2007, 17:02 * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package hadhoc; import javax.bluetooth.UUID; /** * stores the UUID used by both BluetoothServer and BluetoothClient. * Both BluetoothServer and BluetoothClient should implement IBlueChat interface Hugues Sansen public interface IBlueChat { * The standard L2CAPP UUID, used by our application to reduce the scope of the search to server that support L2CAPP protocole static UUID L2CAPUUID = new UUID(0x0100); //this is a valid service UUID , not genererated by uuigen though. We cannot guaranty it is unique * Supposed to be a uuidgen generated UUID to have a UUID deployed uniquely in our application. * This facilitates the scope of the service search static UUID BLUECHATUUID = new UUID(" d a1b121d1e1f100",false); } Formation ITIN

105 BluetoothServer package hadhoc; import java.io.IOException;
import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.L2CAPConnection; import javax.bluetooth.L2CAPConnectionNotifier; import javax.bluetooth.LocalDevice; import javax.microedition.io.Connector; import javax.microedition.midlet.MIDlet; /** * This is a simple Bluetooth adhoc L2CAP server. Receives messages from remote devices. Send them to the midlet if the device is the recipient or tho the local Bluetooth client if messages are to be relayed Hugues Sansen */ public class BluetoothServer implements IBlueChat, Runnable{ private LocalDevice localDevice; private DiscoveryAgent discoveryAgent; private String deviceName; private L2CAPConnection connection; private HadHocChat hadhocChat; private BluetoothClient btClient; /* * BuetoothServer.java * * Created on 3 novembre 2007, 13:48 * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package hadhoc; import java.io.IOException; import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.L2CAPConnection; import javax.bluetooth.L2CAPConnectionNotifier; import javax.bluetooth.LocalDevice; import javax.microedition.io.Connector; import javax.microedition.midlet.MIDlet; /** * This is a Bluetooth L2CAP server. Receives messages from remote devices. Send them to the midlet if the device is the recipient or tho the local Bluetooth client if messages are to be relayed Hugues Sansen * this is a simple peer to peer adhoc Bluetooth server public class BluetoothServer implements IBlueChat, Runnable{ private LocalDevice localDevice; private DiscoveryAgent discoveryAgent; private String deviceName; private L2CAPConnection connection; private HadHocChat hadhocChat; private BluetoothClient btClient; * Creates a new instance of BuetoothServer btClient The local Bluetooth server that is called by the server to relay messages hadhocChat The hadhocChat midlet that uses the Bluetooth server public BluetoothServer(HadHocChat hadhocChat, BluetoothClient btClient) { this.hadhocChat = hadhocChat; this.btClient = btClient; } * initialize the Bluetooth stack javax.bluetooth.BluetoothStateException when Bluetooth stack doesn't initialize correctly public void initialize() throws BluetoothStateException{ System.out.println("Starting server - please wait..."); localDevice = LocalDevice.getLocalDevice(); DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent(); localDevice.setDiscoverable(DiscoveryAgent.LIAC); Thread t = new Thread(this); t.start(); * run the server listening task Runnable#run public void run(){ try { String service_UUID = BLUECHATUUID.toString(); deviceName = localDevice.getFriendlyName(); //this is a L2CAP url String url = "btl2cap://localhost:" + service_UUID + ";name=" + deviceName; L2CAPConnectionNotifier notifier = (L2CAPConnectionNotifier)Connector.open(url); connection = notifier.acceptAndOpen(); while (true) { if (connection.ready()){ byte[] b = new byte[1000]; connection.receive(b); String message = new String(b, 0, b.length); treatMessage(message.trim()); } catch(BluetoothStateException e){ System.out.println(e); } catch(IOException f){ System.out.println(f); * Check if the message is for the device, if true do not relay the message * Check if the device has already relayed the message, if true do not relay the message * otherwise, add the deviceName in the relayList, send the message to be relayed by the client private void treatMessage(String message){ int indexOfTo = message.indexOf(";to:",0); if(message.startsWith(hadhocChat.getPseudo(),indexOfTo+ 4)){ //send the message to the midlet } else if( message.substring(0,indexOfTo).indexOf(deviceName)> 0){ //the device has already relayed the message } else{ //we add the deviceName in the relayList StringBuffer newMessage =new StringBuffer(); newMessage.append(message.substring(0,indexOfTo)); newMessage.append(';'); newMessage.append(deviceName); newMessage.append(message.substring(indexOfTo,message.length())); newMessage.toString(); * send a message to the connected client private void send(String s){ byte[] b = s.getBytes(); connection.send(b); } catch(IOException e){ Formation ITIN

106 BluetoothServer, suite
/** Creates a new instance of BuetoothServer btClient The local Bluetooth server that is called by the * server to relay messages hadhocChat The hadhocChat midlet that uses the Bluetooth *server */ public BluetoothServer(HadHocChat hadhocChat, BluetoothClient btClient) { this.hadhocChat = hadhocChat; this.btClient = btClient; } /** initialize the Bluetooth stack javax.bluetooth.BluetoothStateException when Bluetooth stack * doesn't initialize correctly public void initialize() throws BluetoothStateException{ System.out.println("Starting server - please wait..."); localDevice = LocalDevice.getLocalDevice(); DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent(); localDevice.setDiscoverable(DiscoveryAgent.LIAC); Thread t = new Thread(this); t.start(); Formation ITIN

107 BluetoothServer, suite
/** run the server listening task Runnable#run */ public void run(){ try { String service_UUID = BLUECHATUUID.toString(); deviceName = localDevice.getFriendlyName(); //this is a L2CAP url String url = "btl2cap://localhost:" + service_UUID + ";name=hadHocChatServer"  ; L2CAPConnectionNotifier notifier = (L2CAPConnectionNotifier)Connector.open(url); connection = notifier.acceptAndOpen(); while (true) { if (connection.ready()){ byte[] b = new byte[1000]; connection.receive(b); String message = new String(b, 0, b.length); treatMessage(message.trim()); } } catch(BluetoothStateException e){ System.out.println(e); } catch(IOException f){ System.out.println(f); Formation ITIN

108 BluetoothServer, suite
/** * Check if the message is for the device, if true do not relay the message * Check if the device has already relayed the message, if true do not relay the message * otherwise, add the deviceName in the relayList, send the message to be relayed by the client */ private void treatMessage(String message){ int indexOfTo = message.indexOf(";to:",0); if(message.startsWith(hadhocChat.getPseudo(),indexOfTo+ 4)){ //send the message to the midlet for displaying // the message should be cleaned of relays and formated for nice display hadhocChat.displayMessage(message); } else if( message.substring(0,indexOfTo).indexOf(deviceName)> 0){ //the device has already relayed the message } else{ // we relay the message //we add the deviceName in the relayList StringBuffer newMessage =new StringBuffer(); newMessage.append(message.substring(0,indexOfTo)); newMessage.append(';'); newMessage.append(deviceName); newMessage.append(message.substring(indexOfTo,message.length())); btClient.relayMessage(newMessage.toString()); } Formation ITIN

109 BluetoothClient Formation ITIN package hadhoc;
import java.io.IOException; import java.util.Vector; import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DeviceClass; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.DiscoveryListener; import javax.bluetooth.L2CAPConnection; import javax.bluetooth.LocalDevice; import javax.bluetooth.RemoteDevice; import javax.bluetooth.ServiceRecord; import javax.bluetooth.UUID; import javax.microedition.io.Connector; /** A Bluetooth L2CAP client that is used to connect to remote Blutooth devices Hugues Sansen * This is a simple client for a peer to peer adhoc bluetooth client */ public class BluetoothClient implements IBlueChat, DiscoveryListener, Runnable { private LocalDevice localDevice; // local Bluetooth Manager private DiscoveryAgent discoveryAgent; // discovery agent private HadHocChat hadHocChat; /** Keeps track of the devices found during an inquiry.*/ private Vector deviceList; /* The list of all the peer services */ private Vector peerServices; /** Creates a new instance of BluetoothScanner */ public BluetoothClient(HadHocChat hadHocChat) { this.hadHocChat = hadHocChat; } /* * BluetoothScanner.java * * Created on 31 octobre 2007, 18:35 * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package hadhoc; import java.io.IOException; import java.util.Vector; import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DeviceClass; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.DiscoveryListener; import javax.bluetooth.L2CAPConnection; import javax.bluetooth.LocalDevice; import javax.bluetooth.RemoteDevice; import javax.bluetooth.ServiceRecord; import javax.bluetooth.UUID; import javax.microedition.io.Connector; /** * A Bluetooth L2CAP client that is used to connect to remote Blutooth devices Hugues Sansen * This is a simple client for a peer to peer adhoc bluetooth client public class BluetoothClient implements IBlueChat, DiscoveryListener, Runnable { private LocalDevice localDevice; // local Bluetooth Manager private DiscoveryAgent discoveryAgent; // discovery agent private HadHocChat hadHocChat; * The max number of service searches that can occur at any one time. private int maxServiceSearches = 0; * The number of service searches that are presently in progress. private int serviceSearchCount; * Keeps track of the devices found during an inquiry. private Vector deviceList; * The list of all the peer services private Vector peerServices; /** Creates a new instance of BluetoothScanner */ public BluetoothClient(HadHocChat hadHocChat) { this.hadHocChat = hadHocChat; } * initialize the Bluetooth stack javax.bluetooth.BluetoothStateException throws exception when the Bluetooth stack doen't initialize public void initialize() throws BluetoothStateException { localDevice = null; discoveryAgent = null; // Retrieve the local device to get to the Bluetooth Manager localDevice = LocalDevice.getLocalDevice(); // Clients retrieve the discovery agent discoveryAgent = localDevice.getDiscoveryAgent(); // Get the max number of devices the system can support try{ maxServiceSearches = Integer.parseInt( LocalDevice.getProperty("bluetooth.sd.trans.max")); } catch (NumberFormatException e) { System.out.println("General Application Error"); System.out.println("\tNumberFormatException: " + e.getMessage()); scanServices(); * called each time we need to scan the remote BluetoothServers. * Should be called before sending a message to update the visible BluetoothServers list. public void scanServices(){ Thread t = new Thread(this); t.start(); * scan the devices available in Bluetooth * We make it simple : we should look for the CACHED devices and the PREKNOWN devices first public void run() { RemoteDevice[] devList; //initialize the list of devices each time we do a scan deviceList = new Vector(); * We make it simple although not efficient. * We should look for the CHACHED devices first then the PREKNOWN before discovering all the devices by brute force. * Start an inquiry to find all devices that could be a * printer and do a search on those devices. /* Start an inquiry to find a server */ try { discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this); * When a device is found, discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) calls deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) * Wait until all the devices are found before trying to start the service search. * We get a notify from the inquiryCompleted() synchronized (this) { this.wait(); } catch (Exception e) { } catch (BluetoothStateException e) { System.out.println("Unable to find devices to search"); if (deviceList.size() > 0) { devList = new RemoteDevice[deviceList.size()]; deviceList.copyInto(devList); if (searchPeerServices(devList)) { private boolean searchPeerServices(RemoteDevice[] remoteDeviceList){ *The search list contains a set of UUID that all servers must implement UUID[] searchList = new UUID[2]; * Add the UUID for L2CAP to make sure that the service record * found will support L2CAP. This value is defined in the * Bluetooth Assigned Numbers document. searchList[0] = L2CAPUUID; * Add the UUID for our chat servers that we are going to use to * the list of UUIDs to search for. searchList[1] = BLUECHATUUID; * Start a search on as many devices as the system can support. for (int i = 0; i < remoteDeviceList.length; i++) { int trans = discoveryAgent.searchServices(null, searchList, remoteDeviceList[i], this); //we should limit the search to the max number of services the system can handle return false; * called when a new Bluetooth server is discovered remoteDevice deviceClass DiscoveryListener#deviceDiscovered * this method is called by discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) each time the inquiry finds a new device. * we add the discovered device to the deviceList public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) { * Check the class of device int major = deviceClass.getMajorDeviceClass(); if( ! deviceList.contains( remoteDevice ) ) { deviceList.addElement( remoteDevice ); * called when a new service is discovered DiscoveryListener#servicesDiscovered * called when a new service has been discovered * add all the services found to the peerServices list. * It is up to you to make it smarter... transID serviceRecord public void servicesDiscovered(int transID, ServiceRecord[] serviceRecord) { for(int i = 0; i< serviceRecord.length;i++){ peerServices.addElement(serviceRecord[i]); * implement DiscoveryListener i i0 public void serviceSearchCompleted(int i, int i0) { // notify threads that are waiting on this this.notifyAll(); * this method is called by discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) is completed. * When the inquiry is completed, notifies the waiting threads on this. public void inquiryCompleted(int i) { * send a non formated message to a recepient through all connected peers * used when the client initiates a message * Send a message to remote devices from to timeStamp body public void sendMessage(String from, String to, String timeStamp, String body){ String message = formatMessage(from, to, timeStamp, body); relayMessage(message); * send a formated message to a recepient through all connected peers * used to relay a massage to other peers * relay messages to remote devices message the message to be relayed public void relayMessage(String message){ for(int i = 0; i< peerServices.size(); i++){ ServiceRecord peerService = (ServiceRecord) peerServices.elementAt(i); String url = peerService.getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); int index= url.indexOf(':'); String protocol= url.substring(0, index); // we check if the protocole is "btl2cap" if (protocol.equals("btl2cap")) { L2CAPConnection connection; connection = (L2CAPConnection) Connector.open(url); connection.send(message.getBytes()); } catch (IOException ex) { ex.printStackTrace(); * format a simple message * a better version could be XML public String formatMessage(String from, String to, String timeStamp, String body){ StringBuffer buffer = new StringBuffer(); buffer .append("timeStamp"); buffer .append(timeStamp); buffer .append(";from:"); buffer .append(from); buffer .append(";to:"); buffer .append(to); buffer .append(";body:"); buffer .append(body); return buffer.toString(); Formation ITIN

110 BluetoothClient, suite
/** initialize the Bluetooth stack javax.bluetooth.BluetoothStateException throws exception when the Bluetooth stack * doen't initialize*/ public void initialize() throws BluetoothStateException { localDevice = null; discoveryAgent = null; // Retrieve the local device to get to the Bluetooth Manager localDevice = LocalDevice.getLocalDevice(); // Clients retrieve the discovery agent discoveryAgent = localDevice.getDiscoveryAgent(); // Get the max number of devices the system can support try{ maxServiceSearches = Integer.parseInt( LocalDevice.getProperty("bluetooth.sd.trans.max")); } catch (NumberFormatException e) { System.out.println("General Application Error"); System.out.println("\tNumberFormatException: " + e.getMessage()); } scanServices(); return buffer.toString(); Formation ITIN

111 BluetoothClient, suite
/** * called each time we need to scan the remote BluetoothServers. * Should be called before sending a message to update the visible BluetoothServers list. */ public void scanServices(){ Thread t = new Thread(this); t.start(); } Formation ITIN

112 BluetoothClient, suite
/** scan the devices available in Bluetooth. We make it simple : we should look for the CACHED devices and the PREKNOWN devices first */ public void run() { RemoteDevice[] devList; //initialize the list of devices each time we do a scan deviceList = new Vector(); /* We make it simple although not efficient. We should look for the CHACHED devices first then the PREKNOWN * before discovering all the devices by brute force. Start an inquiry to find a server */ try { discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this); /* When a device is found, discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) calls deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) * Wait until all the devices are found before trying to start the service search. * We get a notify from the inquiryCompleted() */ synchronized (this) { this.wait(); } catch (Exception e) { } } } catch (BluetoothStateException e) { System.out.println("Unable to find devices to search"); } if (deviceList.size() > 0) { devList = new RemoteDevice[deviceList.size()]; deviceList.copyInto(devList); if (searchPeerServices(devList)) { BluetoothClient, suite Formation ITIN

113 BluetoothClient, suite
private boolean searchPeerServices(RemoteDevice[] remoteDeviceList){ /* The search list contains a set of UUID that all servers must implement */ UUID[] searchList = new UUID[2]; /* Add the UUID for L2CAP to make sure that the service record * found will support L2CAP. This value is defined in the * Bluetooth Assigned Numbers document. */ searchList[0] = L2CAPUUID; /*Add the UUID for our chat servers that we are going to use to the list of UUIDs to *search for. */ searchList[1] = BLUECHATUUID; /* Start a search on as many devices as the system can support.*/ for (int i = 0; i < remoteDeviceList.length; i++) { try { int trans = discoveryAgent.searchServices(null, searchList, remoteDeviceList[i], this); } catch (BluetoothStateException e) { } synchronized (this) { //we should limit the search to the max number of services the system can handle this.wait(); } catch (Exception e) { return false; BluetoothClient, suite Formation ITIN

114 BluetoothClient, suite
/** called when a new Bluetooth server is discovered remoteDevice deviceClass DiscoveryListener#deviceDiscovered * this method is called by discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) each time the inquiry finds a new device. * we add the discovered device to the deviceList */ public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) { /* Check the class of device */ int major = deviceClass.getMajorDeviceClass(); if( ! deviceList.contains( remoteDevice ) ) { deviceList.addElement( remoteDevice ); } /** called when a new service is discovered DiscoveryListener#servicesDiscovered * called when a new service has been discovered * add all the services found to the peerServices list. * It is up to you to make it smarter... transID serviceRecord */ public void servicesDiscovered(int transID, ServiceRecord[] serviceRecord) { for(int i = 0; i< serviceRecord.length;i++){ peerServices.addElement(serviceRecord[i]); BluetoothClient, suite Formation ITIN

115 BluetoothClient, suite
/** * implement DiscoveryListener i i0 */ public void serviceSearchCompleted(int i, int i0) { // notify threads that are waiting on this synchronized (this) { this.notifyAll(); } * this method is called by discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this) is completed. * When the inquiry is completed, notifies the waiting threads on this. public void inquiryCompleted(int i) { try { } catch (Exception e) { BluetoothClient, suite Formation ITIN

116 BluetoothClient, suite
/** * send a non formated message to a recepient through all connected peers * used when the client initiates a message from to timeStamp body */ public void sendMessage(String from, String to, String timeStamp, String body){ String message = formatMessage(from, to, timeStamp, body); relayMessage(message); } BluetoothClient, suite Formation ITIN

117 BluetoothClient, suite
/** * send a formated message to a recepient through all connected peers * used to relay a massage to other peers * relay messages to remote devices message the message to be relayed */ public void relayMessage(String message){ for(int i = 0; i< peerServices.size(); i++){ ServiceRecord peerService = (ServiceRecord) peerServices.elementAt(i); String url = peerService.getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); int index= url.indexOf(':'); String protocol= url.substring(0, index); // we check if the protocole is "btl2cap" if (protocol.equals("btl2cap")) { L2CAPConnection connection; try { connection = (L2CAPConnection) Connector.open(url); connection.send(message.getBytes()); } catch (IOException ex) { ex.printStackTrace(); } BluetoothClient, suite Formation ITIN

118 BluetoothClient, suite
/** * format a simple message * a better version could be XML from to timeStamp body */ public String formatMessage(String from, String to, String timeStamp, String body){ StringBuffer buffer = new StringBuffer(); buffer .append("timeStamp"); buffer .append(timeStamp); buffer .append(";from:"); buffer .append(from); buffer .append(";to:"); buffer .append(to); buffer .append(";body:"); return buffer.toString(); } BluetoothClient, suite Formation ITIN

119 Etape 5, suite Terminez l’application pour :
qu’un destinataire envoie un acquittement de réception, envoyer un message à tous, découvrir tous les terminaux accessibles au travers du réseau adhoc. visualisez les pseudos dans une liste, Formation ITIN

120 La 3D en Java Mobile Formation ITIN

121 Etape 6 Ajoutez une fenêtre à votre application pour visualiser le réseau adhoc en 3D Formation ITIN


Télécharger ppt "Java mobile Hugues Sansen Formation ITIN."

Présentations similaires


Annonces Google