Android_Clients_Serveur 1 Connectivité, Web Services Orienté clients/serveur TCP et Bluetooth Notes de cours jean-michel Douin, douin au cnam point fr version : 3 Décembre 2015 Avertissement :
Android_Clients_Serveur 2 Bibliographie utilisée Un ensemble de tutoriels à lire
Android_Clients_Serveur 3 Sommaire Clients et serveurs TCP –Un Client, une requête –Serveur TCP (HTTP,…) –Clients Bluetooth Annexes, cf. NFP121 –Format XML, API SAX –Format JSON json.org
Android_Clients_Serveur 4 Client et serveur Serveurs TCP –Exemples –Requête
Android_Clients_Serveur 5 Serveurs En mode TCP Appels distants en mode TCP/IP –Point à point avec accusé de réception –telnet, ftp, http, …
Android_Clients_Serveur 6 URL … URL Uniform Resource Locator une adresse sur internet – –http le protocole –//jfod.cnam.fr le nom de la ressource –
Android_Clients_Serveur 7 Exemples clients / serveurs 1.Le client s’adresse au serveur –Établit une connexion 2.Le serveur satisfait ses clients –Mode synchrone, analogue à l’appel d’une méthode locale Client2 Serveur Client1 protocole Client3
Android_Clients_Serveur 8 Appels distants protocole « maison » Le contexte –Client Java, ou autres –Serveur en java ou autre –maison : //serveur/…. Client2 serveur JVM Client1 JVM maison Client3
Android_Clients_Serveur 9 Appels distants protocole http Le contexte –Client Java(application comme applette), ou autres –Un navigateur –Serveur en java, ou autres http: //serveur/index.html Standard, universel … Client2 serveur JVM Client1 JVM http un navigateur
Android_Clients_Serveur 10 Implémentation en Java Paquetage java.net –Principales classes ServerSocket Socket InetAddress URLConnection … –Quelques lignes de sources suffisent …
Android_Clients_Serveur 11 usage de java.net TCP/IP 2 classes essentielles Côté Serveur –java.net.ServerSocket Méthode accept() sur une instance de la classe ServerSocket Côté Client –java.net.Socket, java.net.SocketAddress Envoi sur une instance de la classe Socket de données Serveur JVM Client1 JVM
Android_Clients_Serveur 12 Connexion / Principes Le Serveur attend une requête sur son port –ServerSocket server = new ServerSocket(port) –Socket socket = server.accept(); Dès la connexion établie, –une instance de la classe Socket est engendrée sur un port temporaire Établir une connexion par le client est effectuée par –Socket s = new Socket(Serveur, port) Serveur JVM Client1 JVM port
Android_Clients_Serveur 13 2 exemples Serveur et client 1.Au protocole « maison » Le serveur ne connaît que la commande « parle » et répond « bonjour » Tout autre commande est ignorée ! 2.Au protocole http Seule la méthode GET /index.html HTTP1.0 est possible Un sous-ensemble donc …
Android_Clients_Serveur 14 Exemple 1 –Au protocole « maison » Le serveur ne connaît que la commande « parle » et répond « bonjour » Tout autre commande est ignorée ! –Client java ou autre Serveur JVM Client1 JVM maison: //serveur parle bonjour
Android_Clients_Serveur 15 Un serveur avec un protocole « maison » public class Serveur{ public static void main(String[] args) throws Exception{ ServerSocket serveur = new ServerSocket(5000); while(true) { Socket socket = serveur.accept(); BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); String cmd = in.readLine(); // parle !!! DataOutputStream out = new DataOutputStream( socket.getOutputStream()); if(cmd.equals("parle")){ out.write("bonjour\n".getBytes()); }else{ out.write("commande inconnue ?\n".getBytes()); } socket.close(); }
Android_Clients_Serveur 16 Le client « maison » public class Client{ public static void main(String[] args) throws Exception{ Socket socket = new Socket("vivaldi.cnam.fr", 5000); DataOutputStream out= new DataOutputStream( socket.getOutputStream()); out.write(args[0].getBytes()); out.write("\n".getBytes()); BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); System.out.println(in.readLine()); socket.close(); }
Android_Clients_Serveur 17 Un client « maison », telnet telnet localhost 5000 –parle // frappe sans écho petit outil utile : tcpview
Android_Clients_Serveur 18 Exemple 2 Le protocole HTTP –Les méthodes GET, POST, …. Mise en œuvre / démo –Usage d’un client telnet sur un site existant –Une application Java cliente –Un serveur en java
Android_Clients_Serveur 19 Protocole HTTP HyperText Transfer Protocol –Au dessus de TCP Les Méthodes –GET /index.html HTTP/1.0 –HEAD –POST –PUT –DELETE –TRACE –CONNECT –Voir
Android_Clients_Serveur 20 Côté serveur, méthode accept ServerSocket listen = new ServerSocket(HTTP_PORT); while(!stopped()){ try{ Socket socket = listen.accept(); handleRequest(socket); }catch(Exception e){ } listen.close(); } listen.accept() est bloquant : au moins un client.
Android_Clients_Serveur 21 Exemple minimaliste ! Un serveur Web au complet –Un seul client, une seule requête ! Extrait de
Android_Clients_Serveur 22 OneShot Httpd by Hendrik, j2se public class OneShotHttpd { protected static File docRoot; public final static int HTTP_PORT = 8080; public static void main(String argv[]){ try{ docRoot = new File("."); ServerSocket listen = new ServerSocket(HTTP_PORT); Socket client = listen.accept(); BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream())); DataOutputStream os = new DataOutputStream(client.getOutputStream()); String request = is.readLine(); StringTokenizer st = new StringTokenizer(request); if((st.countTokens() == 3) && st.nextToken().equals("GET")){ String filename = docRoot.getPath() + st.nextToken(); if(filename.endsWith("/") || filename.equals("")) filename += "index.html"; File file = new File(filename); sendDocument(os,file); } else System.err.println("400 Bad Request"); is.close(); os.close(); client.close(); }catch(IOException ioe){ System.err.println("Error: " + ioe.toString()); }}
Android_Clients_Serveur 23 OneShot « envoi du document » public static void sendDocument(DataOutputStream out, File file) throws IOException{ try{ BufferedInputStream in = new BufferedInputStream( new FileInputStream(file)); byte[] buf = new byte[1024]; int len; while((len = in.read(buf,0,1024)) != -1) { out.write(buf,0,len); } in.close(); } catch(FileNotFoundException fnfe) { System.err.println("404 Not Found"); }
Android_Clients_Serveur 24 OneShot avec Android AsyncTask Rappel –Réalise une encapsulation d’un Thread et de l’accès à l’écran onPreExecute() –Préambule, l’UI exécute cette méthode Void doInBackground(String… s){ } onProgressUpdate(Progress…p) –Mise à jour de l’UI à la suite de l’appel de publishProgress onPostExecute(Result) –Mise à jour de l’UI à la fin de la méthode doInBackground OneShotHttpd.main(s);
Android_Clients_Serveur 25 Côté serveur, un thread à chaque requête ServerSocket listen = new ServerSocket(HTTP_PORT); while(!stopped()){ try{ new Connection(listen.accept()); // création d’une instance }catch(Exception e){ } listen.close(); } Chaque requête engendre la création d’une instance de la classe Connection Et chaque instance créée engendre à son tour un « Thread »
Android_Clients_Serveur 26 Côté serveur, à chaque Connection un Thread public class Connexion extends Thread{ … public Connexion(Socket s){ this.s = s; start(); } public void run(){ try{ BufferedReader is = new BufferedReader( new InputStreamReader(s.getInputStream())); DataOutputStream os = new DataOutputStream(s.getOutputStream()); // analyse du contenu au bon protocole HTTP // envoi du document
Android_Clients_Serveur 27 Côté serveur, accept « peut-être » ServerSocket listen = new ServerSocket(HTTP_PORT); listen.setSoTimeout(TIME_OUT); while(!stopped()){ try{ new Connection(listen.accept()); }catch(SocketTimeoutException e){ // ici délai de garde échu }catch(Exception e){ } listen.close(); } Par défaut l’appel de accept est bloquant Méthode accept avec délai de garde exception SocketTimeoutException à l’échéance
Android_Clients_Serveur 28 Schéma avec Un Pool de Thread class WebServer { // 2004 JavaOneSM Conference | Session 1358 ThreadPool pool = new ThreadPool(7); public static void main(String[] args) { ServerSocket socket = new ServerSocket(80); while (true) { final Socket s = socket.accept(); Runnable r = new Runnable() { public void run() { BufferedReader is = new BufferedReader( new InputStreamReader(s.getInputStream())); DataOutputStream os = new DataOutputStream(s.getOutputStream()); // analyse du contenu au bon protocole HTTP // envoi du document } }; pool.execute(r); } }}
Android_Clients_Serveur 29 Côté client Usage de telnet Requêtes GET et POST en Java
Android_Clients_Serveur 30 Requête GET avec telnet Un client telnet et un site du Cnam –telnet jfod.cnam.fr 80 GET /index.html HTTP/1.0 ( frappe sans écho) HTTP/ OK Last-Modified: Thu, 08 Feb :55:29 GMT Date: Thu, 08 Mar :33:55 GMT Server: Brazil/1.0 Content-Length: 7624 Content-Type: text/html Connection: close ….. Le résultat est retourné, le source du fichier index.html précédé de quelques informations
Android_Clients_Serveur 31 Requête GET en Java L’essentiel –Créer une URL –Ouvrir une connexion Écrire et lire sur les flots associés Classe java.net.URL Classe java.net.URLConnection – URL url = new URL(" ); – URLConnection connection = url.openConnection();
Android_Clients_Serveur 32 Requête GET au complet public void testGET()throws Exception{ URL url = new URL(" ); URLConnection connection = url.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream())); String inputLine = in.readLine(); while(inputLine != null){ System.out.println(inputLine); inputLine = in.readLine(); } in.close(); }
Android_Clients_Serveur 33 Requête GET avec paramètres public void testGET()throws Exception{ URL url = new URL(" ?listAll=on " ); URLConnection connection = url.openConnection(); connection.setDoInput(true); BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream())); String inputLine = in.readLine(); while(inputLine != null){ System.out.println(inputLine); inputLine = in.readLine(); } in.close(); }
Android_Clients_Serveur 34 Requête POST URL url = new URL (" ); URLConnection connection = url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); PrintWriter out = new PrintWriter(connection.getOutputStream()); out.print("listAll=on"); out.close(); BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream())); String inputLine = in.readLine(); while(inputLine != null){ System.out.println(inputLine); inputLine = in.readLine(); } in.close();
Android_Clients_Serveur 35 Classes utiles InetAddress –Adresse IP en « clair » URL –Pour Uniform Resource Locator, sur le www URLConnection –Une classe abstraite, super classe de toutes les classes établissant un lien entre une application et une URL –Sous-classes HttpURLConnexion, JarURLConnection –Patron Fabrique afin d’écrire son propre gestionnaire de protocole Voir Méthode URLConnection.setContentHandlerFactory( …);
Android_Clients_Serveur 36 En résumé Classe d’accès aux informations –indépendante du protocole choisi Lecture écriture en 7 étapes 1.Après avoir créé l’ URL. 2.Obtenir l’instance URLConnection. 3.Installer les capacités en sortie de cette instance de URLConnection. 4.Ouvrir le flot en entrée. 5.Obtenir le flot en sortie. 6.Écrire sur ce flot. 7.Fermer celui-ci.
Android_Clients_Serveur 37 Android –Toute requête doit être effectuée en dehors de l’UIThread: –En conséquence, usage de AsyncTask Service + Thread
Android_Clients_Serveur 38 En « rappel » le cycle de vie
Android_Clients_Serveur 39 En Rappel: AsyncTask Avec la classe, AsyncTask – Nous avons –Un thread et l’accès à l’UIThread Un thread : pour le traitement en tâche de fond Une mise à jour de l’UI incluse Les paramètres génériques sont –Params type des paramètres transmis au Thread –Progress type des paramètres en cours de traitement transmis au Handler –Result type du résultat pour l’appelant
Android_Clients_Serveur 40 Résumé: AsyncTask Depuis l’UIThread –création d’une instance et appel de la méthode execute Exemple new WebAsyncTask().execute(url1, url2, url3); AsyncTask –Réalise une encapsulation d’un Thread et de l’accès à l’écran Méthodes onPreExecute() –Préambule, l’UI exécute cette méthode Result doInBackground(Params…p) –Le contenu de cette méthode s’exécute dans un autre Thread onProgressUpdate(Progress…p) –Mise à jour de l’UI à la suite de l’appel de publishProgress onPostExecute(Result) –Mise à jour de l’UI à la fin de la méthode doInBackground
Android_Clients_Serveur 41 AsyncTask et réseau, exemples Lire une page sur le web HTTP, requête GET –private class LirePageHTML extends AsyncTask { Schéma onPreExecute Afficher une fenêtre d’informations, ProgressDialog doInBackGround Ouvrir une connexion, avec un échec éventuel onPostExecute Informer l’utilisateur
Android_Clients_Serveur 42 Lire une page Web Si j’ai la permission … de naviguer sur le web – –Une IHM simple –L’accès au web est une opération coûteuse alors héritons de AsyncTask
Android_Clients_Serveur 43 Une classe interne héritant de AsyncTask protected String doInBackground(String... args) { builder = new StringBuilder(); try { HttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(args[0]); HttpResponse response = client.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) { builder.append(line); } } else {error = "Failed to download file";} } catch (Exception e) {error = e.getMessage();} return builder.toString();}
Android_Clients_Serveur 44 Autres exemples, essai d’architecture 1) Ouverture d’une connexion TCP –Obtention d’un flux (OutputStream) –Le flux reste ouvert 2) Envois de données sur le flux –En fonction des opérations de l’utilisateur Règle : l’ouverture de la connexion et l’envoi de données se font sur des threads Une solution : –Ouverture d’une connexion TCP : dans une sous classe d’AsyncTask –Envoi de données : dans un thread en attente sur une file (SynchronousQueue) –java.util.concurrent.SynchronousQueue
Android_Clients_Serveur 45 Un schéma d’une architecture possible UIThread AsyncTask Un Thread Réseau SynchronousQueue offer take 2) Envoi de données 1) Obtention de la connexion
Android_Clients_Serveur 46 Obtention de la connexion, AsyncTask protected void onPreExecute() { dialog = ….); } protected DataOutputStream doInBackground(String... args) { boolean result = true; try{ InetAddress addr = InetAddress.getByName(args[0]); int port = Integer.parseInt(args[1]); int timeout = Integer.parseInt(args[2]); SocketAddress sockaddr = new InetSocketAddress(addr, port); this.socket = new Socket(); socket.connect(sockaddr, timeout); out= new DataOutputStream(socket.getOutputStream()); }catch(Exception e){ erreur = e.getMessage();result= false;} return out; }
Android_Clients_Serveur 47 Envoi de données depuis l’UIThread // ici à chaque clic des données sont envoyées vers la file // les boutons de l’IHM contiennent la commande à envoyer au serveur public void onClickCommand(View v){ String cmd = v.getContentDescription().toString() + "\n"; try { sender.offer(cmd.getBytes()); } catch (Exception e) { } UIThread offer
Android_Clients_Serveur 48 Envois de données, vers la file public class Sender extends Thread{ private BlockingQueue queue; public Sender(){ queue = new SynchronousQueue (); this.start(); } public boolean offer(byte[] cmd){ return queue.offer(cmd); } public void close(){ this.interrupt(); } public void run(){ while(!isInterrupted()){ try { byte[] cmd = queue.take(); // lecture bloquante out.write(cmd); }catch (Exception e) { }} }
Android_Clients_Serveur 49 Sommaire suite Bluetooth Format XML
Android_Clients_Serveur 50 Bluetooth Protocole de communication sans fil peu chère, peu consommatrice d’énergie…, adapté aux mobiles Spécifications ici –Bluetooth is not a one-on-one data transmission technology so it can communicate with up to eight devices within its transmission radius at one time Vocable « habituel » : –Découverte multicast des services Client/serveur, serveur/serveur
Android_Clients_Serveur 51 Mesures, à vérifier… Figures extraites de BT m … Performances : à vérifier …
Android_Clients_Serveur 52 Bluetooth, existentiel Qui suis-je ? –Je me présente Qui êtes vous ? –Aux alentours Parmi vous qui possède ce service ? Avez d’autres services à proposer ? –Quels sont-ils ? UUID ou identification d’un service … –Adéquation UUID/URL –UUID prédéfinis, UUID pour une application Quels protocoles ? Où suis-je, où vais-je ? … –pas facile voir blipnet ericsson »
Android_Clients_Serveur 53 JSR82 à la rescousse, J2SE Deux paquetages Qui suis-je ?, qui est là ?, répondez … –javax.bluetooth.*; Nommage, Découverte Recherche de services Communication –btspp://localhost:{UUID} + (flux habituels) –Un protocole répandu OBEX java.obex.*; –btgoep://localhost:localhost:{UUID} + (flux habituels) –tcpobex://1905 –Irdaobex://localhost:1900 –Session –Transfert d’objets »put, get
Android_Clients_Serveur 54 Qui suis-je ? Chaque périphérique BT possède Une adresse (physique) sur 48 bit et unique –(MAC adresse) –Un nom lui est associé (en général)
Android_Clients_Serveur 55 Bluetooh et nommage 0019EF0117DA Devrons nous connaître les adresses physiques ? –Une UUID associera nom logique / adresse physique Universal Unique IDentifier -> UUID nous utiliserons
Android_Clients_Serveur 56 JSR 82 prémisses Initialisation de la pile (protocole) A la recherche d’un service Découverte de périphériques BT –Aux alentours –Nommage/UUID Universally Unique IDentifier (128 bits), existe en version courte Communication –java.io.*, javax.bluetooth.* –javax.microedition.io.* (inclus dans bluecove) Découverte des services –Au sein de chaque entité –Nommage/UUID Universally Unique IDentifier (128 bits)
Android_Clients_Serveur 57 Parmi mes voisins … Parmi les périphériques BT aux alentours –Quel est celui qui possède ce service … Apparenté à la découverte multicast… –Un service : un UUID new UUID(" A0B0C0D0E0F011",false) –128 bits … pourquoi pas celui-ci … –Plusieurs BT peuvent répondre pour un service souhaité « dépôt d’un fichier », mp3 … redondance
Android_Clients_Serveur 58 A la découverte de … obtention d’un agent import javax.bluetooth.LocalDevice; import javax.bluetooth.DiscoveryAgent; public class ALaDécouverteDe{ public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); // GIAC General inquire Access Code DiscoveryAgent agent = local.getDiscoveryAgent(); un agent capable de tout faire Sélection d’un service Effectuer une recherche exhaustive
Android_Clients_Serveur 59 Adéquation UUID / URL LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); // General inquire Access CodeDiscoveryAgent DiscoveryAgent agent = local.getDiscoveryAgent();DiscoveryAgent UUID UUID uuid = new UUID(" A0B0C0D0E0F011", false); String connString = agent.selectService(uuid, ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);ServiceRecord System.out.println("connString : " + connString); Un exemple d’affichage : connString: btspp://0019EF01194C:1;authenticate=false;encrypt=false;master=false 0019EF01194C l’adresse physique :1 le port de communication
Android_Clients_Serveur 60 Un service comme un autre Nous avons –Un service -> un UUID –un UUID -> une URL –Une URL -> une communication Une syntaxe de type J2ME –Une communication Un flux d’octets, btspp:// Un flux structuré, btgeop://
Android_Clients_Serveur 61 Exemple de service/UUID C’est un serveur … protocole btspp:// StreamConnectionNotifier StreamConnectionNotifier notifier = (StreamConnectionNotifier)Connector.open( "btspp://localhost: A0B0C0D0E0F010"); attente d’une requête StreamConnection StreamConnection conn = notifier.acceptAndOpen();
Android_Clients_Serveur 62 Un serveur au complet public class SimpleBTSPPServer { public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable(DiscoveryAgent.GIAC); StreamConnectionNotifier notifier =StreamConnectionNotifier (StreamConnectionNotifier)Connector.open( "btspp://localhost:" + " A0B0C0D0E0F010"); StreamConnection conn = notifier.acceptAndOpen();StreamConnection InputStream in = conn.openInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); int data; while ((data = in.read()) != -1) { out.write(data); } System.out.println(" message recu : " + out.toString()); in.close(); conn.close(); notifier.close(); } } note : ci-dessus vous avez u n serveur d’une seule connexion… c’est peu… UUID
Android_Clients_Serveur 63 Le client à la recherche de cet UUID Les essentiels agent.selectService … String connString = agent.selectService( new UUID(" A0B0C0D0E0F010", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); StreamConnection StreamConnection conn = (StreamConnection) Connector.open(connString);
Android_Clients_Serveur 64 Un exemple de client de ce service public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); DiscoveryAgent agent = local.getDiscoveryAgent(); String connString = agent.selectService( new UUID(" A0B0C0D0E0F010", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); StreamConnection conn = (StreamConnection) Connector.open(connString); OutputStream out = conn.openOutputStream(); out.write("next".getBytes()); out.flush(); out.close(); conn.close(); }
Android_Clients_Serveur 65 Bluetooth/Android Même principe, avec des noms de méthodes différents –Juste ce qu’il faut pour le TP de télécommande Hypothèse le service est en place –UUID : " A0-B0C0D0E0F0FF" –private UUID MY_UUID = UUID.fromString(" A0-B0C0D0E0F0FF");
Android_Clients_Serveur 66 Une connexion Bluetooth Recherche d’un périphérique bluetooth aux alentours –Hypothèse : Nous connaissons l’adresse physique du périphérique 00:02:72:1A:B4:75 (obtenu ipconfig /all sous windows) –Cette recherche doit s’effectuer dans un thread Alors héritons de AsyncTask Au clic –new ConnexionBT().execute("00:02:72:1A:B4:75"); private class ConnexionBT extends AsyncTask { protected void onPreExecute() { protected BluetoothSocket doInBackground(String... args) { protected void onPostExecute(BluetoothSocket btSocket) {
Android_Clients_Serveur 67 onPreExecute : Patience, doInBackground : Recherche protected void onPreExecute() { dialog = ProgressDialog.show(BTClientActivity.this, "connexion Bluetooth", " patientez ", true); } protected BluetoothSocket doInBackground(String... args) { try{ this.btDevice = btAdapter.getRemoteDevice(args[0]); btSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID); btAdapter.cancelDiscovery(); btSocket.connect(); }catch(Exception e){ erreur = e.getMessage(); btSocket= null; } return btSocket; }
Android_Clients_Serveur 68 Variante sans appairage protected void onPreExecute() { dialog = ProgressDialog.show(BTClientActivity.this, "connexion Bluetooth", " patientez ", true); } protected BluetoothSocket doInBackground(String... args) { try{ this.btDevice = btAdapter.getRemoteDevice(args[0]); btSocket = btDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID); btAdapter.cancelDiscovery(); btSocket.connect(); }catch(Exception e){ erreur = e.getMessage(); btSocket= null; } return btSocket; }
Android_Clients_Serveur 69 onPostExecute(BluetoothSocket btSocket) protected void onPostExecute(BluetoothSocket btSocket) { try { os = btSocket.getOutputStream(); // } catch (IOException e) { erreur = e.getMessage(); e.printStackTrace(); }finally{ dialog.dismiss(); } }
Android_Clients_Serveur 70 Première conclusion Serveurs et service Client et lecture de flux au format XML et JSON –XML, SAX –JSON
Android_Clients_Serveur 71 SAX XML Document John Doe Jane Doe SAX Objects Parser startDocument Parser startElement Parser startElement & characters Parser Parser endElement Parser startElement Parser startElement & characters Parser Parser endElement Parser endElement & endDocument
Android_Clients_Serveur 72 Implémenter les Handlers d'évènements du parseur DefaultHandler Il implémente ces différents Handler avec des méthodes vides, de sorte que l'on peut surcharger seulement celles qui nous intéressent.
Android_Clients_Serveur 73 org.xml.sax.ContentHandler Toutes les applications SAX doivent implanter un ContentHandler Méthodes : – public void startDocument() throws SAXException – public void endDocument() throws SAXException – public void startElement(String nspURI, String localName, String qName, Attributes atts) throws SAXException – public void characters(char[] ch, int start, int length) throws SAXException – …
Android_Clients_Serveur 74 Un exemple: les stations Vélib – – –
Android_Clients_Serveur 75 Analyse des attributs de la balise marker en SAX -> méthode startElement
Android_Clients_Serveur Analyse du contenu de la balise station en SAX -> des méthodes startElement, endElement, characters
Android_Clients_Serveur 77 Les stations Vélib: suite Les Classes, un premier découpage –StationVelib, toutes les infos d’une station, (adresse, longitude, latitude,…) –InfoStation, les informations comme le nombre de vélo et d’emplacements disponibles,... –ListeDesStationsVelib La gestion de la liste des stations – –
Android_Clients_Serveur 78 Initialisation du « parser » class ParserXML extends DefaultHandler { public ParserXML(InputStream in) throws Exception{ SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); xr.setContentHandler(this); xr.parse(new InputSource(in)); }
Android_Clients_Serveur 79 startElement un extrait // Création d’une instance de la classe StationVelib // depuis XML en Java public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if(qName.equals("marker")){ StationVelib station = new StationVelib(); station.setName(attributes.getValue("name")); station.setNumber(Integer.parseInt(attributes.getValue("number"))); station.setAddress(attributes.getValue("address")); station.setLatitude(Double.parseDouble(attributes.getValue("lat"))); station.setLongitude(Double.parseDouble(attributes.getValue("lng"))); }
Android_Clients_Serveur 80 Une Info à chaque Station class ParserXML extends DefaultHandler { private StringBuffer current; // la valeur public ParserXML(int ID){ URL url = new URL(URL_VELIB_INFO + ID); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp; sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); xr.setContentHandler(this); xr.parse(new InputSource(url.openStream())); }
Android_Clients_Serveur 81 A chaque noeud public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); current = new StringBuffer(); } public void characters (char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); current.append(new String(ch, start, length)); } public void endElement (String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if(qName.equals("available")){ available = Integer.parseInt(current.toString()); … }
Android_Clients_Serveur 82 XML plutôt verbeux, JSON plutôt concis JSON JavaScript Object Notation – –JSONArray –JSONObject JSONArray jsonArray = new JSONArray(); JSONObject jsonObject = new JSONObject(); jsonObject.put( "name", "paul"); jsonObject.put("number", 1900); jsonArray.put(jsonObject); // pierre idem System.out.println(jsonArray.toString(2));
Android_Clients_Serveur 83 JSON, exemple paul et pierre [ { "name": "paul", "number": 1900 }, { "name": "pierre", "number": 1900 } ]
Android_Clients_Serveur 84 JSON Lecture InputStream in = …; Reader r = new InputStreamReader(in); BufferedReader br = new BufferedReader(r); StringBuffer sb = new StringBuffer(); String str; while((str = br.readLine()) != null) { sb.append(str); } r.close(); JSONArray jsonarray = new JSONArray(sb.toString()); JSONObject jsonObject = (JSONObject)jsonStations.get(i); Auditeur a = new Auditeur (); a.setName(jsonObject.getString("name")); …
Android_Clients_Serveur 85 StationVelib, lecture JSON JSONArray jsonStations = new JSONArray(sb.toString()); for(int i=0; i< jsonStations.length(); i++){ JSONObject jsonObject = (JSONObject)jsonStations.get(i); StationVelib st = new StationVelib(); st.setName(jsonObject.getString("name")); st.setNumber(jsonObject.getInt("number")); st.setAddress(jsonObject.getString("address")); st.setFullAddress(jsonObject.getString("fullAddress")); st.setLatitude(jsonObject.getDouble("lat")); st.setLongitude(jsonObject.getDouble("lng")); st.setOpen(jsonObject.getBoolean("open")); st.setBonus(jsonObject.getBoolean("bonus"));
Android_Clients_Serveur 86 Démonstration
Android_Clients_Serveur 87 Conclusion Discussions