07.01.2013 Views

David Defour - Université de Perpignan

David Defour - Université de Perpignan

David Defour - Université de Perpignan

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

jeudi 26 janvier 12<br />

PROGRAMMATION SOUS<br />

ANDROID<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


• Equipements<br />

• Salle machine avec:<br />

ORGANISATIONS<br />

• 2 tablettes ACER Iconia A500 sous Android 3.2 (Honeycomb)<br />

• 2 tablettes Archos Internet Tablet 70 sous Android 2.2 (Froyo)<br />

• Au sujet <strong>de</strong> ce module<br />

• 9h <strong>de</strong> CM (6 x 1h 30)<br />

• 21h <strong>de</strong> TDO (7 x 3h)<br />

• Note pour l’UE : Projet final + soutenance<br />

• Terminologie<br />

jeudi 26 janvier 12<br />

A vos Machines


jeudi 26 janvier 12<br />

DESCRIPTION DU PROJET


• Honnêteté intellectuelle<br />

RECOMMANDATIONS<br />

• Toutes parties <strong>de</strong> co<strong>de</strong>, texte, algorithmes, ... qui n’est pas <strong>de</strong> vous et dont la référence n’est pas clairement<br />

indiquée conduira à un ZERO<br />

• Commentaires<br />

• Le programme <strong>de</strong>vra être clairement structuré (décrit dans le rapport) et commenté (utilisation <strong>de</strong><br />

javadoc et d’éclipse)<br />

• Délai<br />

• Le projet <strong>de</strong>vra impérativement être rendu avant le 31 mars 2012<br />

• Sujets<br />

jeudi 26 janvier 12<br />

• Un sujet vous est proposé par défaut,<br />

• En accord avec le responsable du cours il est possible <strong>de</strong> proposer un autre sujet avant le 15 février 2012


DESCRIPTION<br />

• Titre : Réalisation d’une interface en drag-&-drop d’un<br />

interpréteur <strong>de</strong> langage Logo sur le modèle <strong>de</strong> App Inventors<br />

• Objectifs<br />

jeudi 26 janvier 12<br />

• Rendre possible la programmation sur un périphérique<br />

Android<br />

• Programmer sans clavier<br />

(Attention: c’est une condition importante dans ce projet, il<br />

faut minimiser son usage)


DESCRIPTION DE L’INTERFACE<br />

• Fenêtre d’édition divisée en 2 parties<br />

• Une boite à objet avec <strong>de</strong>s boites symbolisant les briques <strong>de</strong> base du langage pour<br />

faire bouger la tortue<br />

• Une zone <strong>de</strong> programmation<br />

• Un interpréteur <strong>de</strong> votre langage pour visualiser le résultat<br />

• Fonctionnalités supplémentaires<br />

jeudi 26 janvier 12<br />

• Bouton «save», «load», «do», «undo», «<strong>de</strong>bug», «help», «procédures», «copy/paste»<br />

• Gestion <strong>de</strong>s erreurs


jeudi 26 janvier 12<br />

EXAMPLE: APP INVENTOR


• Déplacements<br />

• Gestion du trait<br />

STRUCTURATION DU<br />

• Gestion du contrôle<br />

jeudi 26 janvier 12<br />

LANGAGE


jeudi 26 janvier 12<br />

DÉPLACEMENTS<br />

Ordre Fonctions<br />

AV n Comman<strong>de</strong> à la tortue d’avancer <strong>de</strong> n pas<br />

TD n Comman<strong>de</strong> à la tortue d’effectuer une rotation <strong>de</strong> n <strong>de</strong>grés à droite<br />

TG n Comman<strong>de</strong> à la tortue d’effectuer une rotation <strong>de</strong> n <strong>de</strong>grés à gauche<br />

REC n Comman<strong>de</strong> à la tortue <strong>de</strong> reculer <strong>de</strong> n pas<br />

FPOS [n1 n2] Place la tortue à la position (n1,n2) <strong>de</strong> l’écran<br />

FCAP n Fixe le cap <strong>de</strong> la tortue


jeudi 26 janvier 12<br />

GESTION DU TRAIT<br />

Ordre Fonctions<br />

VE Efface l’écran<br />

MT Rend la tortue visible<br />

CT Rend la tortue invisible à l’utilisateur<br />

LC Deman<strong>de</strong> à la tortue <strong>de</strong> lever le crayon<br />

BC Deman<strong>de</strong> à la tortue <strong>de</strong> baisser le crayon<br />

FCC n Fixe la couleur du crayon <strong>de</strong> la tortue


GESTION DU CONTRÔLE<br />

Ordre Fonctions<br />

REPETE n [ liste ] Répète n fois les instructions contenues dans la liste<br />

HASARD n Renvoie un nombre compris entre 0 et n<br />

CAP Renvoie le cap <strong>de</strong> la tortue<br />

LOOP Renvoie le nombre <strong>de</strong> fois que l’instruction REPETE a été exécutée<br />

SI predicat<br />

[ liste 1] [ liste2 ]<br />

Si prédicat est vrai, exécute les instructions <strong>de</strong> liste1 sinon celles <strong>de</strong> liste2. La liste 2 est optionnelle.<br />

TANQUE exp [liste] Répète les instructions contenues dans liste tant que exp est vrai.<br />

jeudi 26 janvier 12


LANGAGE, FONCTIONNALITÉS<br />

• BONUS :<br />

jeudi 26 janvier 12<br />

• Gestions <strong>de</strong>s procédures<br />

AVANCÉES


RÉFÉRENCES:<br />

• http://lwh.free.fr/pages/prog/logo/Logo.pdf<br />

• http://www.appinventorbeta.com/learn/reference/in<strong>de</strong>x.html<br />

jeudi 26 janvier 12


PROGRAMMATION ANDROID:<br />

jeudi 26 janvier 12<br />

PRÉSENTATION<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


• Motivations<br />

RÉSUMÉ DU COURS<br />

• Web Apps vs. Mobile Apps<br />

• iPhone Apps vs. Android Apps<br />

• Livres & Références<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

WEB APPS VS.<br />

ANDROID APPS


AVANTAGES DES APPLI WEB<br />

• Accès universel<br />

• Navigateurs présent partout<br />

• N’importe quel périphérique connecté<br />

peu accé<strong>de</strong>r à du contenu<br />

• PCs, Macs, Linux, Android,<br />

iPhone, Blackberry, etc.<br />

• Mise à jour automatique<br />

• Le contenu vient du serveur =><br />

toujours à jour<br />

• Outils et métho<strong>de</strong>s éprouvées<br />

• Plusieurs langages<br />

• Java, PHP, .NET, Ruby/Rails, CGI, etc.<br />

jeudi 26 janvier 12


INCONVÉNIENTS DES APPLI<br />

WEB<br />

• Peu d’Interface HM avec peu <strong>de</strong> contrôle<br />

• Textfield, text area, button, checkbox, radio, list box, combo box. c’est tout ! Pas <strong>de</strong><br />

<strong>de</strong>ssin direct (Sauf pour les canvas en HTML5)<br />

• Ne peut pas interagir avec les ressources locales<br />

• Impossibilité <strong>de</strong> lire <strong>de</strong>s fichiers, d’appeler <strong>de</strong>s programmes ou d’accé<strong>de</strong>r aux<br />

périphériques <strong>de</strong> la machine<br />

• Communication inefficace<br />

• HTTP est un protocole faible<br />

• Difficulté d’écrite<br />

• Nécessite <strong>de</strong>s connaissances en plusieurs techno<br />

• Java, HTML, HTTP, CSS, JavaScript, XML<br />

• Conçu pour <strong>de</strong>s périphériques avec <strong>de</strong> grand écran et une souris<br />

• Plus difficile <strong>de</strong> les utiliser sur un plus petit téléphone avec écran tactile<br />

jeudi 26 janvier 12


AVANTAGES DES APPLI<br />

MOBILES<br />

• Plusieurs interfaces <strong>de</strong> contrôles GUI<br />

• Textfield, text area, button, checkbox, radio, list box, combo box,<br />

clock, calendar, date picker, dialog box, image gallery, etc.<br />

• Comparable à la programmation sur PC<br />

• Supports du <strong>de</strong>ssin direct<br />

• Les jeux animés <strong>de</strong> type Angry Birds sont possibles<br />

• Possibilité d’interagir avec les ressources locales<br />

jeudi 26 janvier 12<br />

• Possibilités <strong>de</strong> lire les fichiers (ex: liste <strong>de</strong> contact), BD locale,<br />

accès au GPS, lancement d’un appel GSM, accès au micro, au<br />

haut-parleur, lecture <strong>de</strong> l’orientation <strong>de</strong> l’écran, etc...


AVANTAGES DES APPS<br />

MOBILES<br />

• Communication efficace<br />

• Possibilité d’utiliser le protocole <strong>de</strong> communication <strong>de</strong> votre choix<br />

• Plus facile à écrire<br />

• Un seul langage à maîtriser<br />

• Java pour Android<br />

• Objective C pour iPhone<br />

• Conçu pour <strong>de</strong>s périphériques avec <strong>de</strong> petit écran tactile<br />

• Les apps et les interfaces GUI sont optimisées pour ce type<br />

d’environnement<br />

jeudi 26 janvier 12


INCONVÉNIENTS DES APPS<br />

• Pas d’accès universel<br />

MOBILES<br />

• Les Apps doivent être installées sur chaque périphérique<br />

• Une apps Android ne fonctionnera pas sur iPhone, Blackberry,<br />

PC, Mac, où box Linux<br />

• Gestion <strong>de</strong>s updates difficile<br />

• L’utilisateur doit intervenir pour installer la <strong>de</strong>rnière version<br />

• Plus récent (esp. Android)<br />

jeudi 26 janvier 12<br />

• Manque <strong>de</strong> standard, d’outils et <strong>de</strong> métho<strong>de</strong>s établits,<br />

• ... mais la programmation Android est proche <strong>de</strong> la<br />

programmation Java classique qui est elle ancienne.


ANDROID<br />

APPS<br />

VS.<br />

IPHONE APPS<br />

jeudi 26 janvier 12


INSTALLATION<br />

• Apps génériques<br />

• Sélection plus importante pour iPhone<br />

• Android essaie <strong>de</strong> se rattraper<br />

• Apps adhoc pour l’entreprise<br />

• Les apps iPhone ne peuvent s’installer que via l’App Store<br />

• Vous <strong>de</strong>vez soumettre votre apps à l’Apple App Store et obtenir leur feu vert, même<br />

pour <strong>de</strong>s applis privées <strong>de</strong>stinées à votre société.<br />

• (sauf si vous JailBreaké votre Iphone)<br />

• Les apps Android peuvent s’installées via :<br />

• Google App Store<br />

• Amazon App Store<br />

• Connexion USB à partir <strong>de</strong> votre PC<br />

• Email<br />

• Votre Site Web<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

LANGUAGES DE PROG<br />

• iPhone<br />

• Objective-C<br />

• Proche du C++, mais pas i<strong>de</strong>ntique<br />

• Android<br />

• Java<br />

• Langage le + utilisé dans le mon<strong>de</strong> <strong>de</strong> l’entreprise<br />

• C/C++<br />

• Possibilité d’appeler<br />

The real reason Android runs Java<br />

nativement (avec<br />

difficulté) via une<br />

approche <strong>de</strong> type JNI<br />

From Randall Munroe and xkcd.com


OS POUR LE<br />

DÉVELOPPEMENT DES APPS<br />

• iPhone<br />

• Macs<br />

• Android<br />

• Tout ce qui peut installer<br />

Java et Eclipse<br />

• Macs<br />

• PCs<br />

• Linux<br />

• Solaris<br />

jeudi 26 janvier 12<br />

From http://www.hongkiat.com/blog/mac-vs-pc-myth-busting-consumer-gui<strong>de</strong>/


jeudi 26 janvier 12<br />

PROGRAMMING JOBS:<br />

ANDROID VS. IPHONE<br />

• Cadre: In<strong>de</strong>ed.com ne montre que la tendance<br />

• Offre d’emploie contenant les 2 mots n’importe où<br />

• Biaisé par le site <strong>de</strong> références


GOOGLE SEARCH: ANDROID<br />

jeudi 26 janvier 12<br />

VS. IPHONE PROGRAMMING<br />

• Cadre: montre la tendance sur les volumes <strong>de</strong> requête<br />

• Example: plus <strong>de</strong> tuto clair pour Android or iPhone implique<br />

moins <strong>de</strong> recherche


GAINS LIÉS À LA PUBLICITÉ:<br />

ANDROID (53%) VS. IPHONE (27%)<br />

jeudi 26 janvier 12<br />

• Cadre: la pub ne correspond pas aux volumes, biaisé par les<br />

partenaires <strong>de</strong> Millennial Media


jeudi 26 janvier 12<br />

PRÉSENCE SUR LE MARCHÉ<br />

Cadre: basé sur une étu<strong>de</strong> et non sur <strong>de</strong>s volumes <strong>de</strong> vente réel.<br />

Raw data at http://www.comscore.com/Press_Events/Press_Releases/2011/7/comScore_Reports_May_2011_U.S._Mobile_Subscriber_Market_Share


IPHONE VS. ANDROID<br />

• Lequel utiliser personnellement<br />

• iPhone a plus <strong>de</strong> part <strong>de</strong> marché, un catalogue plus étoffé et<br />

<strong>de</strong>s utilisateurs plus loyaux<br />

• Android est plus ouvert et croit plus rapi<strong>de</strong>ment<br />

• Conclusion: pas <strong>de</strong> vainqueur clair, à vous <strong>de</strong> voir<br />

• Lequel choisir si vous avez <strong>de</strong>s apps maisons<br />

jeudi 26 janvier 12<br />

• Plus difficile avec l’iPhone qu’avec Android.<br />

• iPhone utilise Objective C et Android Java<br />

• Conclusion: Android est le vainqueur


jeudi 26 janvier 12<br />

CONCLUSION<br />

Présentation


RÉFÉRENCES<br />

• Livres (Par ordre <strong>de</strong> préférence)<br />

• Android Developer’s Cookbook (Steele & To)<br />

• Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development (Murphy)<br />

• En ligne seulement: http://commonsware.com/Android/<br />

• Android in Action, 2 nd Edition (Ableson, Sen, & King)<br />

• Android Application Development for Dummies (Felker)<br />

• Site web:<br />

• http://<strong>de</strong>veloper.android.com/<br />

• De loin la source la plus importante<br />

• Forum Android sur StackOverflow<br />

• http://stackoverflow.com/questions/tagged/android<br />

• La galerie <strong>de</strong>s widget Android<br />

• http://www.droiddraw.org/widgetgui<strong>de</strong>.html<br />

jeudi 26 janvier 12


• Web apps vs. Android apps<br />

jeudi 26 janvier 12<br />

RÉSUMÉ<br />

• Les apps Web fonctionnent sur n’importe quel <strong>de</strong>vice mais<br />

ont une interface GUI faible, ne peuvent utiliser <strong>de</strong><br />

ressources locales (fichiers, BD, GPS, camera) et sont plus<br />

agréable à utiliser avec un grand écran.<br />

• Les apps Android peuvent utiliser les ressources locales, sont<br />

optimisées pour les petits écrans, ont une GUI plus riches,<br />

mais ne peuvent pas être installé sur d’autres type <strong>de</strong> <strong>de</strong>vice.


jeudi 26 janvier 12<br />

QUESTIONS?


jeudi 26 janvier 12<br />

ANDROID: INSTALLATION &<br />

PREMIER DÉMARRAGE<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


RÉSUMÉ DU COURS<br />

• Installation <strong>de</strong>s logiciels et <strong>de</strong> la documentation<br />

• Java<br />

• Eclipse<br />

• Android SDK, base<br />

• Plugin Eclipse ADT<br />

• Mise à jour <strong>de</strong>s composants du SDK<br />

• AVD (Android Virtual Device)<br />

• Lancement d’une application<br />

jeudi 26 janvier 12<br />

• Importer et tester une application existante<br />

L’exécuter sur l’émulateur<br />

• Créer et tester une nouvelle application<br />

L’exécuter sur l’émulateur<br />

• Visualiser les sorties standards dans le DDMS<br />

• Déployer une application sur un périphérique Android connecté en mo<strong>de</strong> USB


jeudi 26 janvier 12<br />

INSTALLATION DE LA<br />

DOCUMENTATION ET DES<br />

LOGICIELS


• Présentation<br />

jeudi 26 janvier 12<br />

JDK POUR JAVA SE 6<br />

• Java 6 est la version la plus récente et rapi<strong>de</strong><br />

(Java 5 est supporté par Android mais non-recommandé)<br />

• Pour les PC, Linux :<br />

• http://www.oracle.com/technetwork/java/javase/downloads/<br />

• Télécharger le JDK et pas seulement le JRE<br />

• Télécharger la SE (Standard Edition), pas la EE ou la ME (Micro Edition)<br />

• Pas besoin <strong>de</strong> la version avec l’IDE NetBeans<br />

• Pour MAC<br />

• Rien a faire (java est installé et maintenu automatiquement)


INSTALLATION DE JAVA SE 6<br />

• http://www.oracle.com/technetwork/java/javase/downloads/<br />

Use this version. The “JDK – Java<br />

Development Kit” inclu<strong>de</strong>s compiler for .java<br />

files, whereas the “JRE – Java Runtime<br />

Environment” is only for executing<br />

prebuilt .class files.<br />

jeudi 26 janvier 12<br />

After downloading, run installer and accept all <strong>de</strong>faults.<br />

This tutorial uses Eclipse, so<br />

do not use this link.<br />

As of summer 2011, there is<br />

no NetBeans plugin for<br />

Android <strong>de</strong>velopment. So,<br />

Eclipse is strongly<br />

recommen<strong>de</strong>d even if you<br />

normally use NetBeans for<br />

Java <strong>de</strong>velopment. However,<br />

IntelliJ IDEA has Android<br />

support: see<br />

http://www.jetbrains.com/<br />

i<strong>de</strong>a/features/<br />

google_android.html


• Présentation<br />

ECLIPSE<br />

• Eclipse est un IDE libre, opensource. Supporte Java, HTML, CSS, Javascript, C++, PHP, ...<br />

• Google propose un plugin Eclipse pour l’intégration du SDK Android<br />

• Fonctionnalités<br />

jeudi 26 janvier 12<br />

• Générales<br />

• Vérifie la syntaxe lors <strong>de</strong> la saisie<br />

• Compilation automatique à chaque sauvegar<strong>de</strong><br />

• Factorisation du co<strong>de</strong>, <strong>de</strong>bbugage, templates<br />

• Spécifiques à Android<br />

• Facilite le déploiement d’apps Android vers l’émulateur<br />

• Configuration d’un environnement virtuel<br />

• Drag-&-Drop GUI


INSTALLATION D’ECLIPSE<br />

• http://eclipse.org, puis section “Downloads”<br />

jeudi 26 janvier 12<br />

• Résultats <strong>de</strong><br />

http://eclipse.org/downloads/<br />

• Sélectionner “for Java” où<br />

“for Java EE” (+ apps web)<br />

• Dernière version (3.6 – Helios) recommandée<br />

• Avant <strong>de</strong>rnière version (3.5 – Ganyme<strong>de</strong>) encore supportée<br />

• Versions plus anciennes (3.4 et


LANCER ECLIPSE<br />

• Dezippez le fichier téléchargé (pas d’installeur!)<br />

• Renommez le répertoire “installDir”<br />

• Double clickez sur eclipse.exe<br />

• A partir <strong>de</strong> installDir/bin<br />

• Clickez sur l’icone “Workbench”<br />

• Au prochain démarrage d’éclipse<br />

workbench apparaîtra<br />

automatiquement<br />

• Astuce:<br />

• Pensez à rajouter un raccourcit sur votre Bureau<br />

jeudi 26 janvier 12


ANDROID SDK<br />

• Présentation<br />

• Bibliothèque spécifique à Android<br />

• Compilateur Dalvik (Machine Virtuelle Android)<br />

• Emulateur Android (Pour tester sans périphérique Android)<br />

• Environnement <strong>de</strong> débuggage DDMS<br />

• Documentation<br />

• Installation<br />

• http://<strong>de</strong>veloper.android.com/sdk/installing.html<br />

• Developer’s Gui<strong>de</strong><br />

• http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/<strong>de</strong>veloping/in<strong>de</strong>x.html<br />

• JavaDoc (API Reference)<br />

• http://<strong>de</strong>veloper.android.com/reference/classes.html<br />

• Tutoriels & articles<br />

• http://<strong>de</strong>veloper.android.com/resources/in<strong>de</strong>x.html<br />

jeudi 26 janvier 12<br />

Bookmarkez ces URLs!


INSTALLATION DU SDK<br />

• Téléchargez et lancez l’installeur<br />

• A partir <strong>de</strong> http://<strong>de</strong>veloper.android.com/sdk/<br />

• I’installez dans C:\android-sdk-windows<br />

• Sets up basic SDK, but omits many components<br />

• Instructions détaillées<br />

• http://<strong>de</strong>veloper.android.com/sdk/installing.html<br />

• A faire plus tard<br />

• Après l’installation du plugin eclipse, nous lancerons la mise à jour<br />

du SDK, pour obtenir les composants manquants.<br />

• Plus facile à faire à partir d’eclipse qu’à partir <strong>de</strong> la ligne <strong>de</strong><br />

comman<strong>de</strong>.<br />

jeudi 26 janvier 12


• Présentation<br />

PLUGIN ADT<br />

• ADT (Android Development Tools) fournit plusieurs<br />

fonctionnalitées accessibles directement <strong>de</strong>puis eclipse :<br />

• Intégration entre Eclipse & les outils Android en lignes <strong>de</strong><br />

comman<strong>de</strong>s<br />

• Constructeur GUI en Drag-and-drop<br />

• Plusieurs ajouts pour le <strong>de</strong>v et <strong>de</strong>bug.<br />

• Instructions détaillées:<br />

jeudi 26 janvier 12<br />

• http://<strong>de</strong>veloper.android.com/sdk/eclipse-adt.html


INSTALLATION DE ADT<br />

• Etapes :<br />

• Démarrez Eclipse<br />

• Help � Install New Software …<br />

• Clickez sur “Add” dans le coin en haut à<br />

droite<br />

• Dans «Add Repository», pour le champ<br />

nom entrez «ADT Plugin» et pour le<br />

champ adresse saisissez https://dlssl.google.com/android/eclipse/<br />

• Clickez sur OK, sélectionnez la checkbox<br />

à coté <strong>de</strong> «Developer Tools», suivant,<br />

acceptez la licence et terminez.<br />

• Mettez à jour le plugin ADT<br />

• Help � Check for Updates<br />

jeudi 26 janvier 12


CONFIGURATION DE ADT<br />

• Définissez l’adresse du SDK<br />

• Window � Preferences � Android<br />

• Clickez Browse et indiquez l’endroit où vous avez installez le SDK<br />

• Optionnel: décochez envoyez les stats à Google<br />

• Window � Preferences � Android � Usage Stats<br />

jeudi 26 janvier 12


MISE À JOUR DES<br />

COMPOSANTS DU SDK<br />

• Lancez le SDK manager<br />

• Window � Android SDK & AVD Manager<br />

• Clickez sur “Available packages” à gauche<br />

• Sélectionnez toutes les entrées non-obsolète “Android<br />

Repository” entries<br />

• Sélectionnez la checkbox à côté <strong>de</strong> “Android<br />

Repository”, désélectionnez les entrées obsolètes,<br />

puis “Install Selected”<br />

• Prend un long moment pour s’exécuter<br />

• Instructions détaillées<br />

• http://<strong>de</strong>veloper.android.com/<br />

sdk/adding-components.html<br />

jeudi 26 janvier 12


ANDROID VIRTUAL DEVICES<br />

(AVDS)<br />

• Présentation<br />

• Un AVD (Android Virtual Device) est une configuration d’Emulateur<br />

Android qui vous laisse modéliser votre périphérique en définissant le<br />

hardware et le software présents<br />

• Concept<br />

• Définissez plusieurs AVDs avec différentes API Android pour tester vos apps<br />

avec au moins :<br />

• Une version récente (ex: 3.x ou 2.3.3)<br />

• Une version courante (2.2 as ou 2011)<br />

• Les statistiques d’utilisations <strong>de</strong>s périphériques Android sont disponible à<br />

http://<strong>de</strong>veloper.android.com/resources/dashboard/platform-versions.html<br />

• Instructions détaillées<br />

• http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/<strong>de</strong>veloping/<strong>de</strong>vices/managing-avds.html<br />

jeudi 26 janvier 12


DÉFINITION D’UN AVD<br />

• Création<br />

• Window � Android SDK puis AVD Manager<br />

• Clickez sur “Virtual <strong>de</strong>vices” à gauche. Clickez Ajout, choisissez options. Vous pouvez<br />

créer plusieurs AVDs..<br />

• Options<br />

• Cible (ex: version <strong>de</strong> l’API)<br />

• 3.x 4.x pour tester les tablettes<br />

• 2.3.3 pour tester les téléphones ‘récent’<br />

• 2.2 pour tester sur <strong>de</strong>s générations plus anciennes<br />

• Taille <strong>de</strong> la SD Card<br />

• Pas indispensable <strong>de</strong> le renseigner (ou alors 4 Go)<br />

• Skin<br />

• Choisissez «<strong>de</strong>fault for the target you chose»<br />

jeudi 26 janvier 12


LANCEMENT D’UNE APPS SUR<br />

jeudi 26 janvier 12<br />

L’EMULATEUR


DANS LES GRANDES LIGNES<br />

• Lancement d’une apps<br />

• Bientôt, vous écrirez votre apps et la lancerez, mais pour le moment , on va utiliser<br />

une apps toutes faites.<br />

• Façons <strong>de</strong> lancer une apps:<br />

• Couverte maintenant<br />

• Emulateur Android : Déploiement direct à partir d’Eclipse.<br />

• Lors <strong>de</strong> développement, vous utilisez ce mo<strong>de</strong> pour réaliser vos tests<br />

• Sur un périphérique Android : Déployé à partir d’un PC via le port USB.<br />

• Couverte plus tard dans cette sections<br />

• Sur un périphérique Android : Déployé à partir d’un site Web<br />

• Sur un périphérique Android : Déployé via les email.<br />

• Sur un périphérique Android : Déployé à partir <strong>de</strong> l’Android Market<br />

• Vos propres apps<br />

• Couvert plus tard, c’est la partie amusante !<br />

jeudi 26 janvier 12


LANCEMENT DE HELLOANDROID<br />

DANS L’EMULATEUR<br />

• HelloAndroid<br />

• Apps très simple à déployer et à exécuter<br />

• Téléchargez le projet à partir <strong>de</strong> la section «Getting Started» du tutoriel Android et<br />

importez le dans Eclipse.<br />

• http://www.coreservlets.com/android-tutorial/<br />

• Etapes<br />

• Import<br />

• File � General � Existing Projects…<br />

• Click-D sur ‘project’ à gauche<br />

• Run As � Android Application<br />

• Longue attente pour que l’émulateur s’initialise<br />

• Ne fermez pas l’émulateur lorsque vous avez finit !<br />

jeudi 26 janvier 12<br />

• La prochaine fois, l’apps se chargera plus rapi<strong>de</strong>ment


jeudi 26 janvier 12<br />

HELLOANDROID<br />

Co<strong>de</strong> will be discussed in next tutorial section.


jeudi 26 janvier 12<br />

HELLO ANDROID


CONCEPTS DE BASE<br />

• Concept<br />

• Lorsque vous créez une nouvelle apps, elle a un simple “Hello World” par défault<br />

• Vous pouvez donc créer une apps sans connaître la syntaxe<br />

(que nous verrons lors <strong>de</strong>s prochaines séances)<br />

• Etapes<br />

• File � New � Project � Android � Android Project<br />

• La prochaine fois, vous pourrez faire<br />

File � New � Android Project<br />

• Remplissez les options comme indiqué<br />

• Lancez le projet comme précé<strong>de</strong>mment<br />

• click-D � Run As � Android Application<br />

jeudi 26 janvier 12


DÉFINITION DES OPTIONS<br />

DU PROJETS<br />

• Paramétrage d’un nouveau projet Android<br />

• Project Name<br />

• Nom du projet sous eclipse, suivez votre propre convention.<br />

• Build Target<br />

• Version d’Android que vous souhaitez utiliser. Pour la plupart <strong>de</strong>s téléphone, choisissez 2.2 ce qui est le plus<br />

utilisé dans le mon<strong>de</strong>.<br />

• Application name<br />

• Nom <strong>de</strong> l’apps lisible par l’humain, le titre sera visible sur la barre Android.<br />

• Package name<br />

• L’application sur un <strong>de</strong>vice Android doit avoir un nom <strong>de</strong> paquet unique. Une façon <strong>de</strong> procé<strong>de</strong>r est <strong>de</strong><br />

faire : com.yourCompany.project<br />

• Create Activity<br />

• Le nom <strong>de</strong> la classe java la plus haute<br />

• Min SDK Version<br />

• Numéro qui doit correspondre au Build Target.<br />

Plus <strong>de</strong> détails à http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/appendix/api-levels.html<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

DÉFINITION DES OPTIONS<br />

DU PROJETS<br />

Eclipse project name<br />

Android version that you want to run on<br />

Human-readable app name<br />

Package. Use naming convention to ensure uniqueness<br />

Java class name<br />

Number corresponding to build target


LANCEMENT DE VOTRE APPS<br />

• Fonctionnalitées embarquées<br />

• Tout nouveau projet a automatiquement un comportement <strong>de</strong> type “Hello World”<br />

• Etape d’execution<br />

• click-D � Run As �<br />

Android Applicaton<br />

• Rappel : Ne fermez pas l’émulateur<br />

après vos tests.<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

VISUALISATION DES SORTIES<br />

STANDARDS AVEC DDMS


LES BASES DE DDMS<br />

• Concepts<br />

• DDMS (Dalvik Debug Monitor Service) est un outils qui réalise plusieurs choses<br />

• Simule un appel entrant sur l’émulateur<br />

• Peut définir une position GPS dans l’émulateur<br />

• Voir les print et les erreurs <strong>de</strong> runtime<br />

• Définir la position & prendre <strong>de</strong>s screenshots<br />

<strong>de</strong> votre <strong>de</strong>vice Android<br />

• Utilisation simple<br />

• Démarrez DDMS<br />

• Window �<br />

Open Perspective � DDMS<br />

• Une fois cette opération faite,<br />

vous pourrez clicker sur “DDMS” en haut<br />

à droite d’eclipse<br />

• Clickez sur “Java” poure revenir au co<strong>de</strong><br />

• Visualisation <strong>de</strong>s print<br />

• Observez dans la fenêtre ‘LogCat’ en bas<br />

• Type part of output into Filter field to see specific output<br />

jeudi 26 janvier 12


SORTIE DDMS<br />

(HELLOANDROID)<br />

• Co<strong>de</strong><br />

• Ajoutez un System.out.println<br />

Dans le main <strong>de</strong> la métho<strong>de</strong><br />

onCreate<br />

• Observez le co<strong>de</strong> dans la copie<br />

d’écran <strong>de</strong> la page précé<strong>de</strong>nte<br />

• La métho<strong>de</strong> onCreate et le reste<br />

sera abordé plus tard<br />

jeudi 26 janvier 12<br />

Output of System.out.println<br />

Entered so it is easier to find specific output among<br />

the many informational messages that emulator prints


LANCEMENT D’UNE APPS SUR<br />

jeudi 26 janvier 12<br />

UN PÉRIPHÉRIQUE ANDROID


LANCEMENT<br />

• Concept<br />

• La plupart <strong>de</strong>s tests que vous ferez seront réalisé dans l’émulateur Android. Parfois vous<br />

aurez besoin, <strong>de</strong> faire <strong>de</strong>s tests sur un VRAI <strong>de</strong>vice pour tester la compatibilité, la caméra<br />

(Réalité augmenté), le GPS, la liste <strong>de</strong>s contacts, ...<br />

• Vous <strong>de</strong>vez premièrement réaliser un package d’application signé (YourApp.apk). Ensuite, il y a plusieurs<br />

option pour l’envoyer sur le périphérique<br />

• Options<br />

• Couverte maintenant<br />

• Connexion USB, et adb pour la déployer<br />

• Couverte plus tard<br />

• Soumettre une application à l’Android Market<br />

• En autoformation ;)<br />

• Par l’envoie d’une apk par un email lu sur le téléphone<br />

• Déploiement <strong>de</strong> l’apps (fichier apk) sur un site web, et connexion sur ce site pour télécharger le fichier.<br />

( Il faut définir le type MIME à application/vnd.android.package-archive )<br />

jeudi 26 janvier 12


VIA L’USB<br />

• Prérequis : il faut installer les drivers pour le périphérique Android correspondant.<br />

• Brancher le <strong>de</strong>vice<br />

• Les OS récents <strong>de</strong>vraient trouver le driver automatiquement, sinon le télécharger à<br />

partir du site du constructeur :<br />

http://<strong>de</strong>veloper.android.com/sdk/oem-usb.html<br />

• Etapes<br />

• Sur le <strong>de</strong>vice Android<br />

• Dans préférence, passez en mo<strong>de</strong> <strong>de</strong>bug USB<br />

• Autorisez les sources inconnues<br />

• Eclipse<br />

• Exportez un package d’application signé (YourApp.apk)<br />

• adb<br />

• Allez dans sdk-install-dir\tools (où mettez ce chemin dans le PATH)<br />

• Lancez “adb install YourApp.apk”<br />

jeudi 26 janvier 12


CONFIGURATION DU DEVICE<br />

• Passer en mo<strong>de</strong> <strong>de</strong>bug USB<br />

• Settings � Applications �<br />

Development<br />

• Nécessaire : USB <strong>de</strong>bugging<br />

• permet au PC <strong>de</strong> se connecter en USB<br />

• Optionel: Stay awake<br />

• Le <strong>de</strong>vice ne passera pas en mo<strong>de</strong> eco<br />

• Optionel: Allow mock locations<br />

• Autorise le PC à envoyer <strong>de</strong> faux<br />

signaux GPS<br />

• Autoriser les sources inconnues<br />

• Settings � Applications �<br />

Unknown sources<br />

jeudi 26 janvier 12


EXPORTER UN PACKAGE<br />

• A faire à chaque fois : Export<br />

• click-D Eclipse project<br />

• Android Tools � Export<br />

Signed Application Package<br />

• Uniquement la première: définition d’une clé<br />

• Il vous sera <strong>de</strong>mandé <strong>de</strong> donner l’adresse<br />

d’un fournisseur <strong>de</strong> clé et un mot <strong>de</strong><br />

passe. La clé sera crée et l’apps signée, ce<br />

qui est un format vali<strong>de</strong> mais elle ne sera<br />

pas certifié par un organisme <strong>de</strong><br />

confiance.<br />

jeudi 26 janvier 12


INSTALLATION AVEC ADB<br />

• Connectez le <strong>de</strong>vice en USB<br />

• Ouvrez une fenêtre <strong>de</strong> comman<strong>de</strong><br />

• Windows Start Menu � Run � cmd<br />

• Allez dans le répertoire du SDK “platform-tools”<br />

• ..\android-sdk\platform-tools<br />

• Exécutez “adb install YourApp.apk”<br />

• > adb install HelloAndroid.apk<br />

1439 KB/s (13262 bytes in 0.009s)<br />

pkg: /data/local/tmp/HelloAndroid.apk<br />

Success<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

LANCEMENT DE L’APP<br />

• Allez dans applications ou installed<br />

apps<br />

• Tapez new app<br />

• Rappelez vous du nom humain<br />

donné à votre appli lors <strong>de</strong> sa<br />

création (Application Name)<br />

c’est celui qui apparait ici.<br />

• Pour mettre à jour le programme<br />

• Désinstallez au préalable la<br />

précé<strong>de</strong>nte version<br />

• Settings � Applications<br />

� YourApp � Uninstall


jeudi 26 janvier 12<br />

CONCLUSION


RÉSUMÉ<br />

• Installation <strong>de</strong>s logiciels (venez avec vos PC la prochaine fois si vous voulez)<br />

• Java 6, Eclipse, Android SDK, Eclipse ADT plugin<br />

• Mise à jour <strong>de</strong> vos Bookmarks pour la doc<br />

• Developer’s Gui<strong>de</strong> et + à <strong>de</strong>veloper.android.com<br />

• Mise à jour et configuration <strong>de</strong>s logiciels<br />

• Adresse du SDK dans Eclipse<br />

• Mise à jour <strong>de</strong>s composants via le SDK & AVD Manager<br />

• Définition d’au moins une AVD pour lancer vos apps sur un émulateur<br />

• Lancement d’une apps<br />

• Sur l’émulateur (la plupart du tps). click-D project, Run As � Android Application.<br />

• Sur le <strong>de</strong>vice (<strong>de</strong> tps en tps). construction d’un apk signé et utilisation d’adb.<br />

• Réalisation d’une nouvelle app<br />

• File � New � Project � Android � Android Project<br />

• Visualisation <strong>de</strong> la sortie d’écran <strong>de</strong> print<br />

• Dans la fenêtre LogCat <strong>de</strong> DDMS<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

QUESTIONS?


CONCEPTS DE BASE DE LA<br />

PROGRAMMATION ANDROID<br />

jeudi 26 janvier 12<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


RÉSUMÉ DU COURS<br />

• Réaliser & tester un projet Android<br />

• Structure <strong>de</strong> base d’un programme<br />

• Layout Java<br />

• Layout XML<br />

• Eclipse ADT visual layout editor<br />

• Layout Hybrid<br />

• Résumé <strong>de</strong> la structure d’un Project<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

RÉALISER UN PROJET<br />

ANDROID


PETIT RAPPEL<br />

• Déjà installé<br />

• Java 6<br />

• Eclipse<br />

• Android SDK<br />

• Eclipse ADT Plugin<br />

• Déjà configuré<br />

• Les composants SDK d’Android sont à jour<br />

• Eclipse préférences<br />

• Adresse du SDK Android définie<br />

• Au moins 1 AVD (Android Virtual Device) définit<br />

• Documentation<br />

• http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/<strong>de</strong>veloping/in<strong>de</strong>x.html<br />

• http://<strong>de</strong>veloper.android.com/reference/packages.html<br />

jeudi 26 janvier 12


RÉALISER VOTRE PROPRE<br />

PROJET ANDROID: LES BASES<br />

• Concepts<br />

• Lors <strong>de</strong> la création d’une nouvelle apps, elle dispose déjà <strong>de</strong>s fonctionnalités du<br />

‘HelloWorld’.<br />

• So, you can create and test an app without knowing syntax (which is not<br />

discussed until next tutorial section)<br />

• Steps<br />

• File � New � Project � Android � Android Project<br />

• Once you do this once, next time you<br />

can do File � New � Android Project<br />

• Fill in options as shown on next page<br />

• Run new project as shown previously<br />

• R-click � Run As �<br />

Android Application<br />

jeudi 26 janvier 12


DÉFINITION DES OPTIONS<br />

DU PROJETS<br />

• Paramétrage d’un nouveau projet Android<br />

• Project Name<br />

• Nom du projet sous eclipse, suivez votre propre convention.<br />

• Build Target<br />

• Version d’Android que vous souhaitez utiliser. Pour la plupart <strong>de</strong>s téléphone, choisissez 2.2 ce qui est le plus<br />

utilisé dans le mon<strong>de</strong>.<br />

• Application name<br />

• Nom <strong>de</strong> l’apps lisible par l’humain, le titre sera visible sur la barre Android.<br />

• Package name<br />

• L’application sur un <strong>de</strong>vice Android doit avoir un nom <strong>de</strong> paquet unique. Une façon <strong>de</strong> procé<strong>de</strong>r est <strong>de</strong><br />

faire : com.yourCompany.project<br />

• Create Activity<br />

• Le nom <strong>de</strong> la classe java la plus haute<br />

• Min SDK Version<br />

• Numéro qui doit correspondre au Build Target.<br />

Plus <strong>de</strong> détails à http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/appendix/api-levels.html<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

DÉFINITION DES OPTIONS<br />

DU PROJETS<br />

Eclipse project name<br />

Android version that you want to run on<br />

Human-readable app name<br />

Package. Use naming convention to ensure uniqueness<br />

Java class name<br />

Number corresponding to build target


LANCEMENT DE VOTRE APPS<br />

• Fonctionnalitées embarquées<br />

• Tout nouveau projet a automatiquement un comportement <strong>de</strong> type “Hello World”<br />

• Etape d’execution<br />

• click-D � Run As �<br />

Android Applicaton<br />

• Rappel : Ne fermez pas l’émulateur<br />

après vos tests.<br />

jeudi 26 janvier 12


LANCER UNE NOUVELLE APP<br />

SUR UN DEVICE ANDROID<br />

• Apps non signée : trivial<br />

• Brancher le téléphone et la lancer à partir d’Eclipse<br />

• Etapes<br />

jeudi 26 janvier 12<br />

• Configurer le téléphone pour accepter <strong>de</strong>s apps non vérifiées<br />

• Arrêter l’émulateur<br />

• Brancher le dévice<br />

• Click-D «project»<br />

• Run As � Android Application<br />

• Cela installe et lance l’apps. L’apps est laissée sur le <strong>de</strong>vice<br />

même une fois celui-ci débranché.


CONFIGURATION DU DEVICE<br />

• Passer en mo<strong>de</strong> <strong>de</strong>bug USB<br />

• Settings � Applications �<br />

Development<br />

• Nécessaire : USB <strong>de</strong>bugging<br />

• permet au PC <strong>de</strong> se connecter en USB<br />

• Optionel: Stay awake<br />

• Le <strong>de</strong>vice ne passera pas en mo<strong>de</strong> eco<br />

• Optionel: Allow mock locations<br />

• Autorise le PC à envoyer <strong>de</strong> faux<br />

signaux GPS<br />

• Autoriser les sources inconnues<br />

• Settings � Applications �<br />

Unknown sources<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

STRUCTURE D’UN<br />

PROGRAMME


STRUCTURE GÉNÉRALE<br />

(COMMUNE À TOUTES LES<br />

package com.companyname.projectname;<br />

import android.app.Activity;<br />

import android.os.Bundle;<br />

import android.widget.SomeLayoutOrView;<br />

APPROCHES)<br />

There is no need to type the import statements by hand. Just use the classes in your co<strong>de</strong>, and when<br />

Eclipse marks the line as an error, click on the light bulb at the left, or hit Control-1, then choose to have<br />

Eclipse insert the import statements for you.<br />

public class SomeName extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

SomeLayoutOrView view = createOrGetView();<br />

...<br />

setContentView(view);<br />

}<br />

...<br />

}<br />

jeudi 26 janvier 12<br />

Apps are frequently shut down by the <strong>de</strong>vice. This lets<br />

you remember some info about the previous invocation.<br />

Covered in later lectures, but for now, just know that you<br />

should always call super.onCreate as first line of<br />

onCreate.<br />

I also follow a few official Android coding conventions here (4-space in<strong>de</strong>ntation, no *’s in imports, {’s on same line as previous co<strong>de</strong>, @Overri<strong>de</strong> where appropriate). Conventions<br />

are strictly enforced in official co<strong>de</strong>, and are used in all examples and tutorials. So, you might as well follow the conventions from the beginning. Follow these simple ones for<br />

now, and a later lecture will give coding convention <strong>de</strong>tails and provi<strong>de</strong> an Eclipse preferences file to help with them.


LES 3 APPROCHES<br />

PRINCIPALES<br />

• Java<br />

• Définition directement en Java <strong>de</strong>s Strings Strings, window layout window, création <strong>de</strong>s boîtes<br />

<strong>de</strong> contrôle, et assignation <strong>de</strong>s event handlers. (~ Programmation swing)<br />

• XML<br />

• Définition à l’ai<strong>de</strong> <strong>de</strong> fichiers XML les Strings, window layout, création <strong>de</strong>s boîtes <strong>de</strong><br />

contrôle, et assignation <strong>de</strong>s event handlers. Les métho<strong>de</strong>s Java liront le layout à partir du<br />

fichier XML et le à setContentView.<br />

• Hybri<strong>de</strong><br />

• Utilisation <strong>de</strong>s fichiers XML pour la définition <strong>de</strong>s Strings, window layout et la création <strong>de</strong>s<br />

boîtes <strong>de</strong> contrôle. Utilisation <strong>de</strong> Java pour l’assignation <strong>de</strong>s event handlers.<br />

• Exemples dans ce tutoriel<br />

• Le bouton qui dit “Show Greeting”. Un petit message popup apparaîtra lorsque le bouton<br />

sera pressé.<br />

• Implémenté selon les 3 façons.<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

APPROCHE JAVA: SCHÉMA<br />

public class SomeName extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

String message = "...";<br />

LinearLayout window = new LinearLayout(this);<br />

window.setVariousAttributes(…);<br />

Button b = new Button(this);<br />

b.setText("Button Label");<br />

b.setOnClickListener(new SomeHandler());<br />

mainWindow.addView(b);<br />

...<br />

setContentView(window);<br />

}<br />

private class SomeHandler implements OnClickListener {<br />

@Overri<strong>de</strong><br />

public void onClick(View clickedButton) {<br />

doSomething(...);<br />

}<br />

} }<br />

OnClickListener is a public inner class insi<strong>de</strong> View. But, as long as you import android.view.View.OnClickListener, you use it just<br />

like a normal class. And, remember that Eclipse helps you with imports: just type in the class name, then either click on the light<br />

bulb or hit Control-1 to have Eclipse insert the proper import statements for you.


APPROCHE XML: SCHÉMA<br />

• Java<br />

public class SomeClass extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

public void handlerMethod(View clickedButton) {<br />

String someName = getString(R.string.some_name);<br />

doSomethingWith(someName);<br />

} }<br />

• XML<br />

jeudi 26 janvier 12<br />

res/values/strings.xml res/layout/main.xml<br />

<br />

<br />

…<br />

…<br />

<br />

<br />

<br />

<br />

<br />


APPROCHE HYBRIDE: SCHÉMA<br />

• Java<br />

public class SomeClass extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

Button b = (Button)findViewById(R.id.button_id);<br />

b.setOnClickListener(new SomeHandler());<br />

}<br />

private class SomeHandler implements OnClickListener {<br />

@Overri<strong>de</strong><br />

public void onClick(View clickedButton) {<br />

doSomething(...);<br />

}<br />

} }<br />

• XML<br />

• On donne un ID aux controls qui ont besoin d’un handlers<br />

• NE PAS utiliser android:onClick pour attribuer un handler<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

LAYOUT JAVA


CONCEPTS<br />

• Approche<br />

• Définition directement en Java <strong>de</strong>s Strings Strings, window layout window,<br />

création <strong>de</strong>s boîtes <strong>de</strong> contrôle, et assignation <strong>de</strong>s event handlers. (~<br />

Programmation swing)<br />

• Avantages<br />

• Proche <strong>de</strong>s métho<strong>de</strong>s <strong>de</strong> <strong>de</strong>v sur <strong>de</strong>ktop. (~ Swing, SWT & AWT).<br />

• Bien pour les layouts dynamique (ex: qui change en fonction fonction du<br />

programme).<br />

• Inconvénients<br />

• Difficile à maintenir (~discutable, mais il y a consensus)<br />

• Fonctionnement chaotique avec I18N<br />

• Pas recommandé sauf pour les layouts dynamiques<br />

• Acceptable pour l’App Store sous réserve d’un bon fonctionnement (il n’y a<br />

pas <strong>de</strong> police qui traque les mauvais élèves/co<strong>de</strong>urs).<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

CODE (CORPS)<br />

public class SayHelloJava extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

String appName = "SayHello Application";<br />

String windowText =<br />

"Press the button below to receive " +<br />

"a friendly greeting from Android.";<br />

String buttonLabel = "Show Greeting";<br />

LinearLayout mainWindow = new LinearLayout(this);<br />

mainWindow.setOrientation(LinearLayout.VERTICAL);<br />

setTitle(appName);<br />

TextView label = new TextView(this);<br />

label.setText(windowText);<br />

mainWindow.addView(label);<br />

Button greetingButton = new Button(this);<br />

greetingButton.setText(buttonLabel);<br />

greetingButton.setOnClickListener(new Toaster());<br />

mainWindow.addView(greetingButton);<br />

setContentView(mainWindow);<br />

}


}<br />

jeudi 26 janvier 12<br />

CODE (EVENT HANDLER)<br />

private class Toaster implements OnClickListener {<br />

@Overri<strong>de</strong><br />

public void onClick(View clickedButton) {<br />

String greetingText = "Hello from Android!";<br />

Toast tempMessage =<br />

Toast.makeText(SayHelloJava.this,<br />

greetingText,<br />

Toast.LENGTH_SHORT);<br />

tempMessage.show();<br />

}


RÉSULTAT SUR L’ ÉMULATEUR<br />

• click-D, Run As � Android Application<br />

jeudi 26 janvier 12


RÉSULTATS SUR UN DEVICE<br />

• Configurez le <strong>de</strong>vice<br />

• Arrêter l’émulateur, branchez le <strong>de</strong>vice<br />

• Click-D project, Run As � Android Application<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

LAYOUT XML


CONCETS<br />

• Approche<br />

• Définition à l’ai<strong>de</strong> <strong>de</strong> fichiers XML les Strings, window layout, création <strong>de</strong>s boîtes <strong>de</strong><br />

contrôle, et assignation <strong>de</strong>s event handlers.<br />

• Définition <strong>de</strong>s layout et contrôles dans res/layout/main.xml<br />

• Définition <strong>de</strong>s Strings dans res/values/strings.xml<br />

• Avantages<br />

• Plus facile à maintenir<br />

• Bonne compatibilité avec I18N<br />

• Possibilité d’utiliser l’éditeur Visuel d’Eclipse<br />

• Approche Standard/recommndée<br />

(avec l’approche hybri<strong>de</strong>)<br />

• Inconvénients<br />

• Ne fonctionne pas avec les layouts dynamiques<br />

jeudi 26 janvier 12


PLUS DE DÉTAILS<br />

• res/layout/main.xml<br />

• Définit le layout et le controls à l’ai<strong>de</strong> d’une <strong>de</strong>scription XML<br />

• Define controls<br />

• Fait référence aux strings (<strong>de</strong> strings.xml) avec @string/string_name<br />

• Assigne un event handler avec android:onClick<br />

• res/values/strings.xml<br />

• Définit les strings utilisées dans le GUI ou qui peuvent changer avec I18N<br />

res/layout/main.xml<br />

• Co<strong>de</strong> Java<br />

• Fait référence aux layout avec R.layout.main<br />

• Fait référence aux strings avec getString(R.string.string_name)<br />

• Fait référence aux controls avec findViewById(R.id.some_id)<br />

• Plus d’info<br />

• http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/ui/<strong>de</strong>claring-layout.html<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

LAYOUT DU PROJET<br />

Refers to layout <strong>de</strong>fined in res/layout/main.xml with<br />

R.layout.main.<br />

Refers to strings <strong>de</strong>fined in res/values/strings.xml with<br />

getString(R.string.string_name)<br />

Defines screen layout and GUI controls. Optionally assigns event<br />

handlers to controls.<br />

Refers to strings <strong>de</strong>fined in res/values/strings.xml with @string/<br />

string_name<br />

Conventional for main file to be called main.xml, but not required. If it is<br />

foo.xml, then Java uses R.layout.foo. As we will see later, complex apps<br />

have several layout files for different screens.<br />

Defines strings that are either used in GUI controls or that might<br />

change with internationalization.


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

These attributes (android:orientation, etd.)<br />

are <strong>de</strong>fined in JavaDoc API for<br />

LinearLayout.<br />

These strings are <strong>de</strong>fined in res/values/<br />

strings.xml<br />

This must be a public method in main class, have a void<br />

return type, and take a View as argument. No interface<br />

needs to be implemented, as it does with event handlers<br />

referred to in Java co<strong>de</strong>.


RES/VALUES/STRINGS.XML<br />

<br />

<br />

Say Hello Application<br />

<br />

Press the button below to receive<br />

a friendly greeting from Android.<br />

<br />

Show Greeting<br />

Hello from Android!<br />

<br />

jeudi 26 janvier 12<br />

app_name is special, pre<strong>de</strong>fined name (although it can be<br />

overrid<strong>de</strong>n in AndroidManifest.xml)<br />

All the rest are <strong>de</strong>veloper-specified names.<br />

main.xml refers to this with @string/greeting_text<br />

Java refers to this with getString(R.string.greeting_text)<br />

Eclipse auto-completion will recognize the names when editing other<br />

files that use them.


}<br />

jeudi 26 janvier 12<br />

CODE (JAVA)<br />

public class SayHelloXml extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

public void showToast(View clickedButton) {<br />

String greetingText = getString(R.string.greeting_text);<br />

Toast tempMessage =<br />

Toast.makeText(this, greetingText,<br />

Toast.LENGTH_SHORT);<br />

tempMessage.show();<br />

}


• Dans l’émulateur<br />

• Click-D project, Run As �<br />

Android Application<br />

RÉSULTATS<br />

• Apparence & comportement i<strong>de</strong>ntique à l’exemple tout Java<br />

• Sur le <strong>de</strong>vice<br />

• Configurez le téléphone<br />

• Arrêtez l’émulateur et branchez le <strong>de</strong>vice<br />

• Click-D project, Run As � Android Application<br />

jeudi 26 janvier 12<br />

• Apparence & comportement i<strong>de</strong>ntique à l’exemple tout Java


jeudi 26 janvier 12<br />

ECLIPSE ADT<br />

VISUAL LAYOUT EDITOR


ECLIPSE VISUAL GUI BUILDER &<br />

EDITOR<br />

• Invocation<br />

• Lors <strong>de</strong> l’édition du main.xml, clickez sur Graphical Layout<br />

• Fonctionnalités<br />

• Peut changez interactivement les attributs du layout (vertical/horizontal, caractéristiques, etc.)<br />

• Peut faire du drag&drop à partir <strong>de</strong> la palette <strong>de</strong> contrôle GUI disponible<br />

• Peut définir interactivement les caractéristiques <strong>de</strong> contrôle (couleurs, remplissage, event<br />

handler, etc.)<br />

• Prévisualisation<br />

• Attention<br />

• Bien que l’éditeur visuel est très pratique, cela ne vous dispense pas <strong>de</strong> l’édition manuelle <strong>de</strong>s<br />

fichiers XML, pour définir l’in<strong>de</strong>ntation, l’ordre <strong>de</strong>s attributs ....<br />

• Plus d’info<br />

• http://tools.android.com/recent<br />

• http://www.youtube.com/watch?v=Oq05KqjXTvs<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

ECLIPSE VISUAL LAYOUT<br />

EDITOR


jeudi 26 janvier 12<br />

HYBRID LAYOUT


• Approches<br />

CONCEPTS<br />

• Utilisation <strong>de</strong>s fichiers XML pour la définition <strong>de</strong>s Strings,<br />

window layout et la création <strong>de</strong>s boîtes <strong>de</strong> contrôle.<br />

• Utilisation <strong>de</strong> Java pour l’assignation <strong>de</strong>s event handlers.<br />

• Avantages<br />

• Les mêmes que pour l’approche XML<br />

• Mais, puisque les event handler ont besoin d’être édité en Java, il<br />

y a plus <strong>de</strong> sens <strong>de</strong> les assignés en aussi en Java.<br />

• Inconvénients<br />

jeudi 26 janvier 12<br />

• Ne fonctionne pas avec les layouts dynamiques


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

We <strong>de</strong>fine an id for the button, so that the<br />

button can be referred to in Java co<strong>de</strong> with<br />

findViewById(R.id.greeting_button)<br />

We do not assign an event handler to the button, as<br />

we did in the previous example.


RES/VALUES/STRINGS.XML<br />

<br />

<br />

Say Hello Application<br />

<br />

Press the button below to receive<br />

a friendly greeting from Android.<br />

<br />

Show Greeting<br />

Hello from Android!<br />

<br />

jeudi 26 janvier 12<br />

No changes from previous example.


jeudi 26 janvier 12<br />

CODE (JAVA)<br />

public class SayHelloHybrid extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

Button greetingButton =<br />

(Button)findViewById(R.id.greeting_button);<br />

greetingButton.setOnClickListener(new Toaster());<br />

}<br />

private class Toaster implements OnClickListener {<br />

@Overri<strong>de</strong><br />

public void onClick(View clickedButton) {<br />

String greetingText = getString(R.string.greeting_text);<br />

Toast tempMessage =<br />

Toast.makeText(SayHelloHybrid.this,<br />

greetingText,<br />

Toast.LENGTH_SHORT);<br />

tempMessage.show();<br />

}<br />

}}<br />

You must call setContentView before<br />

calling findViewById. If you call<br />

findViewById first, you get null.


• Dans l’émulateur<br />

• Click-D project, Run As �<br />

Android Application<br />

RÉSULTATS<br />

• Apparence & comportement i<strong>de</strong>ntique à l’exemple tout Java<br />

• Sur le <strong>de</strong>vice<br />

• Configurez le téléphone<br />

• Arrêtez l’émulateur et branchez le <strong>de</strong>vice<br />

• Click-D project, Run As � Android Application<br />

jeudi 26 janvier 12<br />

• Apparence & comportement i<strong>de</strong>ntique à l’exemple tout Java


jeudi 26 janvier 12<br />

CONCLUSION


jeudi 26 janvier 12<br />

PROJECT LAYOUT<br />

Refers to layout <strong>de</strong>fined in res/layout/main.xml with<br />

R.layout.main.<br />

Refers to controls <strong>de</strong>fined in res/layout/main.xml with<br />

findViewById(R.id.some_id)<br />

Refers to strings <strong>de</strong>fined in res/values/strings.xml with<br />

getString(R.string.string_name)<br />

Defines screen layout and GUI controls. Optionally assigns event<br />

handlers to controls.<br />

Refers to strings <strong>de</strong>fined in res/values/strings.xml with @string/<br />

string_name<br />

Defines strings that are either used in GUI controls or that might<br />

change with internationalization.


RÉSUMÉ<br />

• XML<br />

• res/layout/main.xml<br />

• Définit les propriétés du layout et le contrôle du GUI.<br />

• Parfois assigne <strong>de</strong>s event handlers à du contrôle<br />

• res/values/strings.xml<br />

• Définit les Strings utilisés dans le GUI ou pour le I18N.<br />

• Java<br />

• La classe principale étend la classe Action<br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

maybeFindControlAndAssignHandler(…);<br />

}<br />

• Le Event handler prend un View en argument<br />

• Si il est assigné en Java, il faut implémenter<br />

OnClickListener (ou un autre Listener)<br />

jeudi 26 janvier 12<br />

Call setContentView<br />

before calling<br />

findViewById.<br />

Widget event handling is<br />

covered in <strong>de</strong>tail in next<br />

tutorial section.


jeudi 26 janvier 12<br />

QUESTIONS?


jeudi 26 janvier 12<br />

WIDGET EVENT HANDLING<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


RÉSUMÉ DU COURS<br />

• Utilisation d’une classe Listener séparée<br />

• Utilisation d’une inner classe nommée<br />

• Utilisation d’une inner classe anonyme<br />

• Utilisation <strong>de</strong> l’ Activity<br />

• et implémentation <strong>de</strong> l’interface Listener<br />

• Utilisation <strong>de</strong> l’ Activity<br />

• et spécification <strong>de</strong>s métho<strong>de</strong>s dans le fichier layout<br />

(main.xml)<br />

• Copie et rennomage <strong>de</strong> projet Android sous Eclipse<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

UTILISATION D’UNE CLASSE<br />

LISTENER SÉPARÉE


CONCEPTS<br />

• Buts<br />

• Changer la couleurs d’un TextView lorsqu’un Button ou RadioButton est pressé.<br />

Gestion <strong>de</strong> différentes couleurs en fonction du bouton.<br />

• Approches<br />

• Utilisation d’une classe externe qui implémente View.OnClickListener<br />

• Import android.view.View.OnClickListener, et dit alors “implements OnClickListener”<br />

• Avantages<br />

• Il est possible <strong>de</strong> donner <strong>de</strong>s arguments pour changer le comportement<br />

• La séparation <strong>de</strong>s classes généralement ne promouvoit qu’un couplage faible<br />

• Si le gestionnaire d’événement peut s’appliquer à différents contrôles, il peut être changé<br />

indépendamment du reste <strong>de</strong> l’application..<br />

• Inconvénients<br />

• Si vous voulez appeler du co<strong>de</strong> à partir du main Activity, vous aurez besoin <strong>de</strong><br />

références<br />

• En plus le co<strong>de</strong> dans le main Activity doit être public<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

RÉSUMÉ SUR LE LAYOUT<br />

Button<br />

Button<br />

Button<br />

Horizontal<br />

RadioGroup<br />

(Containing 3 RadioButtons)<br />

TextView<br />

(No text, but controls will<br />

change the background<br />

color of this region.)<br />

Vertical<br />

LinearLayout<br />

An upcoming tutorial section gives <strong>de</strong>tails on using layouts. However, you can<br />

do a pretty lot now by knowing just two simple things:<br />

1) You can make some pretty complex layouts by nesting horizontal and<br />

vertical layouts insi<strong>de</strong> each other.<br />

2) You can experiment interactively with the visual layout editor in Eclipse.<br />

Edit main.xml and click on Graphical Layout.


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

Overall layout is a vertical stack of graphical items.<br />

This part <strong>de</strong>fines the 3 buttons shown on the previous sli<strong>de</strong>.<br />

Each button is given an id so that it can be found in Java via<br />

findViewById, then assigned an event handler via<br />

setOnClickListener.<br />

The text (Button label) is taken from strings.xml instead of<br />

entered directly here, because the same label will also be used<br />

for RadioButtons.


jeudi 26 janvier 12<br />

RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

A horizontal RadioGroup gives the same layout as a<br />

horizontal LinearLayout, except that it contains only<br />

RadioButtons. A RadioGroup also means that only<br />

one of the RadioButtons insi<strong>de</strong> can be selected at<br />

any given time.


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

jeudi 26 janvier 12<br />

This <strong>de</strong>fines the blank region at the bottom that will<br />

change colors when the Buttons or RadioButtons<br />

are clicked. I used a TextView because I might later<br />

want to put some text insi<strong>de</strong>.


RES/VALUES/STRINGS.XML<br />

<br />

<br />

Event Handling Example<br />

Red<br />

Blue<br />

Yellow<br />

<br />

jeudi 26 janvier 12<br />

main.xml refers to these names with @string/red_prompt, @string/<br />

blue_prompt, and @string/yellow_prompt.<br />

Each string is used as label for one Button and one RadioButton.


jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

public class Events1Example extends Activity {<br />

private View mColorRegion;<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

Button b1 = (Button)findViewById(R.id.button1);<br />

Button b2 = (Button)findViewById(R.id.button2);<br />

Button b3 = (Button)findViewById(R.id.button3);<br />

RadioButton r1 =<br />

(RadioButton)findViewById(R.id.radio_button1);<br />

RadioButton r2 =<br />

(RadioButton)findViewById(R.id.radio_button2);<br />

RadioButton r3 =<br />

(RadioButton)findViewById(R.id.radio_button3);<br />

This part just looks up the controls<br />

that were <strong>de</strong>fined in main.xml, and<br />

assigns them to variables. Note the<br />

Android coding convention that nonpublic<br />

instance variables (data<br />

members) start “m”.


}<br />

}<br />

jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

(CONTINUED)<br />

b1.setOnClickListener(new ColorSetter(Color.RED, this));<br />

b2.setOnClickListener(new ColorSetter(Color.BLUE, this));<br />

b3.setOnClickListener(new ColorSetter(Color.YELLOW, this));<br />

r1.setOnClickListener(new ColorSetter(Color.RED, this));<br />

r2.setOnClickListener(new ColorSetter(Color.BLUE, this));<br />

r3.setOnClickListener(new ColorSetter(Color.YELLOW, this));<br />

public void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

}<br />

Since this method will be called<br />

by method in separate event<br />

handler class, it must be public.<br />

Assigns a separate class as the event handler for<br />

each of the Buttons and RadioButtons.<br />

Good news: you can pass arguments to the event<br />

handler (the colors) so that the same event<br />

handler class can have different behaviors for<br />

different controls.<br />

Bad news: you have to pass a reference to the<br />

main Activity (“this” above) so that the event<br />

handler can call back to co<strong>de</strong> in the Activity.


}<br />

jeudi 26 janvier 12<br />

EVENT HANDLER CLASS<br />

public class ColorSetter implements OnClickListener {<br />

private int regionColor;<br />

private Events1Example mainActivity;<br />

public ColorSetter(int regionColor,<br />

Events1Example mainActivity) {<br />

this.regionColor = regionColor;<br />

this.mainActivity = mainActivity;<br />

}<br />

@Overri<strong>de</strong><br />

public void onClick(View v) {<br />

mainActivity.setRegionColor(regionColor);<br />

}<br />

Event handler must store a reference to the main Activity so that it can call back to it.<br />

Another option in this particular case would be to pass the TextView to the event<br />

handler, but passing the main Activity is a more general solution.


jeudi 26 janvier 12<br />

RÉSULTATS DANS L’<br />

EMULATEUR


jeudi 26 janvier 12<br />

RÉSULTATS SUR UN DEVICE


jeudi 26 janvier 12<br />

UTILISATION D’UNE INNER<br />

CLASSE NOMMÉE


IDÉE<br />

• Buts<br />

• Changer la couleurs d’un TextView lorsqu’un Button ou RadioButton est<br />

pressé. Gestion <strong>de</strong> différentes couleurs en fonction du bouton.<br />

• I<strong>de</strong>m précé<strong>de</strong>nt<br />

• Approche<br />

• Utilisation d’une inner classe qui implémente View.OnClickListener<br />

• Avantages<br />

• Il est possible <strong>de</strong> donner <strong>de</strong>s arguments pour changer le comportement<br />

• La métho<strong>de</strong> du gestionnaire d’événement peut accé<strong>de</strong>r aux données<br />

privées <strong>de</strong> l’Activity. Pas besoin <strong>de</strong> référence pour appeler l’Activity.<br />

• Inconvénients<br />

• La classe Listener est dans le même fichier que l’activity, elles sont plus<br />

liées et ne peuvent pas être changées indépendamment l’une <strong>de</strong> l’autre.<br />

jeudi 26 janvier 12


XML FILES: IDEM PRÉCÉDENT<br />

• res/layout/main.xml<br />

• Définit un LinearLayout vertical qui contient 3 Buttons, un<br />

RadioGroup horizontal (avec 3 RadioButtons), et un<br />

TextView.<br />

• Les Buttons, RadioButtons, et TextView ont le même<br />

i<strong>de</strong>ntifiant auxquels ont peut faire référence dans le co<strong>de</strong><br />

Java<br />

• res/values/strings.xml<br />

jeudi 26 janvier 12<br />

• Définit le nom <strong>de</strong> l’application et les labels <strong>de</strong>s Buttons et<br />

RadioButtons


jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

public class Events2Example extends Activity {<br />

private View mColorRegion;<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

Button b1 = (Button)findViewById(R.id.button1);<br />

Button b2 = (Button)findViewById(R.id.button2);<br />

Button b3 = (Button)findViewById(R.id.button3);<br />

RadioButton r1 =<br />

(RadioButton)findViewById(R.id.radio_button1);<br />

RadioButton r2 =<br />

(RadioButton)findViewById(R.id.radio_button2);<br />

RadioButton r3 =<br />

(RadioButton)findViewById(R.id.radio_button3);<br />

Except for the class name, this top<br />

part of the Activity is exactly the same<br />

as the previous example.


}<br />

jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

b1.setOnClickListener(new ColorSetter(Color.RED, this));<br />

b2.setOnClickListener(new ColorSetter(Color.BLUE, this));<br />

b3.setOnClickListener(new ColorSetter(Color.YELLOW, this));<br />

r1.setOnClickListener(new ColorSetter(Color.RED, this));<br />

r2.setOnClickListener(new ColorSetter(Color.BLUE, this));<br />

r3.setOnClickListener(new ColorSetter(Color.YELLOW, this));<br />

private void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

}<br />

Since this method will only be called<br />

by method in inner event handler<br />

class, it is allowed to be private.<br />

Note no closing brace. This class is not<br />

finished yet (continued on next sli<strong>de</strong>)<br />

Assigns an inner class as the event handler for each<br />

of the Buttons and RadioButtons.<br />

As with the previous example, you can pass<br />

arguments to the event handler (the colors) so that<br />

the same event handler class can have different<br />

behaviors for different controls.<br />

However, since the event handler is in the same<br />

class, you do not have to supply a reference to the<br />

main Activity class.


EVENT HANDLER CLASS<br />

(PARTIE DE MAIN ACTIVITY CLASS)<br />

}<br />

}<br />

jeudi 26 janvier 12<br />

private class ColorSetter implements OnClickListener {<br />

private int regionColor;<br />

public ColorSetter(int regionColor) {<br />

this.regionColor = regionColor;<br />

}<br />

@Overri<strong>de</strong><br />

public void onClick(View v) {<br />

setRegionColor(regionColor);<br />

}<br />

Closes off the main Activity class.<br />

Event handler can directly call methods in the main Activity,<br />

even if the method is private.


RÉSULTATS SUR L’ EMULATEUR<br />

jeudi 26 janvier 12<br />

Same as previous example.


jeudi 26 janvier 12<br />

RÉSULTAT SUR UN DEVICE<br />

Same as previous example.


jeudi 26 janvier 12<br />

UTILISATION D’UNE INNER<br />

CLASSE ANONYME POUR LA<br />

GESTION DES ÉVÉNEMENTS


CONCEPT<br />

• Buts<br />

• Changer la couleur aléatoirement du TextView lorsque le Button est préssé.<br />

• Approche<br />

• Utilisation d’une inner class anonyme qui implémente le Listener<br />

• Avantages<br />

• Si l’on part du principe que l’on a une classe par contrôle, on a les mêmes<br />

avantages qu’une inner classe nommée, mais en plus concis.<br />

• Approche que l’on retrouve dans Swing, SWT, AWT, and GWT.<br />

• Inconvénients<br />

• Si l’on applique le handler à plus d’un control, il faudra faire du copié/collé du co<strong>de</strong><br />

que handler.<br />

• Ce type d’approche doit s’appliquer seulement pour un contrôle unique<br />

• Si le co<strong>de</strong> pour les handler est long, cela rend le co<strong>de</strong> plus difficile à lire en l’inlinant.<br />

• Approche utilisée seulement lorsque le co<strong>de</strong> du handler est court<br />

jeudi 26 janvier 12


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12


RES/VALUES/STRINGS.XML<br />

<br />

<br />

Event Handling Example<br />

Random Color<br />

<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

ACTIVITY CLASS 1:<br />

INNER CLASS NOMMÉE<br />

public class Events3Example extends Activity {<br />

private View mColorRegion;<br />

private int[] mColorChoices =<br />

{ Color.BLACK, Color.BLUE, ...};<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

Button colorButton =<br />

(Button)findViewById(R.id.color_button);<br />

colorButton.setOnClickListener(new ColorRandomizer());<br />

}<br />

private void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

}<br />

There is nothing wrong with this approach.<br />

However, this event handler class is only<br />

used on this line of co<strong>de</strong>. Furthermore, the<br />

co<strong>de</strong> for ColorRandomizer (next page) is<br />

relatively short. So, you can make it a bit<br />

more concise with an anonymous inner class.


}<br />

}<br />

jeudi 26 janvier 12<br />

ACTIVITY CLASS 1:<br />

INNER CLASS NOMMÉE<br />

private class ColorRandomizer<br />

implements OnClickListener {<br />

@Overri<strong>de</strong><br />

public void onClick(View v) {<br />

Random generator = new Random();<br />

int in<strong>de</strong>x = generator.nextInt(mColorChoices.length);<br />

setRegionColor(mColorChoices[in<strong>de</strong>x]);<br />

}


jeudi 26 janvier 12<br />

ACTIVITY CLASS 1:<br />

INNER CLASS ANONYME<br />

public class Events3Example extends Activity {<br />

private View mColorRegion;<br />

private int[] mColorChoices =<br />

{ Color.BLACK, Color.BLUE, ...};<br />

private void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

}<br />

See next page for onCreate


jeudi 26 janvier 12<br />

ACTIVITY CLASS 1:<br />

INNER CLASS ANONYME<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

Button colorButton =<br />

(Button)findViewById(R.id.color_button);<br />

colorButton.setOnClickListener(new OnClickListener() {<br />

@Overri<strong>de</strong><br />

public void onClick(View v) {<br />

Random generator = new Random();<br />

int in<strong>de</strong>x = generator.nextInt(mColorChoices.length);<br />

setRegionColor(mColorChoices[in<strong>de</strong>x]);<br />

}<br />

});<br />

} This <strong>de</strong>fines the class and instantiates it all in one fell swoop. If you have never seen anonymous inner<br />

classes before, the confusion is probably not worth the co<strong>de</strong> savings over a named inner class.<br />

However, once you are used to it, it is more concise and arguably easier to un<strong>de</strong>rstand because the<br />

behavior is shown where it is used. This approach is very commonly used by Swing, SWT, AWT, and<br />

GWT programmers. This is also very analogous to anonymous functions (closures) that are wi<strong>de</strong>ly<br />

used in functional programming languages.


RÉSULTATS SUR L’EMULATEUR<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

RÉSULTATS SUR UN DEVICE


jeudi 26 janvier 12<br />

GESTION DES ÉVÉNEMENTS AVEC<br />

L’ ACTIVITY QUI IMPLÉMENTE<br />

L’INTERFACE LISTENER


CONCEPT<br />

• Buts<br />

• Changer la couleur aléatoirement du TextView lorsque le Button est pressé<br />

• Approche<br />

• Avoir l’ Activity qui implémente l’interface Listener. Placer la métho<strong>de</strong> handler dans l’ Activity.<br />

Appeler setOnClickListener(this).<br />

• Avantages<br />

• Si l’app a un seul contrôle sur ce type <strong>de</strong> Listener, alors c’est la façon la plus simple et la plus<br />

rapi<strong>de</strong> <strong>de</strong> toutes les approches.<br />

• Inconvénients<br />

• Ne passe pas à l’échelle avec <strong>de</strong>s contrôles multiples sauf si l’on a <strong>de</strong>s comportements i<strong>de</strong>ntiques.<br />

• Si l’on assigne “this” comme handler pour plus d’un contrôle du même type Listener, alors la métho<strong>de</strong> onClick (ou<br />

autre) <strong>de</strong>viendra complexe pour déterminer quel contrôle a été clické<br />

• Cette métho<strong>de</strong> est a réserver pour <strong>de</strong>s apps qui ont un seul contrôle <strong>de</strong> ce type <strong>de</strong> Listener<br />

• Il n’est pas possible <strong>de</strong> passer <strong>de</strong>s arguments au Listener<br />

• Donc, fonctionne difficilement pour <strong>de</strong>s contrôles multiples<br />

jeudi 26 janvier 12


• res/layout/main.xml<br />

XML FILES:<br />

IDENTIQUE<br />

• Définit un LinearLayout vertical contenant un Button et un<br />

TextView.<br />

• Le Button et le TextView ont <strong>de</strong>s ids qui pourront être<br />

utilisés pour y faire référence dans le co<strong>de</strong> Java<br />

• res/values/strings.xml<br />

jeudi 26 janvier 12<br />

• Définit le nom <strong>de</strong> l’application et le label du Button


jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

public class Events5Example extends Activity<br />

implements OnClickListener {<br />

private View mColorRegion;<br />

private int[] mColorChoices =<br />

{ Color.BLACK, Color.BLUE, ... };<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

Button colorButton =<br />

(Button)findViewById(R.id.color_button);<br />

colorButton.setOnClickListener(this);<br />

}


}<br />

}<br />

jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

private void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

@Overri<strong>de</strong><br />

public void onClick(View v) {<br />

Random generator = new Random();<br />

int in<strong>de</strong>x = generator.nextInt(mColorChoices.length);<br />

setRegionColor(mColorChoices[in<strong>de</strong>x]);<br />

}


jeudi 26 janvier 12<br />

RÉSULTAT SUR L’ÉMULATEUR<br />

Same as previous example.


jeudi 26 janvier 12<br />

RÉSULTAT SUR LE DEVICE<br />

Same as<br />

previous<br />

example.


jeudi 26 janvier 12<br />

GESTION DES ÉVÉNEMENTS<br />

EN INDIQUANT LA<br />

MÉTHODE DANS LE<br />

MAIN.XML


CONCEPTS<br />

• Buts<br />

• Changer la couleur aléatoirement du TextView lorsque le Button est pressé.<br />

• Approche<br />

• Placer la métho<strong>de</strong> dans l’ Activity. Ne pas implémenter d’interface Listener ou appeler<br />

setOnClickListener. Avoir un fichier layout (main.xml) qui spécifie la métho<strong>de</strong> handler via<br />

l’attribut android:onClick<br />

• Avantages<br />

• Part du principe que l’app a un seul contrôle <strong>de</strong> ce Listener type. Avantages (co<strong>de</strong> simple/court)<br />

i<strong>de</strong>ntique à l’approche précé<strong>de</strong>nte.<br />

• Plus consistant avec la stratégie “do layout in XML”<br />

• Il est possible <strong>de</strong> fournir plusieurs nom <strong>de</strong> métho<strong>de</strong>s pour différents contrôles.<br />

• Inconvénients<br />

• Il n’est toujours pas possible <strong>de</strong> passer <strong>de</strong>s arguments au Listener.<br />

• Moins clair pour le développeur Java pour qui la métho<strong>de</strong> est le handler du contrôle<br />

jeudi 26 janvier 12


RES/LAYOUT/MAIN.XML<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

This is the name of the event handler<br />

method in the main class. This method<br />

must have a void return type and take a<br />

View as an argument. However, the<br />

method name is arbitrary, and the main<br />

class need not implement any particular<br />

interface.


RES/VALUES/STRINGS.XML<br />

<br />

<br />

Event Handling Example<br />

Random Color<br />

<br />

jeudi 26 janvier 12<br />

Unchanged from the previous two examples


jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

public class Events6Example extends Activity {<br />

private View mColorRegion;<br />

private int[] mColorChoices =<br />

{ Color.BLACK, Color.BLUE, ... };<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mColorRegion = findViewById(R.id.color_region);<br />

// No need to look up the button or assign event handler<br />

}


}<br />

}<br />

jeudi 26 janvier 12<br />

MAIN ACTIVITY CLASS<br />

private void setRegionColor(int color) {<br />

mColorRegion.setBackgroundColor(color);<br />

public void randomizeColor(View v) {<br />

Random generator = new Random();<br />

int in<strong>de</strong>x = generator.nextInt(mColorChoices.length);<br />

setRegionColor(mColorChoices[in<strong>de</strong>x]);<br />

}<br />

Matches method name given for<br />

android:onClick in main.xml


jeudi 26 janvier 12<br />

RÉSULTAT SUR L’ÉMULATEUR<br />

Same as previous example.


jeudi 26 janvier 12<br />

RÉSULTAT SUR LE DEVICE<br />

Same as<br />

previous<br />

example.


jeudi 26 janvier 12<br />

COPIE D’UN PROJET<br />

ANDROID SOUS ECLIPSE


ETAPES<br />

• Problème<br />

• Les projets dans ce tutoriel sont très proches les uns <strong>de</strong>s autres.<br />

• Vous voulez copié/renomé vos précé<strong>de</strong>nts projets au lieu <strong>de</strong> créer <strong>de</strong> nouveau projet et <strong>de</strong><br />

copié chaque partie <strong>de</strong> façon séparée<br />

• Mais, le noms <strong>de</strong>s paquets sur le <strong>de</strong>vice doit être unique<br />

• Le renommage <strong>de</strong>s paquets nécessite quelques précautions. Pas <strong>de</strong> vraie support dans Eclipse.<br />

• Etapes (l’ordre est important !)<br />

1. click-D sur le vieux projet. click-D et choississez Paste. New name.<br />

2. click-D nouveau projet, Android Tools � Rename Application Package. New<br />

name. Déselectionnez la classes Java, et laissez la sélection seulement pour le<br />

manifest. OK lorsque l’on vous <strong>de</strong>man<strong>de</strong> <strong>de</strong> mettre à jour la configuration.<br />

3. click-D src/projectName dans le nouveau projet. Refactor � Rename. OK<br />

lorsque l’on informe que le paquet existe.<br />

4. Optionnel : click-D dans l’Activity. Refactor � Rename.<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

CONCLUSION


APPROCHES: CONTRÔLES<br />

SIMPLES OU MULTIPLES<br />

• Situation<br />

• Le même co<strong>de</strong> <strong>de</strong> gestionnaire doit être appliqué à plusieurs contrôles<br />

• Options<br />

• Utiliser une classe gestionnaire d’événement séparée<br />

• Pros: possibilité <strong>de</strong> passer <strong>de</strong>s args au gestionnaire afin <strong>de</strong> customiser son<br />

comportement; plus facile à changer indépendamment <strong>de</strong> l’app principale<br />

• Cons: Si le gestionnaire appel du co<strong>de</strong> <strong>de</strong> l’ Activity, il faut utiliser “this” et rendre la<br />

métho<strong>de</strong> public<br />

• Utiliser une inner classe nommée<br />

• Pros: possibilité <strong>de</strong> passer <strong>de</strong>s arps au gestionnaire afin <strong>de</strong> customiser son<br />

comportement; pas besoins <strong>de</strong> “this” reference, la métho<strong>de</strong> peut être privée<br />

• C’est <strong>de</strong> mon point <strong>de</strong> vue la métho<strong>de</strong> la plus facile pour la gestion <strong>de</strong>s événement<br />

<strong>de</strong> type Widget<br />

• Cons: le gestionnaire est lié à l’Activity<br />

jeudi 26 janvier 12


APPROCHES: CONTRÔLE<br />

SIMPLE<br />

• Situation<br />

• Le co<strong>de</strong> du gestionnaire doit être appliqué à un seul contrôle<br />

• Options<br />

• Utilisation d’une inner classe anonyme<br />

• Pros: i<strong>de</strong>ntique à l’inner class nommée, et plus concise<br />

• Cons: + difficile pour les novices ou si le co<strong>de</strong> du handler est long<br />

• Mettre le handler dans l’ Activity, implémenter l’interface et appeler<br />

setOnClickListener(this)<br />

• Pros: co<strong>de</strong> simple<br />

• Cons: impossibilité <strong>de</strong> passer <strong>de</strong>s arguments au handler<br />

• Mettre le handler dans l’ Activity, pas d’interface, spécifier la métho<strong>de</strong> avec<br />

android:onClick dans le main.xml<br />

• Pros: 1 métho<strong>de</strong> par contrôle, mais différentes métho<strong>de</strong>s pour chaque contrôle.. Plus orientée<br />

XML, moins <strong>de</strong> co<strong>de</strong> Java<br />

• Cons: plus difficile pour les développeurs Java<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

BOUTON ET WIDGET<br />

CLICABLE<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


• Buttons<br />

RÉSUMÉ DU COURS<br />

• ImageButtons chacune avec un image unique<br />

• ImageButtons chacune avec 3 (normal/focused/pressée)<br />

images<br />

• RadioButtons avec OnClickListener sur chaque<br />

• RadioButtons avec OnCheckedChangeListener sur un<br />

RadioGroup<br />

• CheckBoxes<br />

• ToggleButtons<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

APPROCHE GÉNÉRALE<br />

POUR LES WIDGET


WIDGET LECTURES COMBINED<br />

IN SINGLE PROJECT<br />

• Main screen<br />

• Lets user choose screens on various Widget topics<br />

• Other screens<br />

• Correspond to separate lectures.<br />

• One screen for lecture on Buttons, another for lecture on Spinners, another for<br />

number input, etc.<br />

• Separate layout files<br />

• main.xml, buttons.xml, spinners.xml, etc. See next sli<strong>de</strong>.<br />

• Separate Java classes<br />

• WidgetActivity.java, ButtonActivity.java, SpinnerActivity.java, etc.<br />

• Shared strings file<br />

• strings.xml has separate sections for each lecture, but same file<br />

jeudi 26 janvier 12


LAYOUT FILES FOR WIDGET<br />

LECTURES<br />

• Separate layout files for each Activity<br />

• res/layout/main.xml<br />

• Gives layout for main screen. Loa<strong>de</strong>d with setContentView(R.layout.main);<br />

• res/layout/buttons.xml<br />

• Gives layout for screen on Button and related Widgets. Loa<strong>de</strong>d with<br />

setContentView(R.layout.buttons);<br />

• res/layout/spinners.xml<br />

• Gives layout for screen on Spinners (i.e., combo boxes). Loa<strong>de</strong>d with<br />

setContentView(R.layout.spinners);<br />

• Two common layout attributes<br />

• android:layout_width, android:layout_height<br />

• match_parent (fill up space in enclosing View)<br />

• wrap_content (use natural size)<br />

jeudi 26 janvier 12


SWITCHING ACTIVITIES:<br />

SUMMARY<br />

• Switches Activities with Intents<br />

• Main screen has buttons to navigate to other Activities<br />

• Return to original screen with phone’s “back” button<br />

• Syntax required to start new Activity<br />

• Java<br />

• Intent newActivity = new Intent(this, NewActivity.class);<br />

• startActivity(newActivity);<br />

• XML<br />

• Requires entry in AndroidManifest.xml (which is part of downloadable Eclipse<br />

project for Widgets)<br />

• More <strong>de</strong>tails<br />

• Co<strong>de</strong> and some information given in Spinner lecture<br />

• Even more information given in later lecture on Intents<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

OVERALL WIDGET PROJECT<br />

LAYOUT<br />

Java co<strong>de</strong><br />

Images and XML files that refer to sets of images. The<br />

layout files will refer to these images via @drawable/<br />

base_file_name (e.g., @drawable/gps). The first<br />

ImageButton example will use an image file, and the<br />

second ImageButton example will use an XML file<br />

containing references to image files.<br />

Layout files. The Java co<strong>de</strong> will refer to the overall layouts via<br />

R.layout.base_file_name (R.layout.main, R.layout.buttons, etc.). The<br />

Java co<strong>de</strong> will refer to specific GUI elements with<br />

findViewById(R.id.element_id).<br />

Strings. The Java co<strong>de</strong> will refer to these via<br />

getString(R.string.string_name). The layout files will refer to these with<br />

@string/string_name. You can also <strong>de</strong>fine arrays of strings here, or put the<br />

arrays in a separate file typically called arrays.xml. Arrays are used in the<br />

next lecture on Spinners.<br />

In or<strong>de</strong>r for one Activity to start another Activity in the same project, you need some<br />

entries in here. See Spinner lecture.


jeudi 26 janvier 12<br />

APPROACH FOR<br />

BUTTON-RELATED EXAMPLES


jeudi 26 janvier 12<br />

SUMMARY OF LAYOUT<br />

Horizontal LinearLayout (with 3 Buttons)<br />

Horizontal LinearLayout (with 3 ImageButtons)<br />

Horizontal LinearLayout (with 3 ImageButtons)<br />

Horizontal RadioGroup<br />

(with 3 RadioButtons)<br />

Horizontal RadioGroup<br />

(with 3 RadioButtons)<br />

Horizontal LinearLayout (with 3 CheckBoxes)<br />

Vertical<br />

LinearLayou<br />

Horizontal LinearLayout (with 3 ToggleButtons)<br />

An upcoming tutorial section gives <strong>de</strong>tails on using layouts. However, you can do a pretty<br />

lot now by knowing just two simple things:<br />

1) You can make some pretty complex layouts by nesting horizontal and vertical layouts<br />

insi<strong>de</strong> each other.<br />

2) You can experiment interactively with the visual layout editor in Eclipse. Edit layout file<br />

and click on Graphical Layout.<br />

t


XML: LAYOUT FILE<br />

(RES/LAYOUT/BUTTONS.XML)<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

One entry for each row in previous sli<strong>de</strong>.<br />

These entries are shown in upcoming sli<strong>de</strong>s.


XML: STRINGS FILE<br />

(RES/VALUES/STRINGS.XML)<br />

<br />

<br />

jeudi 26 janvier 12<br />

<br />

...<br />

...<br />

...<br />

<br />

<br />

<br />


JAVA (BUTTONACTIVITY.JAVA)<br />

public class ButtonActivity extends Activity {<br />

...<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.buttons);<br />

...<br />

}<br />

private void showToast(String text) {<br />

Toast.makeText(this, text, Toast.LENGTH_LONG).show();<br />

}


jeudi 26 janvier 12<br />

BUTTON


BUTTON<br />

• I<strong>de</strong>a<br />

• A push button displaying text<br />

• Main Listener type<br />

• View.OnClickListener<br />

• If you specify the handler method in the XML file, you never explicitly refer to this<br />

Listener class.<br />

• Key XML attributes<br />

• android:text<br />

• The label of the button. Can also be manipulated in Java with setText and getText<br />

• android:onClick<br />

• The event handler method. As shown in event-handling lecture, you can also use<br />

android:id and then have Java co<strong>de</strong> programmatically assign event handler.<br />

jeudi 26 janvier 12


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

Hi!<br />

Bye!<br />

Yo!<br />

<br />

You clicked the \'%s\' Widget.<br />

<br />

These are the labels referred to in<br />

previous sli<strong>de</strong><br />

The event handler method will use<br />

String.format and this template to<br />

produce a message that will be<br />

shown in a Toast (short-lived<br />

popup message) when a Button is<br />

clicked.


JAVA (RELEVANT PARTS)<br />

public class ButtonActivity extends Activity {<br />

private String mButtonMessageTemplate;<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.buttons);<br />

mButtonMessageTemplate =<br />

getString(R.string.button_message_template);<br />

}<br />

public void showButtonText(View clickedButton) {<br />

Button button = (Button)clickedButton;<br />

CharSequence text = button.getText();<br />

String message =<br />

String.format(mButtonMessageTemplate, text);<br />

showToast(message);<br />

}<br />

This is the method specified for<br />

each Button via the<br />

android:onClick attribute in the<br />

layout file.


jeudi 26 janvier 12<br />

Emulator<br />

RESULTS<br />

Phone


jeudi 26 janvier 12<br />

IMAGEBUTTON<br />

(EACH WITH SINGLE IMAGE)


IMAGEBUTTON, VARIATION 1<br />

• I<strong>de</strong>a<br />

• A push button displaying an image<br />

• Main Listener type<br />

• View.OnClickListener<br />

• Key XML attributes<br />

• android:src<br />

jeudi 26 janvier 12<br />

If you just want to display an<br />

image, but not take action when it<br />

is clicked, see the ImageView<br />

class.<br />

• The image for the button. Refers to the base name (minus the extension) of an image file<br />

in the res/drawable fol<strong>de</strong>r<br />

• Supported formats are png, jpeg, gif, and bmp.<br />

You can also refer to a drawable XML file as in next example.<br />

• The localization lecture will talk about drawable-xdpi fol<strong>de</strong>rs<br />

• Can also be set in Java with setImageDrawable<br />

• android:onClick<br />

• The event handler method


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

Refers to res/drawable/<br />

android_platform.png<br />

Refers to res/drawable/<br />

camera_phone.png<br />

Refers to res/drawable/gps.png


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

<br />

You clicked the ImageButton that displays %s.<br />

<br />

<br />

the android_platform.png image<br />

<br />

<br />

the camera_phone.png image<br />

<br />

<br />

the gps.png image<br />

<br />

The event handler method will use<br />

String.format, this template, and<br />

the <strong>de</strong>scriptions below to produce<br />

a message that will be shown in a<br />

Toast when an ImageButton is<br />

clicked.


JAVA (RELEVANT PARTS)<br />

public class ButtonActivity extends Activity {<br />

private String mImageButtonMessageTemplate;<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

...<br />

mImageButtonMessageTemplate =<br />

getString(R.string.image_button_message_template);<br />

}<br />

public void showImageButton1Info(View clickedImageButton) {<br />

showImageButtonInfo(R.string.image_button_1_image);<br />

}<br />

...<br />

private void showImageButtonInfo(int imageId) {<br />

String image = getString(imageId);<br />

String message =<br />

String.format(mImageButtonMessageTemplate, image);<br />

showToast(message);<br />

}<br />

This is the method specified for the first<br />

ImageButton via the android:onClick attribute in<br />

the layout file. Methods for the other<br />

ImageButtons are similar.


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

IMAGEBUTTON<br />

(EACH WITH 3 IMAGES)


IMAGEBUTTON, VARIATION 2<br />

• I<strong>de</strong>a<br />

• A push button displaying one of three images, <strong>de</strong>pending upon the situation<br />

• Main Listener type<br />

• View.OnClickListener<br />

• Key XML attributes<br />

• android:src<br />

• The image <strong>de</strong>scriptor file for the button. Refers to the base name (minus<br />

the .xml extension) of an XML file in the res/drawable fol<strong>de</strong>r<br />

• The file, in turn, refers to three regular images in drawable fol<strong>de</strong>r<br />

• Can also be set in Java with setImageDrawable<br />

• android:onClick<br />

• The event handler method<br />

jeudi 26 janvier 12


INDIVIDUAL IMAGE FILES<br />

VS. XML FILES<br />

• Individual image files<br />

• Android will use the same image for all states of the button (normal, focused,<br />

pressed)<br />

• Android will change the background color when focused or pressed. This affects<br />

the transparent pixels.<br />

To get images for practicing, look in android-sdk-installdir/platform-x/data/res/drawable-xdpi.<br />

Or, do a Google search for free icons. Also, see http://<br />

<strong>de</strong>veloper.android.com/gui<strong>de</strong>/<strong>de</strong>veloping/tools/<br />

draw9patch.html for building your own images.<br />

• XML files<br />

• Android will use a different image for each state of the button (normal, focused,<br />

pressed)<br />

• The different images can have different foreground colors, not just different<br />

backgrounds.<br />

jeudi 26 janvier 12


IMAGE DESCRIPTOR FILE (RES/<br />

DRAWABLE/BUTTON_ANDROID.XML)<br />

<br />

<br />

<br />

<br />

<br />

<br />

jeudi 26 janvier 12<br />

The or<strong>de</strong>r of the three files matters. For more <strong>de</strong>tail, see http://<br />

<strong>de</strong>veloper.android.com/reference/android/widget/ImageButton.html<br />

These are the actual image files<br />

for each of the three possible<br />

states of the ImageButton.


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

Refers to res/drawable/button_android.xml. This,<br />

in turn, refers to three regular image files. Co<strong>de</strong><br />

on previous sli<strong>de</strong>.<br />

Refers to res/drawable/button_dialog.xml. This<br />

in turn, refers to three regular image files.<br />

Refers to res/drawable/button_rating_star.xml.<br />

This, in turn, refers to three regular image files


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

<br />

You clicked the ImageButton that displays %s.<br />

<br />

<br />

the Drawable <strong>de</strong>fined in button_android.xml<br />

<br />

<br />

the Drawable <strong>de</strong>fined in button_dialog.xml<br />

<br />

<br />

the Drawable <strong>de</strong>fined in button_rating_star.xml<br />

<br />

The event handler method will use<br />

String.format, this template, and the<br />

<strong>de</strong>scriptions below to produce a<br />

message that will be shown in a Toast<br />

when an ImageButton is clicked. This<br />

is just a copy of entry already shown in<br />

previous ImageButton example.


JAVA (RELEVANT PARTS)<br />

public class ButtonActivity extends Activity {<br />

private String mImageButtonMessageTemplate;<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

...<br />

mImageButtonMessageTemplate =<br />

getString(R.string.image_button_message_template);<br />

}<br />

public void showImageButton4Info(View clickedImageButton) {<br />

showImageButtonInfo(R.string.image_button_4_image);<br />

}<br />

...<br />

private void showImageButtonInfo(int imageId) {<br />

String image = getString(imageId);<br />

String message =<br />

String.format(mImageButtonMessageTemplate, image);<br />

showToast(message);<br />

}<br />

This is the method specified for the first of<br />

these 3 ImageButtons via the<br />

android:onClick attribute in the layout file.<br />

Methods for the other ImageButtons are<br />

similar.


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

RADIOBUTTON<br />

(WITH EVENT HANDLER ATTACHED TO<br />

EACH)


RADIOBUTTON<br />

• I<strong>de</strong>a<br />

• A button for choosing a single option among alternatives<br />

• Main Listener types<br />

• View.OnClickListener<br />

• Assign to each RadioButton if you only care about which has been pressed most<br />

recently. But also see upcoming example for Listener attached to the RadioGroup.<br />

• No need to explicitly refer to Listener when using android:onClick<br />

• No Listener at all<br />

• Some apps take no action when RadioButton is clicked, but instead query the<br />

RadioGroup later to find selection<br />

• Key XML attributes<br />

• android:text, android:onClick<br />

• Same as in previous examples.<br />

jeudi 26 janvier 12


RADIOGROUP<br />

• I<strong>de</strong>a<br />

• Similar to LinearLayout, but specifically for organizing RadioButtons.<br />

• Makes the RadioButtons exclusive (checking one causes previous selection<br />

to become unchecked)<br />

• Main Listener types<br />

• RadioGroup. OnCheckedChangeListener<br />

• Assign to RadioGroup if you want to keep track of both current and previous selections<br />

• Key XML attributes<br />

• Mostly same as for LinearLayout<br />

• Use android:id if you want to programmatically set an<br />

OnCheckedChangeListener<br />

• No android:onBlah to set RadioGroup Listener in XML<br />

jeudi 26 janvier 12


FIRST EXAMPLE: EVENT HANDLERS<br />

ATTACHED TO EACH RADIOBUTTON<br />

• I<strong>de</strong>a<br />

• Respond to clicks on each RadioButton by showing Toast<br />

saying which one was pressed.<br />

• Approach<br />

jeudi 26 janvier 12<br />

• Put RadioButtons insi<strong>de</strong> RadioGroup so that they are<br />

mutually exclusive.<br />

• To assign event handlers, use android:onClick for each<br />

RadioButton<br />

• No id for RadioGroup. No Listener for RadioGroup


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

This first example uses click<br />

handlers attached to each<br />

RadioButton.


STRINGS FILE AND JAVA<br />

• Nothing new for this example<br />

jeudi 26 janvier 12<br />

• Strings file<br />

CODE<br />

• Already showed button labels and<br />

button_message_template<br />

• Java co<strong>de</strong><br />

• Already showed makeToast and showButtonText


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

RADIOBUTTON<br />

(WITH EVENT HANDLER<br />

ATTACHED TO RADIOGROUP)


SECOND EXAMPLE: EVENT HANDLER<br />

• I<strong>de</strong>a<br />

ATTACHED TO RADIOGROUP<br />

• Respond to clicks by showing Toast saying which one was<br />

pressed and which one was previously selected.<br />

• Approach<br />

jeudi 26 janvier 12<br />

• Put RadioButtons insi<strong>de</strong> RadioGroup so that they are mutually<br />

exclusive.<br />

• Same as last example<br />

• In XML, give id to RadioGroup.<br />

• In Java, find RadioGroup and call setOnCheckedChangeListener


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

The id is nee<strong>de</strong>d so that Java can get a<br />

reference and programmatically set the<br />

OnCheckedChangeListener.<br />

RadioButtons do not have<br />

android:onClick entries


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

<br />

You selected the \'%s\' RadioButton.<br />

There was no previous selection.<br />

<br />

<br />

You selected the \'%s\' RadioButton.<br />

Previous selection was \'%s\'.<br />

The event handler method will use String.format, one of these templates, the<br />

current selection, and the previous selection to produce a message that will be<br />

shown in a Toast when a RadioButton is clicked.<br />

Use formatted="false" if a string has more than one %s placehol<strong>de</strong>r.


JAVA (RELEVANT PARTS)<br />

public class ButtonActivity extends Activity {<br />

...<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.buttons);<br />

...<br />

RadioGroup radioGroup =<br />

(RadioGroup)findViewById(R.id.radio_group);<br />

radioGroup.setOnCheckedChangeListener(new RadioGroupInfo());<br />

}<br />

Continued on next page.<br />

RadioGroupInfo is an inner class insi<strong>de</strong><br />

ButtonActivity.


JAVA<br />

(RELEVANT PARTS, CONTINUED)<br />

private class RadioGroupInfo implements OnCheckedChangeListener {<br />

private RadioButton mLastChecked;<br />

private String mNewSelectionMessageTemplate;<br />

private String mChangedSelectionMessageTemplate;<br />

jeudi 26 janvier 12<br />

public RadioGroupInfo() {<br />

mNewSelectionMessageTemplate =<br />

getString(R.string.new_selection_message_template);<br />

mChangedSelectionMessageTemplate =<br />

getString(R.string.changed_selection_message_template);<br />

}<br />

Top of the inner class


JAVA<br />

(RELEVANT PARTS, CONTINUED)<br />

}<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCheckedChanged(RadioGroup group, int checkedId) {<br />

RadioButton newChecked =<br />

(RadioButton)findViewById(checkedId);<br />

String message;<br />

if (mLastChecked == null) { // No previous selection<br />

message = String.format(mNewSelectionMessageTemplate,<br />

newChecked.getText());<br />

} else {<br />

message = String.format(mChangedSelectionMessageTemplate,<br />

newChecked.getText(),<br />

mLastChecked.getText());<br />

}<br />

mLastChecked = newChecked;<br />

showToast(message);<br />

}<br />

Bottom of the inner class. Keeps track of current<br />

and previous selections.


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

CHECKBOX


CHECKBOX<br />

• I<strong>de</strong>a<br />

• A button with two states (checked and unchecked)<br />

• Has visual indicator to show whether it is checked<br />

• In Java, use isChecked() to <strong>de</strong>termine state. Use setChecked to<br />

programmatically change the state.<br />

• Same text in both states (unlike ToggleButton)<br />

• Main Listener types<br />

• View.OnClickListener<br />

• No Listener at all<br />

• Take no action when CheckBox is clicked, but instead query the CheckBox<br />

later to find if it is checked or not<br />

• Key XML attributes<br />

• android:text, android:onClick<br />

• Same as in previous examples<br />

jeudi 26 janvier 12


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

Note that the class name is CheckBox, not<br />

Checkbox<br />

(as in AWT).


STRINGS FILE AND JAVA<br />

• Nothing new for this example<br />

jeudi 26 janvier 12<br />

• Strings file<br />

CODE<br />

• Already showed button labels and<br />

button_message_template<br />

• Java co<strong>de</strong><br />

• Already showed makeToast and showButtonText


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

TOGGLEBUTTON


TOGGLEBUTTON<br />

• I<strong>de</strong>a<br />

• A button with two states (checked and unchecked)<br />

• Has visual indicator to show whether it is checked<br />

• In Java, use isChecked() to <strong>de</strong>termine state. Use setChecked to programmatically change the state.<br />

• Has different text for each state (unlike CheckBox)<br />

• Main Listener types<br />

• View.OnClickListener<br />

• No Listener at all<br />

• Take no action when ToggleButton is clicked, but instead query the ToggleButton later to find if it is<br />

checked or not<br />

• Key XML attributes<br />

• android:textOn, android:textOff<br />

• The text for the two states. If you omit this, then the text is automatically ON and OFF (in caps)<br />

• android:onClick<br />

• Same as in previous examples<br />

jeudi 26 janvier 12


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/BUTTONS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />

<br />

No textOn or textOff attributes, so the<br />

<strong>de</strong>faults of ON and OFF will be used.


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

Use SSL<br />

No SSL<br />

GPS On<br />

GPS Off<br />

<br />

You turned the ToggleButton %s.<br />

Label is now \'%s\'.<br />

<br />

The event handler method will use<br />

String.format, this template, the<br />

state of the ToggleButton (on or<br />

off), and the text to produce a<br />

message that will be shown in a<br />

Toast when a ToggleButton is<br />

clicked.


JAVA (RELEVANT PARTS)<br />

public class ButtonActivity extends Activity {<br />

private String mToggleButtonMessageTemplate;<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

...<br />

mToggleButtonMessageTemplate =<br />

getString(R.string.toggle_button_message_template);<br />

}


JAVA<br />

(RELEVANT PARTS, CONTINUED)<br />

This is the method specified for the<br />

jeudi 26 janvier 12<br />

public void showToggleButtonInfo(View clickedToggleButton) {<br />

ToggleButton toggleButton =<br />

(ToggleButton)clickedToggleButton;<br />

String status;<br />

if (toggleButton.isChecked()) {<br />

status = "ON";<br />

} else {<br />

status = "OFF";<br />

}<br />

CharSequence label = toggleButton.getText();<br />

String message =<br />

String.format(mToggleButtonMessageTemplate,<br />

status, label);<br />

showToast(message);<br />

}<br />

ToggleButtons via the android:onClick attribute in<br />

the layout file.


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

WRAP-UP


SUMMARY<br />

• Click handling is consistent among buttons<br />

• Button, ImageButton, RadioButton, CheckBox, ToggleButton<br />

• Can specify event handler method with android:onClick<br />

• Or can set programmatically as in events lecture<br />

• ImageButton<br />

• Can have single image or set of three.<br />

• Specify with android:src<br />

• Images and image XML files go in res/drawable fol<strong>de</strong>r<br />

• RadioGroup<br />

• Surrounds RadioButtons. Can have its own Listener if you need to track previous<br />

selection.<br />

• ToggleButton<br />

• Similar behavior to CheckBox. But has android:textOn and android:textOff instead of a<br />

fixed label.<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

WIDGETS: SPINNERS<br />

(COMBO BOXES)<br />

<strong>David</strong> <strong>Defour</strong><br />

<strong>Université</strong> <strong>de</strong> <strong>Perpignan</strong><br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/


TOPICS IN THIS SECTION<br />

• Switching from one Activity to another<br />

• Spinners with choices set in XML<br />

• Spinners with choices set in Java<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

GENERAL APPROACH<br />

FOR WIDGET EXAMPLES


WIDGET LECTURES COMBINED<br />

IN SINGLE PROJECT<br />

• Main screen<br />

• Lets user choose screens on various Widget topics<br />

• Other screens<br />

• Correspond to separate lectures.<br />

• One screen for lecture on Buttons, another for lecture on Spinners, another for<br />

number input, etc.<br />

• Separate layout files<br />

• main.xml, buttons.xml, spinners.xml, etc. See next sli<strong>de</strong>.<br />

• Separate Java classes<br />

• WidgetActivity.java, ButtonActivity.java, SpinnerActivity.java, etc.<br />

• Shared strings file<br />

• strings.xml has separate sections for each lecture, but same file<br />

jeudi 26 janvier 12


LAYOUT FILES FOR WIDGET<br />

LECTURES<br />

• Separate layout files for each Activity<br />

• res/layout/main.xml<br />

• Gives layout for main screen. Loa<strong>de</strong>d with setContentView(R.layout.main);<br />

• res/layout/buttons.xml<br />

• Gives layout for screen on Button and related Widgets. Loa<strong>de</strong>d with<br />

setContentView(R.layout.buttons);<br />

• res/layout/spinners.xml<br />

• Gives layout for screen on Spinners (i.e., combo boxes). Loa<strong>de</strong>d with<br />

setContentView(R.layout.spinners);<br />

• Two common layout attributes<br />

• android:layout_width, android:layout_height<br />

• match_parent (fill up space in enclosing View)<br />

• wrap_content (use natural size)<br />

jeudi 26 janvier 12


STRINGS FILE FOR WIDGET LECTURES<br />

(RES/VALUES/STRINGS.XML)<br />

<br />

<br />

<br />

...<br />

...<br />

...<br />

<br />

<br />

<br />

<br />

...<br />

<br />

jeudi 26 janvier 12


SWITCHING ACTIVITIES:<br />

SUMMARY<br />

• Switches Activities with Intents<br />

• Main screen has buttons to navigate to other Activities<br />

• Return to original screen with phone’s “back” button<br />

• Syntax required to start new Activity<br />

• Java<br />

• Intent newActivity = new Intent(this, NewActivity.class);<br />

• startActivity(newActivity);<br />

• XML<br />

• Requires entry in AndroidManifest.xml (which is part of downloadable Eclipse<br />

project for Widgets)<br />

• More <strong>de</strong>tails<br />

• Co<strong>de</strong> shown on next few sli<strong>de</strong>s<br />

• Even more information given in later lecture on Intents<br />

jeudi 26 janvier 12


SWITCHING ACTIVITIES:<br />

DETAILS<br />

• Java (InitialActivity.java)<br />

Intent newActivity = new Intent(this, NewActivity.class);<br />

startActivity(newActivity);<br />

• XML (AndroidManifest.xml)<br />

<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

<br />


SWITCHING ACTIVITIES:<br />

WIDGETSINITIALACTIVITY.JAVA<br />

public class WidgetsInitialActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

}<br />

private void goToActivity<br />

(Class


SWITCHING ACTIVITIES:<br />

ANDROIDMANIFEST.XML<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Most parts of this file were created automatically when the Android<br />

project was ma<strong>de</strong> in Eclipse. To switch Activities yourself, cut and paste<br />

this co<strong>de</strong> from the downloadable source, and change only android:name<br />

and android:label.<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

OVERALL WIDGET PROJECT<br />

LAYOUT<br />

Java co<strong>de</strong><br />

Images and XML files that refer to sets of images. The<br />

layout files will refer to these images via @drawable/<br />

base_file_name (e.g., @drawable/gps). See ImageButton<br />

examples in lecture on buttons.<br />

Layout files. The Java co<strong>de</strong> will refer to the overall layouts via<br />

R.layout.base_file_name (R.layout.main, R.layout.spinners, etc.). The<br />

Java co<strong>de</strong> will refer to specific GUI elements with<br />

findViewById(R.id.element_id).<br />

Strings. The Java co<strong>de</strong> will refer to these via<br />

getString(R.string.string_name). The layout files will refer to these with<br />

@string/string_name. You can also <strong>de</strong>fine arrays of strings here, or put the<br />

arrays in a separate file typically called arrays.xml. Arrays <strong>de</strong>fined here are<br />

used in the first Spinner example.<br />

In or<strong>de</strong>r for one Activity to start another Activity in the same project, you need some<br />

entries in here. See upcoming sli<strong>de</strong>.


jeudi 26 janvier 12<br />

SPINNER APPROACH 1:<br />

CHOICES SPECIFIED IN XML


SPINNER WITH PREDEFINED<br />

• I<strong>de</strong>a<br />

CHOICES<br />

• A combo box (drop down list of choices)<br />

• Similar purpose to a RadioGroup: to let the user choose<br />

among a fixed set of options<br />

• Main Listener types<br />

jeudi 26 janvier 12<br />

• AdapterView.OnItemSelectedListener<br />

• AdapterView.OnItemClickedListener<br />

• The first is more general purpose, since it will be invoked on<br />

programmatic changes and keyboard events as well as clicks.


SPINNER (CONTINUED)<br />

• Key XML attributes<br />

• android:id<br />

• You need a Java reference to assign an event handler<br />

• android:prompt<br />

• The text shown at the top of Spinner when user clicks to open it.<br />

• Since text is not shown when the Spinner is closed, the string used for the prompt is typically also displayed in a<br />

TextView above the Spinner.<br />

• android:entries<br />

• An XML entry <strong>de</strong>fining an array of choices.<br />

Can be in strings.xml or a separate file (e.g., arrays.xml)<br />

<br />

choice 1<br />

choice 2<br />

…<br />

<br />

jeudi 26 janvier 12


ONITEMSELECTEDLISTENER<br />

• onItemSelected<br />

• Invoked when the an entry is selected. Invoked once when Spinner is first<br />

displayed, then again for each time the user selects something.<br />

• Arguments<br />

• AdapterView: the Spinner itself<br />

• View: the row of the Spinner that was selected<br />

• int: the in<strong>de</strong>x of the selection. Pass this to the Spinner’s getItemAtPosition<br />

method to get the text of the selection.<br />

• long: The row id of the selected item<br />

• onNothingSelected<br />

• Invoked when there is now nothing displayed. This cannot happen due to<br />

normal user interaction, but only when you programmatically remove an entry.<br />

jeudi 26 janvier 12


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/SPINNERS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

Same text used twice, since<br />

the text is hid<strong>de</strong>n when the<br />

Spinner is closed.<br />

An array of entries. If you have<br />

lots of arrays, you typically put<br />

them in arrays.xml. However,<br />

here, it makes more sense to<br />

keep the array of entries in<br />

strings.xml with the spinner<br />

prompt and the spinner<br />

message template.


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

<br />

Current Android Vendors (Choices from XML)<br />

<br />

<br />

Acer<br />

Dell<br />

HTC<br />

Huawei<br />

Kyocera<br />

LG<br />

Motorola<br />

Nexus<br />

Samsung<br />

Sony Ericsson<br />

T-Mobile<br />

Neptune<br />

<br />

<br />

You selected \'%s\'.<br />

<br />

The event handler method will use<br />

String.format, this template, and<br />

the current selection to produce a<br />

message that will be shown in a<br />

Toast when a Spinner selection is<br />

ma<strong>de</strong>.


JAVA (RELEVANT PARTS)<br />

public class SpinnerActivity extends Activity {<br />

private String mItemSelectedMessageTemplate;<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.spinners);<br />

mItemSelectedMessageTemplate =<br />

getString(R.string.spinner_message_template);<br />

Spinner spinner1 = (Spinner)findViewById(R.id.spinner1);<br />

spinner1.setOnItemSelectedListener(new SpinnerInfo());<br />

... // Co<strong>de</strong> for spinner2 shown later<br />

}<br />

private void showToast(String text) {<br />

Toast.makeText(this, text, Toast.LENGTH_LONG).show();<br />

}<br />

// Continued on next sli<strong>de</strong> with the SpinnerInfo inner class


JAVA<br />

(RELEVANT PARTS, CONTINUED)<br />

private class SpinnerInfo implements OnItemSelectedListener {<br />

private boolean isFirst = true;<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

Don't want the Toast when the screen is first displayed,<br />

public void onItemSelected(AdapterView so ignore spinner, the first call to View onItemSelected. selectedView,<br />

Other calls are<br />

int selectedIn<strong>de</strong>x, long due to user id) interaction. {<br />

if (isFirst) {<br />

isFirst = false;<br />

} else {<br />

String selection =<br />

spinner.getItemAtPosition(selectedIn<strong>de</strong>x).toString();<br />

String message =<br />

String.format(mItemSelectedMessageTemplate, selection);<br />

showToast(message);<br />

}<br />

}<br />

@Overri<strong>de</strong><br />

public void onNothingSelected(AdapterView spinner) {<br />

// Won’t be invoked unless you programmatically remove entries<br />

}


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

SPINNER APPROACH 2:<br />

CHOICES SPECIFIED IN JAVA


SPINNER WITH CHOICES<br />

COMPUTED BY JAVA CODE<br />

• I<strong>de</strong>a<br />

• A combo box (drop down list of choices)<br />

• Same general purpose as previous example. However, here you<br />

want to programmatically compute the options to be displayed,<br />

possibly based on earlier user interaction.<br />

• Main Listener types<br />

• AdapterView.OnItemSelectedListener<br />

• AdapterView.OnItemClickedListener<br />

jeudi 26 janvier 12<br />

• These are same as in previous Spinner example


SPINNER (CONTINUED)<br />

• Key XML attributes<br />

• android:id<br />

• You need a Java reference to specify the entries and to assign an event<br />

handler.<br />

• android:prompt<br />

• The text shown at the top of Spinner when user clicks to open it.<br />

• Since this text is not shown when the Spinner is closed, the string<br />

used for the prompt is typically also displayed in a TextView above<br />

the Spinner.<br />

• android:entries<br />

• Not used in this version. Java will compute the entries.<br />

jeudi 26 janvier 12


CREATING SPINNER ENTRIES<br />

PROGRAMMATICALLY<br />

• Get reference to the Spinner<br />

Spinner spinner = (Spinner)findViewById(R.id.spinner_id);<br />

• Make an ArrayAdapter<br />

List entries = …; // Can also use String[]<br />

ArrayAdapter spinnerAdapter =<br />

new ArrayAdapter(this,<br />

android.R.layout.simple_spinner_item,<br />

entries);<br />

• Specify the drop down View resource<br />

spinnerAdapter.setDropDownViewResource<br />

(android.R.layout.simple_spinner_dropdown_item);<br />

• Set the adapter for the Spinner<br />

spinner.setAdapter(spinnerAdapter);<br />

jeudi 26 janvier 12<br />

Pre<strong>de</strong>fined entry in<br />

Android distribution


XML: LAYOUT FILE ENTRY<br />

(PART OF RES/LAYOUT/SPINNERS.XML)<br />

jeudi 26 janvier 12<br />

<br />

<br />

Same text used twice, since<br />

the text is hid<strong>de</strong>n when the<br />

Spinner is closed.<br />

android:entries is not used.<br />

Instead of having fixed<br />

choices, the Java co<strong>de</strong> will<br />

compute the options.


XML: STRINGS FILE ENTRIES<br />

(PART OF RES/VALUES/STRINGS.XML)<br />

jeudi 26 janvier 12<br />

<br />

Future Android Vendors (Choices from Java)<br />


JAVA (RELEVANT PARTS)<br />

public class SpinnerActivity extends Activity {<br />

private String mItemSelectedMessageTemplate;<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

// General co<strong>de</strong> and co<strong>de</strong> for spinner1 shown earlier<br />

List futureAndroidVendors =<br />

getFutureAndroidVendors();<br />

ArrayAdapter spinner2Adapter =<br />

new ArrayAdapter(this,<br />

android.R.layout.simple_spinner_item,<br />

futureAndroidVendors);<br />

spinner2Adapter.setDropDownViewResource<br />

(android.R.layout.simple_spinner_dropdown_item);<br />

spinner2.setAdapter(spinner2Adapter);<br />

spinner2.setOnItemSelectedListener(new SpinnerInfo());<br />

}


JAVA<br />

(RELEVANT PARTS, CONTINUED)<br />

jeudi 26 janvier 12<br />

private List getFutureAndroidVendors() {<br />

String[] vendorArray = { "Apple", "RIM",<br />

"Palm", "Microsoft" };<br />

List vendorList = Arrays.asList(vendorArray);<br />

Collections.shuffle(vendorList);<br />

return(vendorList);<br />

} The last argument to the ArrayAdapter<br />

constructor on previous page can be any List<br />

or String[]. I am randomizing the or<strong>de</strong>r of the<br />

elements to <strong>de</strong>monstrate that you can have Java<br />

compute the entries instead of having a fixed set of<br />

choiuces (in which case you would <strong>de</strong>fine the entries<br />

in the XML file as with approach 1).


jeudi 26 janvier 12<br />

RESULTS (EMULATOR)


jeudi 26 janvier 12<br />

WRAP-UP


SUMMARY<br />

• Spinner with fixed entries<br />

• Define array in strings.xml.<br />

• Use android:prompt and android:entries in layout file. Also assign id with<br />

android:id<br />

• Java gets ref and calls setOnItemSelectedListener<br />

• Spinner with computed entries<br />

• XML uses android:prompt and android:id<br />

• Java gets ref, makes ArrayAdapter with a List or String[], uses some<br />

pre<strong>de</strong>fined resource names<br />

• Switching Activities<br />

• Intent newActivity = new Intent(this, NewActivity.class);<br />

• startActivity(newActivity);<br />

• Also requires entry in AndroidManifest.xml<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Layouts:<br />

Organizing the Screen<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• LinearLayout<br />

• Strategy of nesting layouts<br />

• Using color files<br />

–And preview of Localization<br />

• Layout weights<br />

• RelativeLayout<br />

• TableLayout<br />

• hierarchyviewer<br />

261<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Main Layout Strategies<br />

• XML-based<br />

– Declare layout in res/layouts/some_layout.xml<br />

• Set various XML properties<br />

• Use visual editor in Eclipse<br />

– Load with setContentView(R.layout.some_layout)<br />

• Java-based<br />

– Instantiate layout, set properties, insert sub-layouts<br />

• LinearLayout window = new LinearLayout(this);<br />

• window.setVariousAttributes(…);<br />

• window.addView(widgetOrLayout);<br />

– Load with setContentView(window)<br />

• This tutorial<br />

– Uses XML-based approach. However, attributes can be adapted<br />

for Java-based approach.<br />

263<br />

jeudi 26 janvier 12


XML Layout Attributes<br />

• I<strong>de</strong>a<br />

– Each Layout class has an inner class called LayoutParams that<br />

<strong>de</strong>fines general XML parameters that layout uses. These<br />

parameters are always named android:layout_blah, and usually<br />

have to do with sizes and margins.<br />

– Layout classes <strong>de</strong>fine more specific attributes. Many inherited<br />

from LinearLayout (which extends ViewGroup and View).<br />

• Not named beginning with “layout_”<br />

• Example<br />

…<br />

264<br />

jeudi 26 janvier 12


Commonly Used Attributes<br />

• Size<br />

– android:layout_height, android:layout_width<br />

• match_parent: fill the parent space (minus padding)<br />

– Renamed from fill_parent in ol<strong>de</strong>r versions<br />

• wrap_content: use natural size (plus padding)<br />

• An explicit size with a number and a dimension. See margins on next sli<strong>de</strong>.<br />

– android:layout_weight<br />

• A number that gives proportional sizes. See example.<br />

• Alignment<br />

– android:layout_gravity<br />

• How the View is aligned within containing View.<br />

– android:gravity<br />

• How the text or components insi<strong>de</strong> the View are aligned.<br />

– Possible values<br />

• top, bottom, left, right, center_vertical, center_horizontal, center (i.e., center both<br />

ways), fill_vertical, fill_horizontal, fill (i.e., fill both directions), clip_vertical,<br />

clip_horizontal<br />

265<br />

jeudi 26 janvier 12


Commonly Used Attributes<br />

(Continued)<br />

• Margins (blank space outsi<strong>de</strong>)<br />

–android:layout_marginBottom, android:layout_marginTop,<br />

android:layout_marginLeft, android:layout_marginRight<br />

–Units (e.g., "14.5dp") – negative values are legal<br />

• dp: <strong>de</strong>nsity-in<strong>de</strong>pen<strong>de</strong>nt pixels (scaled by <strong>de</strong>vice resol.)<br />

• sp: scaled pixels (scaled based on preferred font size)<br />

• px: pixels<br />

• in: inches<br />

• mm: millimeters<br />

• Padding (blank space insi<strong>de</strong>)<br />

266<br />

jeudi 26 janvier 12<br />

–android:paddingBottom, android:paddingTop,<br />

android:paddingLeft, android:paddingRight<br />

• Values are numbers with units as above


Commonly Used Attributes<br />

(Continued)<br />

• ID<br />

–android:id<br />

• Used if the Java co<strong>de</strong> needs a reference to View<br />

• Used in RelativeLayout so XML can refer to earlier ids<br />

• Colors<br />

–android:background (color or image, for any Layout)<br />

–android:textColor (e.g., for TextView or Button)<br />

–Common color value formats<br />

• "#rrggbb", "#aarrggbb", "@color/color_name"<br />

• Click handler<br />

267<br />

jeudi 26 janvier 12<br />

–android:onClick<br />

• Should be a public method in main Activity that takes a View (the<br />

thing clicked) as argument and returns void


jeudi 26 janvier 12<br />

LinearLayout Basics<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


LinearLayout<br />

• I<strong>de</strong>a<br />

–Put components in a single row or single column<br />

–By nesting, can have rows within columns, etc.<br />

• Most important XML attributes<br />

269<br />

jeudi 26 janvier 12<br />

–android:orientation<br />

• "horizontal" (a row) or "vertical" (a column)<br />

• horizontal is the <strong>de</strong>fault, so can be omitted for rows<br />

–android:gravity<br />

• How the Views insi<strong>de</strong> are aligned.<br />

• Possible values<br />

– top, bottom, left, right, center_vertical, center_horizontal, center (i.e., center<br />

both ways), fill_vertical, fill_horizontal, fill (i.e., fill both directions), clip_vertical,<br />

clip_horizontal


Example Summary<br />

(Highly Nested Layouts)<br />

270<br />

jeudi 26 janvier 12<br />

• General Approach<br />

<br />

<br />

<br />


Example Details<br />

271<br />

jeudi 26 janvier 12<br />

Horizontal LinearLayout with gravity of center_horizontal.<br />

<br />

<br />

<br />

<br />

<br />

<br />

Horizontal LinearLayout with gravity of left. Otherwise almost<br />

same as first row.<br />

Remember that horizontal is the <strong>de</strong>fault for android:orientation, so this attribute was omitted for these<br />

two rows. The colors will be explained later in this tutorial.


Example Details<br />

272<br />

jeudi 26 janvier 12<br />

Horizontal LinearLayout.<br />

That Layout then contains two more horizontal LinearLayouts. The first<br />

(yellow) has android:layout_width of "wrap_content" and android:gravity<br />

of "left". The second (green) has android:layout_width of "match_parent"<br />

and android:gravity of "right".


Example Details<br />

273<br />

jeudi 26 janvier 12<br />

Horizontal LinearLayout.<br />

That Layout then contains three vertical nested layouts. The first (blue) is a<br />

LinearLayout with android:orientation of "vertical" and four Buttons insi<strong>de</strong>.<br />

The second (violet) is a RadioGroup (similar to LinearLayout but specific to<br />

enclosing RadioButtons and making them mutually exclusive), also with<br />

android:orientation of "vertical". It has four RadioButtons insi<strong>de</strong>. The third is<br />

a LinearLayout with android:orientation of "vertical" and four nested<br />

LinearLayouts insi<strong>de</strong> (<strong>de</strong>tails on next sli<strong>de</strong>).<br />

The first two columns (nested layouts) have android:layout_width of<br />

"wrap_content", and the third has android:layout_width of "match_parent".


Example Details<br />

274<br />

jeudi 26 janvier 12<br />

Vertical LinearLayout.<br />

That Layout then contains four horizontal nested layouts. The first (red)<br />

has android:gravity of "center_horizontal". The second (orange) has<br />

android:gravity of "left". The third (yellow) has android:gravity of "right".<br />

The fourth contains two further nested horizontal LinearLayouts. The first<br />

(green) has android:layout_width of "wrap_content" and android:gravity of<br />

"left". The second (blue) has android:layout_width of "match_parent" and<br />

android:gravity of "right".


Example Details<br />

275<br />

jeudi 26 janvier 12<br />

Button<br />

android:layout_width="wrap_content"<br />

android:layout_gravity="center_horizontal"<br />

android:layout_marginTop="20dp"<br />

Button<br />

android:layout_width="match_parent"


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Setting Colors<br />

(& Localization Preview)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Colors<br />

• I<strong>de</strong>a<br />

– Although colors can be <strong>de</strong>fined explicitly within layout file (e.g.,<br />

background="#ff0000"), usually more flexible to <strong>de</strong>fine color<br />

names in separate file, so they can be changed all at once. Refer<br />

to color with "@color/color_name".<br />

• Syntax<br />

<br />

#rrggbb<br />

… <br />

<br />

• Convention<br />

– Use res/values/colors.xml<br />

• However, any file name is legal. Sometimes it makes more sense to<br />

<strong>de</strong>fine all attributes (strings, arrays, colors) of a View in a single file<br />

<strong>de</strong>dicated to that view.<br />

277<br />

jeudi 26 janvier 12


Color File<br />

(res/values/colors.xml)<br />

<br />

<br />

#ff0000<br />

#ffa500<br />

#ffff00<br />

#008000<br />

#0000ff<br />

#ee82ee<br />

<br />

278<br />

jeudi 26 janvier 12


Layout File (res/layouts/<br />

nested_layouts.xml)<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

279<br />

jeudi 26 janvier 12


Result<br />

280<br />

jeudi 26 janvier 12


Localization Preview<br />

• I<strong>de</strong>a<br />

–You can store colors or other files in res/values-xy instead of<br />

res/values. If the Locale is set to xy, then that file is loa<strong>de</strong>d<br />

after the files in res/values.<br />

• If names match, later file overri<strong>de</strong>s value from earlier file<br />

• Usual approach<br />

–Locale is set for entire phone by end user<br />

• Approach used here<br />

–Locale is set programmatically<br />

• Many more <strong>de</strong>tails<br />

281<br />

jeudi 26 janvier 12<br />

–In later lecture on localization


Setting Locale Programmatically<br />

• Usual purpose<br />

–If user sometimes wants to run app in one language and other<br />

times in a different language.<br />

• Again, more common for end user to set Locale for entire phone,<br />

not for individual apps.<br />

• Purpose here<br />

282<br />

jeudi 26 janvier 12<br />

–Set the Locale to a fake value ("qq") just so that we can<br />

replace colors.xml with another version that makes all the<br />

background colors be black.


Setting Locale Programmatically<br />

• Steps<br />

Locale locale = new Locale("es"); // Language co<strong>de</strong><br />

Locale.setDefault(locale);<br />

Configuration config = new Configuration();<br />

config.locale = locale;<br />

context.getResources().updateConfiguration(config,<br />

–context above is reference to the main Activity<br />

• More <strong>de</strong>tails<br />

283<br />

jeudi 26 janvier 12<br />

–http://adrianvintu.com/blogengine/post/<br />

Force-Locale-on-Android.aspx<br />

null);


Project Layout<br />

284<br />

jeudi 26 janvier 12<br />

Sets color_1, color_2, …, color_6 to red, orange, yellow,<br />

green, blue, and violet. Full text of this file shown on<br />

earlier sli<strong>de</strong>. Used if Locale is anything other than "qq".<br />

Sets all of color_1, color_2, …, color_6 to black. Full text<br />

of this file shown on next sli<strong>de</strong>. Used only if Locale is<br />

"qq".


Localized Color File<br />

(res/values-qq/colors.xml)<br />

<br />

<br />

#000000<br />

#000000<br />

#000000<br />

#000000<br />

#000000<br />

#000000<br />

<br />

285<br />

jeudi 26 janvier 12


Main Java Co<strong>de</strong><br />

public class NestedLayoutsActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.nested_layouts);<br />

}<br />

}<br />

286<br />

jeudi 26 janvier 12<br />

...<br />

// Event handlers for bottom two Buttons<br />

There are two buttons on initial screen that invoke this same<br />

Activity. But, one sets the Locale to "qq" first.


Results<br />

287<br />

jeudi 26 janvier 12<br />

Locale set to anything<br />

other than "qq".<br />

Locale set to "qq".


jeudi 26 janvier 12<br />

Layout Weight<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Using android:layout_weight<br />

• I<strong>de</strong>a<br />

– Assign numbers for android:layout_weight. Sizes given are<br />

proportional to those values.<br />

• Steps (for heights)<br />

– Assign android:layout_height to 0dp<br />

– Use relative values for android:layout_weight<br />

• For example, if you have three nested entries with<br />

android:layout_weights of 1, 1, and 2, then they take up 25%, 25%,<br />

and 50% of the height of the parent.<br />

– Analogous approach to set widths<br />

• Common strategy<br />

– Make the layout weights add up to 100, then treat them as<br />

percents. So, use 25, 25, and 50 instead of 1, 1, and 2 in the<br />

previous example. (Same effect, but clearer.)<br />

289<br />

jeudi 26 janvier 12


Layout File (res/layouts/<br />

layout_weights.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

290<br />

jeudi 26 janvier 12


Java Co<strong>de</strong><br />

public class LayoutWeightsActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.layout_weights);<br />

}<br />

}<br />

291<br />

jeudi 26 janvier 12


Results<br />

292<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

RelativeLayout<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


RelativeLayout<br />

• I<strong>de</strong>a<br />

– Give ids to 1 or more key components (id="@+id/blah")<br />

– Position other components relative to those components<br />

• Most important XML attributes<br />

– Aligning with container<br />

• android:layout_alignParentBottom (and Top, Right, Left)<br />

• android:layout_centerInParent (and centerHorizontal, centerVertical)<br />

294<br />

jeudi 26 janvier 12<br />

– These all take "true" or "false" as values<br />

– Aligning with other component<br />

• android:layout_alignBottom (and Top, Right, Left)<br />

• android:layout_toLeftOf (and toRightOf), android:layout_above (and<br />

below)<br />

– These all take existing ids as values<br />

» android:layout_alignBlah="@id/existing_id" (@id, not @+id)


Referring to Existing IDs<br />

• First component<br />

–<br />

• Second component<br />

–<br />

• Result<br />

295<br />

jeudi 26 janvier 12<br />

Button 2<br />

@+id for assigning a new id<br />

Button 1<br />

@id (no +) for referring to an existing id


Example Summary<br />

296<br />

jeudi 26 janvier 12<br />

• General Approach<br />

<br />

<br />

<br />


Example Details<br />

297<br />

jeudi 26 janvier 12<br />

TextView with width of match_parent and specific height. Goes<br />

at top since I didn't say otherwise. Has id.<br />

TextView with android:layout_alignTop referring to first<br />

component. Moved down via android:layout_marginTop<br />

<br />


Example Details<br />

298<br />

jeudi 26 janvier 12<br />

<br />

<br />

<br />

EditText with android:layout_above referring to image button.<br />

Has width of match_parent.<br />

Button with android:layout_alignBottom and android:layout_toLeftOf referring to<br />

image button. Has width of wrap_content.<br />

Button with android:layout_alignParentBottom="true" and<br />

android:layout_alignParentRight="true". Has an id. Has width of wrap_content.<br />

This is the first Button <strong>de</strong>fined.


jeudi 26 janvier 12<br />

TableLayout<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


TableLayout<br />

• I<strong>de</strong>a<br />

– Put widgets or nested layouts in a grid. No bor<strong>de</strong>rs.<br />

– Like HTML tables, the number of rows and columns is<br />

<strong>de</strong>termined automatically, not explicitly specified.<br />

– Components are usually placed insi<strong>de</strong> TableRow<br />

• Most important XML attributes (TableLayout)<br />

– android:stretchColumns<br />

• An in<strong>de</strong>x or comma-separated list of in<strong>de</strong>xes. Specifies the column or<br />

columns that should be stretched wi<strong>de</strong>r if the table is narrower than its<br />

parent. In<strong>de</strong>xes are 0-based.<br />

– android:shrinkColumns<br />

• Column(s) that should be shrunk if table is wi<strong>de</strong>r than parent.<br />

– android:collapseColumns<br />

• Column(s) to be totally left out. Can be programmatically put back in<br />

later.<br />

300<br />

jeudi 26 janvier 12


TableRow<br />

• I<strong>de</strong>a<br />

– Goes insi<strong>de</strong> TableLayout to <strong>de</strong>fine a row.<br />

• Technically, elements between rows are permitted, but you can<br />

achieve same effect with a TableRow and android:layout_span.<br />

• Most important XML attributes of elements insi<strong>de</strong> a<br />

TableRow<br />

– android:layout_column<br />

• Normally, elements are placed in left-to-right or<strong>de</strong>r. However, you can<br />

use android:layout_column to specify an exact column, and thus<br />

leave earlier columns empty.<br />

– android:layout_span<br />

• The number of columns the element should straddle.<br />

Like colspan for HTML tables.<br />

• There is nothing equivalent to HTML’s rowspan; you must use nested<br />

tables instead. See example.<br />

301<br />

jeudi 26 janvier 12


Example Summary<br />

302<br />

jeudi 26 janvier 12<br />

• General Approach<br />

<br />

<br />

…<br />

…<br />

…<br />

…<br />

<br />

This is why the middle column<br />

is wi<strong>de</strong>r than the other two<br />

columns.


Example Details<br />

303<br />

jeudi 26 janvier 12<br />

Two TableRows, each with 3 Buttons. No special options.<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />


Example Details<br />

304<br />

jeudi 26 janvier 12<br />

Button 7 uses android:layout_column="2". So, there is no entry<br />

at all for the middle column.<br />

Button 9 uses android:layout_span="2".<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />


Example Details<br />

305<br />

jeudi 26 janvier 12<br />

A nested table. Uses android:layout_span="2" so that it straddles two<br />

columns of the main table. Uses android:stretchColumns="1" so that the<br />

second column fills available space.<br />

A Button. android:layout_height is match_parent so that it is the same height<br />

as table to its left. There is no option similar to HTML’s colspan, so nested<br />

tables are nee<strong>de</strong>d to achieve this effect.<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />


jeudi 26 janvier 12<br />

The Hierarchy Viewer<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Hierarchy Viewer<br />

• I<strong>de</strong>a<br />

–The Android distribution inclu<strong>de</strong>s a program called<br />

hieararchyviewer that will show a graphical representation of<br />

Views and sub-Views. Useful for <strong>de</strong>bugging and<br />

un<strong>de</strong>rstanding nested layouts.<br />

• Details<br />

307<br />

jeudi 26 janvier 12<br />

–Start app in emulator. Go to screen of interest.<br />

–Go to android-sdk/tools (or, put this in your PATH)<br />

–Type hierarchyviewer<br />

–Click on Focused Window,<br />

then press Load View<br />

Hierarchy button<br />

–Explore!


Hierarchy View for<br />

RelativeLayout Example<br />

308<br />

jeudi 26 janvier 12<br />

Click on an entry to show which part of screen it corresponds to,<br />

and to get <strong>de</strong>tails about the XML attributes.<br />

Details: http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/<strong>de</strong>veloping/<strong>de</strong>bugging/<strong>de</strong>bugging-ui.html


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Other Layouts<br />

• AbsoluteLayout<br />

–From ol<strong>de</strong>r versions; now <strong>de</strong>precated; use RelativeLayout<br />

• FrameLayout<br />

–For formatting a single item. Usually used explicitly with<br />

TabHost. Used internally by other layouts.<br />

• TabHost<br />

–Combines tabs with switching Activities. Covered in later<br />

lecture on Intents and Activity switching.<br />

• ListView and GridView<br />

310<br />

jeudi 26 janvier 12<br />

–Not generalized layouts, but have somewhat similar role.<br />

Covered in later lecture.


More Reading<br />

• Tutorial: Declaring Layout<br />

–http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/ui/<br />

<strong>de</strong>claring-layout.html<br />

• Tutorial: Hello Views<br />

–http://<strong>de</strong>veloper.android.com/resources/tutorials/views/<br />

• Has sub-sections on LinearLayout, RelativeLayout, and<br />

TableLayout<br />

• Chapter: Working with Containers<br />

–From The Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development by<br />

Mark Murphy.<br />

• http://commonsware.com/Android/<br />

• Chapter: User Interface Layout<br />

311<br />

jeudi 26 janvier 12<br />

–From The Android Developer’s Cookbook by Steele & To


Summary<br />

• LinearLayout<br />

– I<strong>de</strong>as<br />

• One row or one column.<br />

• Nesting is key window-layout strategy<br />

– Key XML attributes<br />

• android:orientation, android:layout_weight<br />

• RelativeLayout<br />

– I<strong>de</strong>a<br />

• Position later component relative to earlier one<br />

– Key XML attributes<br />

• android:layout_alignBottom (and similar),<br />

android:layout_toLeftOf (and similar)<br />

• TableLayout<br />

– I<strong>de</strong>a<br />

• Put components in a grid<br />

– Key XML attributes for entries insi<strong>de</strong> TableRow<br />

• android:layout_column, android:layout_span<br />

312<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Android Coding Style Conventions<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Why follow conventions?<br />

• Valuable conventions<br />

–Ones that are wi<strong>de</strong>ly consi<strong>de</strong>red good practice for any Java<br />

project (based on general Java industry consensus)<br />

• Tolerable conventions<br />

–Ones that do no harm, but are of questionable value<br />

(in Marty’s highly subjective opinion)<br />

• Dubious conventions<br />

314<br />

jeudi 26 janvier 12<br />

–Ones that we would have been better off without<br />

(in Marty’s highly subjective opinion)


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Official Android Co<strong>de</strong><br />

Conventions<br />

• Required for<br />

– Co<strong>de</strong> contributed to Android project<br />

• Used in<br />

– All official tutorials and (supposedly) all source co<strong>de</strong><br />

• Suggested for<br />

– Co<strong>de</strong> submitted to the app store<br />

– Any Android project<br />

• Details<br />

– http://source.android.com/source/co<strong>de</strong>-style.html<br />

• Eclipse preferences file<br />

– Downloadable from coreservlets.com from this section of the<br />

Android Tutorial.<br />

• Sets spacing, brace style, and use of @Overri<strong>de</strong><br />

316<br />

jeudi 26 janvier 12


Pros and Cons of Following<br />

Conventions<br />

• Pros<br />

– Consistent with official tutorials and Android source<br />

– More familiar to Android <strong>de</strong>velopers who join your team<br />

• Cons<br />

– Inconsistent with Java co<strong>de</strong> you wrote before<br />

– Less familiar to other Java <strong>de</strong>velopers<br />

– Simply bothers you.<br />

• Java <strong>de</strong>velopers often have strong personal preferences<br />

• My recommendations<br />

– Most conventions are best practices anyhow<br />

• Definitely follow those<br />

– Most others are neither worse nor better than alternatives<br />

• Probably follow those<br />

– A few are (arguably) bad or at least wrong in some situations<br />

• Ignore those if the situation warrants it<br />

317<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Conventions that are Good<br />

Standard Practice<br />

(For any Java project)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


In<strong>de</strong>ntation: blocks that are nested<br />

more should be in<strong>de</strong>nted more<br />

• Yes<br />

blah;<br />

blah;<br />

for(...) {<br />

}<br />

319<br />

jeudi 26 janvier 12<br />

blah;<br />

blah;<br />

for(...) {<br />

}<br />

blah;<br />

blah;<br />

• No<br />

blah;<br />

blah;<br />

for(...) {<br />

blah;<br />

blah;<br />

for(...) {<br />

blah;<br />

blah;<br />

}<br />

}


In<strong>de</strong>ntation: blocks that are nested the same<br />

should be in<strong>de</strong>nted the same<br />

• Yes<br />

blah;<br />

blah;<br />

for(...) {<br />

}<br />

320<br />

jeudi 26 janvier 12<br />

blah;<br />

blah;<br />

for(...) {<br />

}<br />

blah;<br />

blah;<br />

• No<br />

blah;<br />

blah;<br />

for(...) {<br />

}<br />

}<br />

blah;<br />

blah;<br />

for(...) {<br />

blah;<br />

blah;


Break Things into Small Pieces<br />

• Write short methods<br />

–No official limit, but try to keep methods short and focused.<br />

Think often about how to refactor your co<strong>de</strong> to break it into<br />

smaller and more reusable pieces.<br />

• This is good advice in any language.<br />

• This also shows why overly strict rules on the length of<br />

comments can be counter productive by encouraging <strong>de</strong>velopers<br />

to write long methods to avoid writing docs.<br />

• Keep lines short<br />

321<br />

jeudi 26 janvier 12<br />

–They have a strict rule of 100 characters except for imports or<br />

comments that contain URLs or commands that cannot be<br />

broken up.<br />

• Not sure 100 is the magic number, but short lines are good<br />

practice anyhow.


Follow Normal Capitalization<br />

Rules<br />

• Classes start with uppercase letter<br />

public class SomeClass { … }<br />

• Constants use all caps<br />

public static final double GOLDEN_RATIO =<br />

(1 + Math.sqrt(5.0))/2;<br />

• Everything else starts with lowercase letter<br />

–Instance variables, local variables, parameters to methods,<br />

package names<br />

• Extra rule<br />

322<br />

jeudi 26 janvier 12<br />

–Use words for acronyms, not all uppercase<br />

• getUrl, not getURL<br />

– This is good advice in Web apps also


Use JavaDoc<br />

• Use JavaDoc from the beginning<br />

–Don’t wait until the co<strong>de</strong> is finished. Short comments are fine,<br />

but use some. Explain purpose and non-obvious behavior.<br />

Don’t explain standard Java constructs.<br />

• Document every class<br />

/** Represents a collection of Blahs. Used to … **/<br />

public class Foo { … }<br />

• Document anything public<br />

–Methods<br />

–Constructors<br />

–Instance variables (but very rare to have public ones)<br />

• Review Oracle JavaDoc gui<strong>de</strong>lines<br />

• http://www.oracle.com/technetwork/java/javase/documentation/in<strong>de</strong>x-137868.html<br />

323<br />

jeudi 26 janvier 12


Use @Overri<strong>de</strong><br />

• Use @Overri<strong>de</strong> when you overri<strong>de</strong> methods<br />

from parent class<br />

–Won’t be caught until run time<br />

public void oncreate(Bundle savedInstanceState) {<br />

…<br />

}<br />

–Will be caught at compile time<br />

@Overri<strong>de</strong><br />

public void oncreate(Bundle savedInstanceState) {<br />

…<br />

}<br />

• Gui<strong>de</strong>lines are silent regarding interfaces<br />

324<br />

jeudi 26 janvier 12<br />

–But, in Java 6 or later, I prefer to also use @Overri<strong>de</strong> when<br />

implementing methods from interface


Use Other Standard Annotations<br />

when Warranted (but Rarely)<br />

• @Deprecated<br />

–If you use a <strong>de</strong>precated method, add this annotation to your<br />

method. Also add @<strong>de</strong>precated JavaDoc tag explaining why it<br />

was necessary to use <strong>de</strong>pracated co<strong>de</strong>.<br />

• Of course, try hard to avoid use of <strong>de</strong>precated methods<br />

• @SuppressWarnings<br />

325<br />

jeudi 26 janvier 12<br />

–Generic collections are prohibited from doing extra work at<br />

run time, so casting to generic type can cause warning that<br />

Java can’t verify the types. Sometimes unavoidable<br />

• @SuppressWarnings("unchecked")<br />

• Other similar situations when making generic types<br />

–Android gui<strong>de</strong>lines require a TODO comment in these cases,<br />

saying why you cannot avoid the situation


Limit the Scope of Variables<br />

• Use narrowest scope possible<br />

– Variables should be <strong>de</strong>clared in the innermost block that encloses<br />

all uses of the variable.<br />

• E.g., if variable is only used insi<strong>de</strong> if statement, <strong>de</strong>clare it insi<strong>de</strong> if<br />

statement.<br />

– Yes<br />

if (…) {<br />

double d = someCalculation(…);<br />

doSomethingWith(d);<br />

} else {<br />

// No use of d<br />

}<br />

– No<br />

double d = 0;<br />

if (…) { … } else { … }<br />

326<br />

jeudi 26 janvier 12


Initialize Local Variables when<br />

Declared<br />

• Initialize (almost) all local variables<br />

327<br />

jeudi 26 janvier 12<br />

–Yes<br />

String s = "Hello";<br />

–No<br />

String s;<br />

…<br />

s = "Hello";<br />

–Exception: try/catch blocks<br />

int n;<br />

try {<br />

n = Integer.parseInt(someString);<br />

} catch(NumberFormatException nfe) {<br />

n = 10;<br />

}


Put Braces on Conditionals<br />

• Always use braces for if statements<br />

–Even if there is only one thing to do<br />

• Yes<br />

if (…) {<br />

• No<br />

}<br />

doSomething();<br />

if (…)<br />

doSomething();<br />

• Gui<strong>de</strong>lines give small exception<br />

328<br />

jeudi 26 janvier 12<br />

–If there is only one thing to do and it is all on one line<br />

• Tolerated (grudgingly?)<br />

if (…) doSomething();


Use TODO Comments for<br />

Temporary Co<strong>de</strong><br />

• Use “// TODO: … ” for co<strong>de</strong> that needs to be<br />

changed later<br />

–Situations<br />

• Temporary fix<br />

• OK but not great<br />

• Works for small sizes, but bad performance in future when data<br />

sets get bigger.<br />

–Examples:<br />

// TODO: Switch to a Map when you have more entries<br />

// TODO: Remove after UrlTable2 has been checked in<br />

• Eclipse note<br />

329<br />

jeudi 26 janvier 12<br />

–Eclipse puts TODO in bold and puts check mark in left<br />

margin of co<strong>de</strong>


Avoid Finalizers<br />

• Do not use finalize()<br />

–I<strong>de</strong>a<br />

• finalize() gets called when an object is garbage collected, so you<br />

can do cleanup work then (such as closing socket connections)<br />

–Problem<br />

• No guarantee when (or even if) finalizer will be called<br />

–Gui<strong>de</strong>lines<br />

• Don’t use them.<br />

• Good news<br />

330<br />

jeudi 26 janvier 12<br />

–Finalizers have long ago fallen out of favor, and many Java<br />

<strong>de</strong>velopers don’t even know what they are.


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Conventions that<br />

Don’t Hurt<br />

(No harm in following them, but<br />

their value is questionable)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Put Open Braces with Preceding<br />

Co<strong>de</strong><br />

• Put { with previous line, not on its own line<br />

332<br />

jeudi 26 janvier 12<br />

–Yes<br />

public void foo() {<br />

if (...) {<br />

doSomething();<br />

}<br />

}<br />

–No public void foo()<br />

{<br />

}<br />

if (...)<br />

{<br />

doSomething();<br />

}


In<strong>de</strong>nt 4 Spaces for Blocks<br />

• In<strong>de</strong>nt 4 spaces when starting a block<br />

333<br />

jeudi 26 janvier 12<br />

–Yes<br />

public void foo() {<br />

if (...) {<br />

doSomething();<br />

}<br />

}<br />

–No<br />

public void foo() {<br />

if (...) {<br />

doSomething();<br />

}<br />

}


In<strong>de</strong>nt 8 Spaces for Lines<br />

• In<strong>de</strong>nt 8 spaces when splitting a line<br />

334<br />

jeudi 26 janvier 12<br />

–Yes<br />

String s =<br />

somethingVeryLong(…);<br />

–No<br />

String s =<br />

somethingVeryLong(…);


Fully Qualify Imports<br />

• List each class name; don’t use *<br />

–Yes<br />

• import android.widget.Button;<br />

• import android.widget.CheckBox;<br />

• import android.widget.EditText;<br />

–No<br />

• import android.widget.*;<br />

• Exception<br />

335<br />

jeudi 26 janvier 12<br />

–Can use * for java or javax packages<br />

• Permitted<br />

– import java.util.*;


Or<strong>de</strong>r Import Statements<br />

• First<br />

– Android packages<br />

• import android.foo.Bar;<br />

• Second<br />

– Third party packages<br />

• import com.coreservlets.utils.RandomUtils;<br />

• Third<br />

– Standard java or javax packages<br />

• import java.util.*;<br />

• Within each group<br />

– Alphabetical (uppercase Z before lowercase a)<br />

• Separating groups<br />

– Blank line between each major grouping<br />

336<br />

jeudi 26 janvier 12


Start JavaDoc Comments with 3 rd<br />

Person Verb<br />

• Examples<br />

–Yes<br />

• Represents a …<br />

• Responds to mouse clicks with …<br />

• Deletes …<br />

–No<br />

• This class …<br />

• This method …<br />

• Android’s own docs are inconsistent<br />

337<br />

jeudi 26 janvier 12<br />

–Many (most?) classes start with “This class” or similar.<br />

• E.g., View, Activity, LinearLayout


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Questionable Conventions<br />

(You would have been<br />

better off without them)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Start Instance Variables with<br />

“m” (normal) or “s” (static)<br />

• Use “m” for non-public, non static fields<br />

– “m” for “member variable” or “data member”<br />

• Yes<br />

– private String mFirstName;<br />

– private boolean mIsMarried;<br />

• No<br />

– private String firstName;<br />

– private boolean isMarried;<br />

• Use “s” for static (non-final) fields<br />

• Yes<br />

– private static double sBiggestRadius;<br />

• No<br />

– private static double biggestRadius;<br />

• Marty’s opinion<br />

– Results in less readable names with no real benefit<br />

339<br />

jeudi 26 janvier 12


Impact of Naming Convention<br />

on Constructors<br />

Standard Style<br />

public class Person {<br />

public String firstName, lastName;<br />

}<br />

340<br />

public Person(String firstName,<br />

String lastName) {<br />

this.firstName = firstName;<br />

this.lastName = lastName;<br />

}<br />

…<br />

jeudi 26 janvier 12<br />

Android Style<br />

public class Person {<br />

public String mFirstName, mLastName;<br />

}<br />

public Person(String firstName,<br />

String lastName) {<br />

mFirstName = firstName;<br />

mLastName = lastName;<br />

}<br />


Never Ignore Exceptions<br />

• Avoid empty catch blocks<br />

341<br />

jeudi 26 janvier 12<br />

–Yes<br />

try {<br />

…<br />

} catch(SomeException se) {<br />

doSomethingReal();<br />

}<br />

–No<br />

try {<br />

…<br />

} catch(SomeException se) { }<br />

–Marty’s opinion<br />

• Usually, but not always, a good rule


Why Ignoring Exceptions Rule is<br />

Too Strict<br />

• Can make shorter co<strong>de</strong> with same safety<br />

342<br />

jeudi 26 janvier 12<br />

–Android style<br />

int n;<br />

try {<br />

n = Integer.parseInt(…);<br />

} catch(NumberFormatException nfe) {<br />

n = 10;<br />

}<br />

–Shorter style if you could ignore exceptions<br />

int n = 10;<br />

try {<br />

n = Integer.parseInt(…);<br />

} catch(NumberFormatException nfe) { }


Why Ignoring Exceptions Rule is<br />

Too Strict (Continued)<br />

• Sometimes there is nothing to be done<br />

try {<br />

Thread.sleep(…);<br />

} catch(InterruptedException ie) {<br />

// What could you do here?<br />

}<br />

doSomethingAfterThePause();<br />

343<br />

jeudi 26 janvier 12


Don’t Catch Generic Exception<br />

• List each Exception type<br />

–Yes<br />

try {<br />

…<br />

} catch(ExceptionType1 et1) {<br />

…<br />

} catch(ExceptionType2 et2) {<br />

…<br />

}<br />

344<br />

jeudi 26 janvier 12<br />

–No try {<br />

…<br />

} catch(Exception e) {<br />

…<br />

}


Why Generic Exception Rule is<br />

(Arguably) Too Strict<br />

• Listing each type is almost always best<br />

–So exceptions you didn’t expect don’t get caught there<br />

–So real failure-handling is not obscured<br />

• Sometimes combining is concise and safe<br />

345<br />

jeudi 26 janvier 12<br />

–E.g., if someString could be null, you could have either<br />

NumberFormatException or NullPointerException. But, in<br />

both cases, you just want to use original value for n.<br />

int n = 10;<br />

try {<br />

n = Integer.parseInt(someString);<br />

} catch(Exception e) { }


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• Strictly follow conventions that reflect wi<strong>de</strong>ly<br />

accepted best practices<br />

– Also, familiarize yourself with best practices.<br />

• All <strong>de</strong>velopers who have worked with Java more than two years full<br />

time should read Josh Bloch’s Effective Java (2 nd Edition).<br />

– Even experts will learn something new and valuable<br />

• For other conventions, if you don’t strongly object,<br />

follow the conventions anyhow<br />

– Even if you don’t see any real value<br />

• If convention really bothers you, ignore it<br />

– Assuming it is not in category of generally accepted best<br />

practices. Personal taste plays role in many of them.<br />

347<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Intents, Intent Filters,<br />

and Invoking Activities:<br />

Part I: Using Class Name<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Part I<br />

–Invoking Activities by class name<br />

–Defining dimensions in res/values<br />

–Sending data via the “extras” Bundle<br />

• Part II<br />

–Invoking Activities with a URI<br />

–Sending data via parameters in the URI<br />

• Part III<br />

349<br />

jeudi 26 janvier 12<br />

–Invoking Activities with tabbed windows<br />

–Defining two-image icons in res/drawable


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


I<strong>de</strong>a<br />

• Android philosophy<br />

–Activities are small, single-screen units<br />

• Consequence<br />

–You need easy way to switch from one Activity to another<br />

• Approach: use Intent<br />

351<br />

jeudi 26 janvier 12<br />

–An abstract <strong>de</strong>scription of an operation to be performed<br />

–Intent can refer to class name of Activity or a URI<br />

–If a URI, then Activity registers as handler for the scheme,<br />

host name, or MIME type of the URI<br />

–In all cases, new Activity must have entry in<br />

AndroidManifest.xml in or<strong>de</strong>r to be invoked


Summary of Options<br />

• Invoke Activity by class name (Part I)<br />

–Exactly one Activity can match<br />

–New Activity must be in same project as original<br />

–Can send data via an “extras” Bundle<br />

• Invoke Activity by URI (Part II)<br />

–More than one Activity could match<br />

–New Activity need not be in the same project as original<br />

–Can send data via URI parameters or “extras” Bundle<br />

• Switch Activities via tabs (Part III)<br />

352<br />

jeudi 26 janvier 12<br />

–Can use class name or URI to specify Activity<br />

–New Activity must be in same project as original<br />

–Can send data via URI parameters or “extras” Bundle


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example Target Activity:<br />

Loan Payment Calculator<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example Target Activity:<br />

Loan Calculator<br />

• Inputs<br />

–Loan amount<br />

–Interest rate (as a percent)<br />

–Loan period in months<br />

• Outputs<br />

–Monthly payment<br />

–Total payments over life of loan<br />

• Both are in same units<br />

(e.g., dollars) as the loan amount<br />

• Defaults<br />

354<br />

jeudi 26 janvier 12<br />

–Unless values are passed in from other Activity, uses <strong>de</strong>fault<br />

values for all inputs


Summary of Layout<br />

355<br />

jeudi 26 janvier 12<br />

Entries in first column<br />

are right-aligned.<br />

Entries in second column are<br />

left-aligned. They are also given<br />

ids so that the Java co<strong>de</strong> can<br />

insert the text.<br />

This is a View with<br />

android:column_span="2" and<br />

a fixed height.<br />

TableLayout


XML: Layout File: First Row<br />

(res/layout/loan_payment.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

356<br />

jeudi 26 janvier 12<br />

Second and third rows are very similar. Bottom two rows are almost the same except for a different textColor for the second column.


XML: Layout File: Divi<strong>de</strong>r<br />

(res/layout/loan_payment.xml)<br />

357<br />

jeudi 26 janvier 12<br />

<br />

<br />


XML: Strings File<br />

(res/values/strings.xml)<br />

<br />

<br />

Intent Filters and Activity Switching<br />

<br />

Loan Calculator: Monthly Payments<br />

<br />

Tabbed Windows<br />

Loan amount:&#160;&#160;<br />

Interest rate:&#160;&#160;<br />

Months:&#160;&#160;<br />

Monthly payment:&#160;&#160;<br />

Total payments:&#160;&#160;<br />

<br />

358<br />

jeudi 26 janvier 12<br />

The same prompts will also be used in a later input form.<br />

Note that &#160; represents a non-breaking space. Regular spaces are not preserved at the beginning and end of strings in Android<br />

resource files. Note also that &nbsp; is not legal here, since that is a character entity specific to HTML, not general in XML.


XML: Colors File<br />

(res/values/colors.xml)<br />

<br />

<br />

<br />

#d3d3d3<br />

#ffffff<br />

#ff0000<br />

<br />

359<br />

jeudi 26 janvier 12


XML: Dimensions File<br />

(res/values/dimensions.xml)<br />

<br />

<br />

20dp<br />

<br />

360<br />

jeudi 26 janvier 12<br />

If you haven't seen a dimensions file before, note that the file name is arbitrary, as with all of the resource files in res/values. However, dimensions.xml is<br />

a common convention. Since they come with units (dp, sp, px, in, mm), you cannot store dimensions as regular strings. Dimensions are supplied via<br />

"@dimen/some_name" to attributes that expect font sizes, margin sizes, widths, heights, etc. In this case, "@dimen/font_size" was supplied for the<br />

android:textSize attribute of each of the TextViews.


Java (LoanCalculatorActivity.java)<br />

public class LoanCalculatorActivity extends Activity {<br />

private double mLoanAmount=100000,<br />

mAnnualInterestRateInPercent=5.0;<br />

private long mLoanPeriodInMonths=360; // 30 years<br />

private String mCurrencySymbol = "$";<br />

361<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.loan_payments);<br />

setInputsFromExtras();<br />

setInputsFromUri();<br />

calculateAndSetOutputValues();<br />

}<br />

We will explain setInputsFromExtras in an upcoming subsection. We will explain setInputsfromUri in Part II of the<br />

Intents series. For now, these methods make no changes to the instance variables, and the <strong>de</strong>fault values of the<br />

instance variables (shown at the top) will be used by calculateAndSetOutputValues.


Java, Continued<br />

(LoanCalculatorActivity.java)<br />

private void calculateAndSetOutputValues() {<br />

PaymentInfo paymentInfo =<br />

new PaymentInfo(mLoanAmount, mAnnualInterestRateInPercent,<br />

mLoanPeriodInMonths, mCurrencySymbol);<br />

TextView loanAmountDisplay = (TextView)findViewById(R.id.loan_amount);<br />

loanAmountDisplay.setText(paymentInfo.getFormattedLoanAmount());<br />

TextView interestRateDisplay =<br />

(TextView)findViewById(R.id.interest_rate);<br />

interestRateDisplay.setText<br />

(paymentInfo.getFormattedAnnualInterestRateInPercent());<br />

TextView loanPeriodDisplay = (TextView)findViewById(R.id.loan_period);<br />

loanPeriodDisplay.setText(paymentInfo.getFormattedLoanPeriodInMonths());<br />

TextView monthlyPaymentDisplay =<br />

(TextView)findViewById(R.id.monthly_payment);<br />

monthlyPaymentDisplay.setText(paymentInfo.getFormattedMonthlyPayment());<br />

TextView totalPaymentsDisplay =<br />

(TextView)findViewById(R.id.total_payments);<br />

totalPaymentsDisplay.setText(paymentInfo.getFormattedTotalPayments());<br />

}<br />

362<br />

jeudi 26 janvier 12<br />

The math is done in the PaymentInfo class (next sli<strong>de</strong>s) at the top of the method,<br />

which in turn calls the LoanUtils class (following sli<strong>de</strong>s). The rest of the co<strong>de</strong> just<br />

assigns the output values to the TextViews that are in the second column of the table<br />

from the layout file (res/layouts/loan_payments.xml).


Java (PaymentInfo.java)<br />

public class PaymentInfo {<br />

private final double mLoanAmount, mAnnualInterestRateInPercent,<br />

mMonthlyPayment, mTotalPayments;<br />

private final long mLoanPeriodInMonths;<br />

private final String mCurrencySymbol;<br />

}<br />

363<br />

jeudi 26 janvier 12<br />

public PaymentInfo(double loanAmount, double annualInterestRateInPercent,<br />

long loanPeriodInMonths, String currencySymbol) {<br />

mLoanAmount = loanAmount;<br />

mAnnualInterestRateInPercent = annualInterestRateInPercent;<br />

mLoanPeriodInMonths = loanPeriodInMonths;<br />

mCurrencySymbol = currencySymbol;<br />

mMonthlyPayment = LoanUtils.monthlyPayment(loanAmount,<br />

annualInterestRateInPercent,<br />

loanPeriodInMonths);<br />

mTotalPayments = mMonthlyPayment * mLoanPeriodInMonths;<br />

}<br />

...<br />

The remaining methods are just getter methods and variations of the getter methods<br />

that return the values as formatted strings (e.g., with commas and with exactly two<br />

values after the <strong>de</strong>cimal point).


Java (LoanUtils.java)<br />

public class LoanUtils {<br />

public static double monthlyPayment(double loanAmount,<br />

double annualInterestRateInPercent,<br />

long loanPeriodInMonths) {<br />

if (annualInterestRateInPercent


Example: Results<br />

365<br />

jeudi 26 janvier 12<br />

For now, these values are fixed to the initial values set<br />

for the instance variables of the<br />

LoanCalculatorActivity. However, the upcoming<br />

sections will show how to pass values from another<br />

Activity to this one.<br />

Computed by LoanUtils. Formatted by<br />

PaymentInfo.


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Invoking Activities by<br />

Class Name<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• I<strong>de</strong>a<br />

– Specify class name of new Activity<br />

• New Activity must be in same project as original Activity<br />

• Syntax<br />

– Java (original Activity)<br />

367<br />

jeudi 26 janvier 12<br />

Intent activityIntent = new Intent(this, NewActivity.class);<br />

startActivity(activityIntent);<br />

– XML (AndroidManifest.xml)<br />

<br />

<br />

<br />

<br />

<br />


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Invoking Loan Calculator<br />

with Default Values<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example: Overview<br />

• Initial Activity<br />

–Has Button that, when pressed,<br />

invokes the loan calculator activity<br />

• No data is sent to the loan calculator,<br />

so it will use <strong>de</strong>fault values for the<br />

loan amount, interest rate, etc.<br />

• Approach<br />

369<br />

jeudi 26 janvier 12<br />

–Create Intent referring to LoanCalculatorActivity.class<br />

• Thus, the two Activities must be in same project<br />

–Call startActivity<br />

–Put entry for LoanCalculatorActivity in AndroidManifest.xml<br />

• So that the initial Activity has permission to invoke the loan<br />

calculator


XML: Layout File<br />

(res/layout/main.xml)<br />

<br />

<br />

<br />

...<br />

<br />

370<br />

jeudi 26 janvier 12<br />

Other buttons shown later


XML: Manifest File Template<br />

(AndroidManifest.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

371<br />

jeudi 26 janvier 12<br />

Other Activities will be<br />

<strong>de</strong>clared here.<br />

See next sli<strong>de</strong> for<br />

LoanCalculatorActivity.<br />

Means that this is the<br />

Action that runs when<br />

you run the project.<br />

This part is generated automatically<br />

when you build a new Android<br />

project in Eclipse.<br />

Means that this app<br />

gets an icon on the<br />

screen of your Android<br />

<strong>de</strong>vice.


XML: Manifest File<br />

Action Declaration<br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

...<br />

<br />

<br />

372<br />

jeudi 26 janvier 12<br />

The "data" tag of the land the "activity" tag for the tabbed<br />

windows Activity are both shown later.<br />

Use the fully-qualified name if the new Activity is in a<br />

different package than the main one (i.e., the one<br />

listed at the top in the "manifest" start tag).<br />

Means that this Action<br />

displays data to the user,<br />

but is not launched as the<br />

initial Activity of the project.<br />

Means that this Action can<br />

be the <strong>de</strong>fault for certain<br />

types of data (shown later).<br />

You virtually always set action.VIEW and category.DEFAULT for<br />

Activities that will be invoked by other Activities.


XML: Strings File<br />

(res/values/strings.xml)<br />

<br />

<br />

<br />

Intent Filters and Activity Switching<br />

<br />

...<br />

<br />

373<br />

jeudi 26 janvier 12<br />

Other strings shown earlier, and apply to the LoanCalculatorActivity, not to the initial Activity with the buttons that launch the loan calculator.


Java (IntentFilter1Activity.java)<br />

public class IntentFilter1Activity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

}<br />

374<br />

jeudi 26 janvier 12<br />

public void showLoanPayments1(View clickedButton) {<br />

Intent activityIntent =<br />

new Intent(this, LoanCalculatorActivity.class);<br />

startActivity(activityIntent);<br />

}<br />

...<br />

Event handler methods for other buttons shown later


Example: Results<br />

375<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Sending Data via the<br />

“Extras” Bundle<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• I<strong>de</strong>a<br />

– Attach a Bundle (like a Map – see next sli<strong>de</strong>s) to the Intent. The<br />

Bundle will contain data to be used by the new Activity.<br />

• Syntax<br />

– Java (original Activity)<br />

Intent activityIntent = new Intent(this, NewActivity.class);<br />

Bundle newActivityInfo = new Bundle();<br />

newActivityInfo.putBlah(…); // putDouble, putString, etc.<br />

activityIntent.putExtras(newActivityInfo);<br />

startActivity(activityIntent);<br />

– Java (new Activity)<br />

Intent intent = getIntent();<br />

Bundle info = intent.getExtras();<br />

if (info != null) { /* Retrieve vals with info.getBlah(...) */ }<br />

377<br />

jeudi 26 janvier 12


The Bundle Class: Details<br />

• Putting data in a Bundle<br />

– putBoolean, putBooleanArray, putDouble, putDoubleArray,<br />

putString, putStringArray, etc.<br />

• These all take keys and values as arguments.<br />

The keys must be Strings. The values must be of the standard types<br />

(int, double, etc.) or array of them.<br />

– You can also make a custom class that implements Serializable or Parceleable, then<br />

store instance of that class with putSerializable or putParceleable<br />

• Methods return void, so you cannot chain as with the putExtra method<br />

of Intent.<br />

• Retrieving data from a Bundle<br />

– getBoolean, getBooleanArray, getDouble, getDoubleArray,<br />

getString, getStringArray, etc.<br />

• These take keys (Strings) as arguments.<br />

No typecast required on retrieval.<br />

378<br />

jeudi 26 janvier 12


Option 1: Attaching Entire Bundle<br />

to Intent<br />

• I<strong>de</strong>a<br />

–Make a Bundle, add it all at once to Intent.<br />

• Instantiate a Bundle, then use the Bundle’s putBlah method (one<br />

such method for each standard type). Then, attach Bundle to<br />

Intent with Intent’s putExtras method.<br />

• Syntax<br />

Bundle newActivityInfo = new Bundle();<br />

newActivityInfo.putDouble("key1", someDouble);<br />

newActivityInfo.putString("key2", someString);<br />

…<br />

yourIntent.putExtras(newActivityInfo);<br />

379<br />

jeudi 26 janvier 12<br />

– Note that it is putExtras, not putExtra


Option 2: Adding One Piece of<br />

Data at a Time to Intent<br />

• I<strong>de</strong>a<br />

–Add individual pieces of data to the Intent. No need to<br />

explicitly create and attach a Bundle.<br />

• You use the overloa<strong>de</strong>d “putExtra” method. The first argument is<br />

the key (String), and the second argument is the value, which<br />

can be of any standard type. However, the co<strong>de</strong> that retrieves the<br />

value later needs to know type.<br />

• Syntax<br />

yourIntent.putExtra("key1", someDouble);<br />

yourIntent.putExtra("key2", someString);<br />

…<br />

– Unlike putBlah for Bundle, these putExtra methods return the Intent, so you<br />

can do jQuery-like chaining:<br />

380<br />

jeudi 26 janvier 12<br />

» yourIntent.putExtra(…).putExtra(…) … .putExtra(…);


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Invoking Loan Calculator<br />

with Custom Values<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example: Overview<br />

• Initial Activity<br />

–Has Button that, when pressed,<br />

invokes the loan calculator activity<br />

• Creates randomized data and<br />

sends it to the loan calculator, which<br />

retrieves the values and uses them<br />

for its calculations.<br />

• Approach<br />

382<br />

jeudi 26 janvier 12<br />

–Create Intent referring to LoanCalculatorActivity.class<br />

–Create Bundle with 3 values<br />

• Loan amount, interest rate, loan period<br />

–Attach Bundle to Intent with putExtras<br />

–Call startActivity<br />

–Put entry for LoanCalculatorActivity in manifest


XML: Layout File<br />

(res/layout/main.xml)<br />

<br />

<br />

...<br />

<br />

...<br />

<br />

383<br />

jeudi 26 janvier 12<br />

First button shown earlier


XML: Manifest File<br />

Action Declaration<br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

...<br />

<br />

<br />

384<br />

jeudi 26 janvier 12<br />

No changes from previous example.


Java (IntentFilter1Activity.java)<br />

public class IntentFilter1Activity extends Activity {<br />

...<br />

}<br />

385<br />

jeudi 26 janvier 12<br />

public void showLoanPayments2(View clickedButton) {<br />

Intent activityIntent =<br />

new Intent(this, LoanCalculatorActivity.class);<br />

activityIntent.putExtras<br />

(LoanBundler.makeRandomizedLoanInfoBundle());<br />

startActivity(activityIntent);<br />

}<br />

...<br />

Co<strong>de</strong> for onCreate and first button’s event handler shown earlier.


Java (LoanBundler.java)<br />

public class LoanBundler {<br />

public static Bundle makeLoanInfoBundle(double loanAmount,<br />

double annualInterestRateInPercent,<br />

long loanPeriodInMonths,<br />

String currencySymbol) {<br />

Bundle loanInfo = new Bundle();<br />

loanInfo.putDouble("loanAmount", loanAmount);<br />

loanInfo.putDouble("annualInterestRateInPercent",<br />

annualInterestRateInPercent);<br />

loanInfo.putLong("loanPeriodInMonths", loanPeriodInMonths);<br />

loanInfo.putString("currencySymbol", currencySymbol);<br />

return(loanInfo);<br />

}<br />

386<br />

jeudi 26 janvier 12


Java<br />

(LoanBundler.java, Continued)<br />

387<br />

jeudi 26 janvier 12<br />

public static Bundle makeRandomizedLoanInfoBundle() {<br />

Random randomizer = new Random();<br />

double loanAmount = 25000 * (1 + randomizer.nextInt(10));<br />

double interestRate = 0.25 * (1 + randomizer.nextInt(60));<br />

long loanPeriod = 12 * (1 + randomizer.nextInt(30));<br />

return(LoanBundler.makeLoanInfoBundle(loanAmount,<br />

interestRate, loanPeriod));<br />

}


Java (LoanCalculatorActivity.java)<br />

public class LoanCalculatorActivity extends Activity {<br />

private double mLoanAmount=100000,<br />

mAnnualInterestRateInPercent=5.0;<br />

private long mLoanPeriodInMonths=360; // 30 years<br />

private String mCurrencySymbol = "$";<br />

388<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.loan_payments);<br />

setInputsFromExtras();<br />

setInputsFromUri();<br />

calculateAndSetOutputValues();<br />

}


Java (LoanCalculatorActivity,<br />

Continued)<br />

389<br />

jeudi 26 janvier 12<br />

private void setInputsFromExtras() {<br />

Intent intent = getIntent();<br />

Bundle loanInfo = intent.getExtras();<br />

if (loanInfo != null) {<br />

double loanAmount = loanInfo.getDouble("loanAmount");<br />

double annualInterestRateInPercent =<br />

loanInfo.getDouble("annualInterestRateInPercent");<br />

long loanPeriodInMonths =<br />

loanInfo.getLong("loanPeriodInMonths");<br />

String currencySymbol =<br />

loanInfo.getString("currencySymbol");<br />

setInputs(loanAmount, annualInterestRateInPercent,<br />

loanPeriodInMonths, currencySymbol);<br />

}<br />

}


Java (LoanCalculatorActivity,<br />

Continued)<br />

390<br />

jeudi 26 janvier 12<br />

private void setInputs(double loanAmount,<br />

double annualInterestRateInPercent,<br />

long loanPeriodInMonths,<br />

String currencySymbol) {<br />

if (loanAmount > 0) {<br />

mLoanAmount = loanAmount;<br />

}<br />

if (annualInterestRateInPercent > 0) {<br />

mAnnualInterestRateInPercent =<br />

annualInterestRateInPercent;<br />

}<br />

if (loanPeriodInMonths > 0) {<br />

mLoanPeriodInMonths = loanPeriodInMonths;<br />

}<br />

if (currencySymbol != null) {<br />

mCurrencySymbol = currencySymbol;<br />

}<br />

}


Example: Results<br />

391<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• Tutorial: Intents and Intent Filters<br />

–http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/intents/<br />

intents-filters.html<br />

• JavaDoc: Intent<br />

–http://<strong>de</strong>veloper.android.com/reference/android/content/<br />

Intent.html<br />

• Chapters: Creating Intent Filters and<br />

Launching Activities and Sub-Activities<br />

–From The Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development<br />

• http://commonsware.com/Android/<br />

• Chapter: Intents and Services<br />

393<br />

jeudi 26 janvier 12<br />

–From Android in Action by Ableson et al


Summary<br />

• Java (original Activity)<br />

Intent activityIntent = new Intent(this, NewActivity.class);<br />

Bundle newActivityInfo = new Bundle();<br />

newActivityInfo.putBlah(…); // putDouble, putString, etc.<br />

activityIntent.putExtras(newActivityInfo);<br />

startActivity(activityIntent);<br />

• Java (new Activity)<br />

Intent intent = getIntent();<br />

Bundle info = intent.getExtras();<br />

if (info != null) { /* Retrieve vals with info.getBlah(...) */ }<br />

• XML (AndroidManifest.xml)<br />

<br />

<br />

<br />

<br />

394<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Intents, Intent Filters,<br />

and Invoking Activities:<br />

Part II: Using URI<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Part I<br />

–Invoking Activities by class name<br />

–Defining dimensions in res/values<br />

–Sending data via the “extras” Bundle<br />

• Part II<br />

–Invoking Activities with a URI<br />

–Sending data via parameters in the URI<br />

• Part III<br />

396<br />

jeudi 26 janvier 12<br />

–Invoking Activities with tabbed windows<br />

–Defining two-image icons in res/drawable


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary of Options<br />

• Invoke Activity by class name (Part I)<br />

–Exactly one Activity can match<br />

–New Activity must be in same project as original<br />

–Can send data via an “extras” Bundle<br />

• Invoke Activity by URI (Part II)<br />

–More than one Activity could match<br />

–New Activity need not be in the same project as original<br />

–Can send data via URI parameters or “extras” Bundle<br />

• Switch Activities via tabs (Part III)<br />

398<br />

jeudi 26 janvier 12<br />

–Can use class name or URI to specify Activity<br />

–New Activity must be in same project as original<br />

–Can send data via URI parameters or “extras” Bundle


jeudi 26 janvier 12<br />

Invoking Activities<br />

with a URI<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• I<strong>de</strong>a<br />

– Supply a URI that indirectly refers to new Activity. The new Activity registers<br />

as target for URIs of a certain form.<br />

• The originating Activity and the new Activity need not be in the same project<br />

• More than one Activity could match the URI.<br />

– If so, Android will ask you which one to use.<br />

• Syntax<br />

– Java (original Activity)<br />

400<br />

jeudi 26 janvier 12<br />

Uri uri = Uri.parse("foo://bar.example.com/baz");<br />

Intent intent = new Intent(Intent.ACTION_VIEW, uri);<br />

startActivity(activityIntent);<br />

– XML (AndroidManifest.xml)<br />

<br />

<br />

<br />

<br />


Registering to Handle URIs<br />

• Matching the URI itself<br />

–Register for a scheme and a host<br />

• Example URI<br />

– loan://coreservlets.com/calc<br />

• intent-filter entry<br />

– <br />

• Matching the data type<br />

–Register for a MIME type<br />

• Example URIs<br />

– content:// (referring to that MIME type)<br />

– file:// (referring to that MIME type)<br />

– anything:// (the Intent can call setType to specify MIME type)<br />

• intent-filter entry<br />

– <br />

– <br />

401<br />

jeudi 26 janvier 12


Pre<strong>de</strong>fined Action/URI<br />

Combinations<br />

402<br />

jeudi 26 janvier 12<br />

Action URI Meaning<br />

Intent.ACTION_CALL tel:phone_number Opens phone application and calls<br />

phone_number.<br />

Intent.ACTION_DIAL tel:phone_number Opens phone application and dials (but<br />

doesn’t call) phone_number.<br />

Intent.ACTION_DIAL voicemail: Opens phone application and dials (but<br />

doesn’t call) the voice mail number.<br />

Intent.ACTION_VIEW geo:lat,long Opens the maps application centered on<br />

(lat, long).<br />

Intent.ACTION_VIEW geo:0,0?q=address Opens the maps application centered on<br />

the specified address.<br />

Intent.ACTION_VIEW http://url<br />

https://url<br />

Intent.<br />

ACTION_WEB_SEARCH<br />

Opens the browser application to the<br />

specified address.<br />

plain_text Opens the browser application and uses<br />

Google search for given string.<br />

Table adapted from Section 4.1.5 of Android in Action by Ableson et al.


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Invoking Loan Calculator<br />

(Data in Extras Bundle)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example: Overview<br />

• Initial Activity<br />

–Has Button that, when pressed,<br />

invokes the loan calculator activity<br />

• Initial Activity uses URI to indirectly invoke loan calculator<br />

• Initial Activity is in different project than loan calculator<br />

• Data is sent via extras Bundle as in previous example<br />

• Approach<br />

404<br />

jeudi 26 janvier 12<br />

–Create Intent with Intent.ACTION_VIEW and URI of "loan://<br />

coreservlets.com/calc"<br />

–Create and attach Bundle as in previous example<br />

–Call startActivity<br />

–Put data entry for LoanCalculatorActivity in manifest<br />


XML: Layout File<br />

(res/layout/main.xml – 2 nd Proj.)<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

405<br />

jeudi 26 janvier 12<br />

Entries for input form and second<br />

button shown later.


XML: Manifest File<br />

Action Declaration (Loan Proj.)<br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

406<br />

jeudi 26 janvier 12


Java (IntentFilter2Activity.java)<br />

public class IntentFilter2Activity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

}<br />

407<br />

jeudi 26 janvier 12<br />

public void showLoanPayments1(View clickedButton) {<br />

Uri uri = Uri.parse("loan://coreservlets.com/calc");<br />

Intent intent = new Intent(Intent.ACTION_VIEW, uri);<br />

intent.putExtras<br />

(LoanBundler.makeRandomizedLoanInfoBundle());<br />

startActivity(intent);<br />

}<br />

...<br />

Co<strong>de</strong> for second button (that embeds data in the URI) shown later.


Java Co<strong>de</strong> Shown Earlier<br />

• LoanBundler<br />

–Makes a Bundle that stores the loan amount, interest rate, and<br />

loan period<br />

• LoanCalculatorActivity<br />

408<br />

jeudi 26 janvier 12<br />

–Calls getIntent().getExtras() and reads the data out of the<br />

resultant Bundle. Uses that for the initial values for the loan<br />

amount, interest rate, and loan period<br />

–Passes the values to PaymentInfo, which in turn uses<br />

LoanUtils to calculate monthly payment and total payments<br />

–Puts all five values (loan amount, interest rate, loan period,<br />

monthly payment, total payments) into TextViews


Example: Results<br />

409<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Sending Data via<br />

Parameters in the URI<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• I<strong>de</strong>a<br />

– Embed query parameters in the URI. These parameters will represent data<br />

to be used by the new Activity.<br />

• Syntax<br />

– Java (original Activity)<br />

411<br />

jeudi 26 janvier 12<br />

String address =<br />

"loan://coreservlets.com/calc?loanAmount=xxx&…";<br />

Uri uri = Uri.parse(address);<br />

Intent intent = new Intent(Intent.ACTION_VIEW, uri);<br />

startActivity(activityIntent);<br />

– Java (new Activity)<br />

Uri uri = getIntent().getData();<br />

String loanAmountString = uri.getQueryParameter("loanAmount");<br />

// Convert String to double<br />

...


Sending Data:<br />

Extras vs. URI Parameters<br />

• Extras Bundle<br />

–Pros<br />

• Can send data of different types.<br />

• No parsing required in Activity that receives the data.<br />

–Cons<br />

• More complex for originating Activity<br />

– Requires parsing in originating Activity if values come from EditText<br />

• URI parameters<br />

412<br />

jeudi 26 janvier 12<br />

–Pros<br />

• Simpler for originating Activity, especially if EditText used<br />

• More consistent with URI usage<br />

–Cons<br />

• Can send Strings only<br />

• Requires parsing in receiving Activity


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Invoking Loan Calculator<br />

(Data in URI Parameters)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example: Overview<br />

• Initial Activity<br />

–Has Button that, when pressed,<br />

invokes the loan calculator activity<br />

• Data is extracted from textfields (EditTexts) and embed<strong>de</strong>d in the<br />

URI that is used to invoke loan calculator<br />

• Approach<br />

414<br />

jeudi 26 janvier 12<br />

–Create Intent with Intent.ACTION_VIEW and URI of "loan://<br />

coreservlets.com/calc?data"<br />

• Data is<br />

"loanAmount=…&annualInterestRateInPercent=…&…"<br />

–Call startActivity<br />

–Put data entry for LoanCalculatorActivity in manifest<br />


XML: Layout File<br />

(res/layout/main.xml – 2 nd Proj.)<br />

<br />

<br />

...<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

415<br />

jeudi 26 janvier 12<br />

Entry for first button shown earlier. Entries for other textfields (EditTexts)<br />

similar to the one shown. Entry for button at the bottom just has<br />

android:onClick="showLoanPayments2".


XML: Strings File<br />

(res/values/strings.xml)<br />

<br />

<br />

Intent Filters and Activity Switching<br />

<br />

Loan Calculator: Monthly Payments<br />

<br />

Tabbed Windows<br />

Loan amount:&#160;&#160;<br />

Interest rate:&#160;&#160;<br />

Months:&#160;&#160;<br />

Monthly payment:&#160;&#160;<br />

Total payments:&#160;&#160;<br />

<br />

416<br />

jeudi 26 janvier 12<br />

The same prompts are also used in the output display.<br />

Note that &#160; represents a non-breaking space. Regular spaces are not preserved at the beginning and end of strings in Android<br />

resource files. Note also that &nbsp; is not legal here, since that is a character entity specific to HTML, not general in XML.


XML: Manifest File<br />

Action Declaration (Loan Proj.)<br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

417<br />

jeudi 26 janvier 12<br />

Unchanged from previous example.


Java (IntentFilter2Activity.java)<br />

public class IntentFilter2Activity extends Activity {<br />

...<br />

418<br />

jeudi 26 janvier 12<br />

public void showLoanPayments2(View clickedButton) {<br />

String address = makeLoanAddressFromEditTextInputs();<br />

Uri uri = Uri.parse(address);<br />

Intent intent = new Intent(Intent.ACTION_VIEW, uri);<br />

startActivity(intent);<br />

}<br />

Co<strong>de</strong> for onCreate and first button shown earlier.


Java<br />

(IntentFilter2Activity, Continued)<br />

private String makeLoanAddressFromEditTextInputs() {<br />

EditText loanAmountInput = (EditText)findViewById(R.id.loan_amount);<br />

Editable loanAmount = loanAmountInput.getText();<br />

String loanAmountParam =<br />

String.format("loanAmount=%s", loanAmount);<br />

EditText interestRateInput = (EditText)findViewById(R.id.interest_rate);<br />

Editable interestRate = interestRateInput.getText();<br />

String interestRateParam =<br />

String.format("annualInterestRateInPercent=%s", interestRate);<br />

EditText loanPeriodInput = (EditText)findViewById(R.id.loan_period);<br />

Editable loanPeriod = loanPeriodInput.getText();<br />

String loanPeriodParam =<br />

String.format("loanPeriodInMonths=%s", loanPeriod);<br />

String baseAddress = "loan://coreservlets.com/calc";<br />

String address =<br />

String.format("%s?%s&%s&%s", baseAddress, loanAmountParam,<br />

interestRateParam, loanPeriodParam);<br />

return(address);<br />

}<br />

419<br />

jeudi 26 janvier 12


Java (LoanCalculatorActivity.java)<br />

public class LoanCalculatorActivity extends Activity {<br />

private double mLoanAmount=100000,<br />

mAnnualInterestRateInPercent=5.0;<br />

private long mLoanPeriodInMonths=360; // 30 years<br />

private String mCurrencySymbol = "$";<br />

420<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.loan_payments);<br />

setInputsFromExtras();<br />

setInputsFromUri();<br />

calculateAndSetOutputValues();<br />

}


Java (LoanCalculatorActivity,<br />

Continued)<br />

421<br />

jeudi 26 janvier 12<br />

private void setInputsFromUri() {<br />

Uri uri = getIntent().getData();<br />

if (uri != null) {<br />

double loanAmount = getDoubleParam(uri, "loanAmount");<br />

double annualInterestRateInPercent =<br />

getDoubleParam(uri, "annualInterestRateInPercent");<br />

long loanPeriodInMonths =<br />

getLongParam(uri, "loanPeriodInMonths");<br />

String currencySymbol =<br />

uri.getQueryParameter("currencySymbol");<br />

setInputs(loanAmount, annualInterestRateInPercent,<br />

loanPeriodInMonths, currencySymbol);<br />

}<br />

}<br />

getQueryParameter is the builtin method of Uri. getDoubleParam and getLongParam (next sli<strong>de</strong>s) are<br />

methods of LoanCalculatorActivity that call getQueryParameter and then parse the resultant String.


Java (LoanCalculatorActivity,<br />

Continued)<br />

422<br />

jeudi 26 janvier 12<br />

private void setInputsFromUri() {<br />

Uri uri = getIntent().getData();<br />

if (uri != null) {<br />

double loanAmount = getDoubleParam(uri, "loanAmount");<br />

double annualInterestRateInPercent =<br />

getDoubleParam(uri, "annualInterestRateInPercent");<br />

long loanPeriodInMonths =<br />

getLongParam(uri, "loanPeriodInMonths");<br />

String currencySymbol =<br />

uri.getQueryParameter("currencySymbol");<br />

setInputs(loanAmount, annualInterestRateInPercent,<br />

loanPeriodInMonths, currencySymbol);<br />

}<br />

}


Java (LoanCalculatorActivity,<br />

Continued)<br />

423<br />

jeudi 26 janvier 12<br />

private double getDoubleParam(Uri uri, String queryParamName) {<br />

String rawValue = uri.getQueryParameter(queryParamName);<br />

double value = 0.0;<br />

try {<br />

value = Double.parseDouble(rawValue);<br />

} catch(Exception e) { } // NumberFormatEx or NullPointerEx<br />

return(value);<br />

}<br />

private long getLongParam(Uri uri, String queryParamName) {<br />

String rawValue = uri.getQueryParameter(queryParamName);<br />

long value = 0;<br />

try {<br />

value = Long.parseLong(rawValue);<br />

} catch(Exception e) { } // NFE or NPE<br />

return(value);<br />

}


Example: Results<br />

424<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• Java (original Activity)<br />

String address =<br />

"loan://coreservlets.com/calc?loanAmount=xxx&…";<br />

Uri uri = Uri.parse(address);<br />

Intent intent = new Intent(Intent.ACTION_VIEW, uri);<br />

startActivity(activityIntent);<br />

• Java (new Activity – can be different project)<br />

Uri uri = getIntent().getData();<br />

String loanAmountString = uri.getQueryParameter("loanAmount");<br />

// Convert String to double, handle bad data<br />

...<br />

• XML (AndroidManifest.xml)<br />

<br />

<br />

<br />

<br />

<br />

426<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Intents, Intent Filters,<br />

and Invoking Activities:<br />

Part III: Using Tabs<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Part I<br />

–Invoking Activities by class name<br />

–Defining dimensions in res/values<br />

–Sending data via the “extras” Bundle<br />

• Part II<br />

–Invoking Activities with a URI<br />

–Sending data via parameters in the URI<br />

• Part III<br />

428<br />

jeudi 26 janvier 12<br />

–Invoking Activities with tabbed windows<br />

–Defining two-image icons in res/drawable


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary of Options<br />

• Invoke Activity by class name (Part I)<br />

–Exactly one Activity can match<br />

–New Activity must be in same project as original<br />

–Can send data via an “extras” Bundle<br />

• Invoke Activity by URI (Part II)<br />

–More than one Activity could match<br />

–New Activity need not be in the same project as original<br />

–Can send data via URI parameters or “extras” Bundle<br />

• Switch Activities via tabs (Part III)<br />

430<br />

jeudi 26 janvier 12<br />

–Can use class name or URI to specify Activity<br />

–New Activity must be in same project as original<br />

–Can send data via URI parameters or “extras” Bundle


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Invoking Activities with<br />

Tabbed Windows<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• I<strong>de</strong>a<br />

– Make tabbed windows. Each tab invokes a different Activity, or<br />

an Activity with different data.<br />

• Can use either specific-class approach or URI approach<br />

• Can send data either with an extras Bundle or in URI<br />

• Tab window Activity and new Activities must be in same project<br />

– Due to security reasons<br />

• Syntax<br />

– Java<br />

• Extends TabActivity. Uses TabHost and TabSpec<br />

432<br />

jeudi 26 janvier 12<br />

– Details on next sli<strong>de</strong><br />

– XML (AndroidManifest.xml)<br />

• Same as shown earlier


Using TabActivity: Outline<br />

public class SomeActivity extends TabActivity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

Resources resources = getResources();<br />

TabHost host = getTabHost();<br />

Intent intent1= ...;<br />

Drawable tabIcon =<br />

resources.getDrawable(R.drawable.icon_name);<br />

TabSpec tab1Spec =<br />

host.newTabSpec("Tab One")<br />

.setIndicator("Some Text", tabIcon)<br />

.setContent(intent1);<br />

host.addTab(tab1Spec);<br />

// Repeat for other tabs<br />

}<br />

}<br />

433<br />

jeudi 26 janvier 12<br />

Note that the setter methods for TabSpec return the TabSpec so that you can do chained assignments.<br />

Note also that there is no layout file when using this approach.


Defining Tab Icons<br />

• I<strong>de</strong>a<br />

–Although it is legal to call setIndicator(someString), the<br />

resultant tab looks bad because of blank space at top. So,<br />

more common to do setIndicator(someString, someIcon).<br />

• You can also do setIndicator(someView) for fancy tabs<br />

• Icon option 1<br />

–Use a single image for the icon<br />

• Same image used when the tab is or is not selected<br />

• Icon option 2<br />

434<br />

jeudi 26 janvier 12<br />

–Use 2 similar but differently colored images for the icon<br />

• One for when selected, one for when not


Option 1: A Single Image<br />

• Pros<br />

–Simpler<br />

–Text color and background color of the tab already change on<br />

selection, so not confusing if icon stays same.<br />

• Cons<br />

–Doesn’t look quite as good as with two images<br />

• Approach<br />

435<br />

jeudi 26 janvier 12<br />

–Put image file in res/drawable/some_icon.png<br />

–Refer to image with<br />

• Drawable tabIcon =<br />

resources.getDrawable(R.drawable.some_icon);<br />

–Put icon in tab label with<br />

• tabSpec.setIndicator("Some Text", tabIcon);


Option 2: Two Images<br />

(Normal and Selected)<br />

• Pros<br />

– Looks better<br />

• Cons<br />

– More work<br />

• Approach<br />

– Put image files in<br />

• res/drawable/some_icon_normal.png and<br />

• res/drawable/some_icon_selected.png<br />

– Make XML file (next page)<br />

• res/drawable/some_icon.xml<br />

– Refer to XML file with<br />

• Drawable tabIcon =<br />

resources.getDrawable(R.drawable.some_icon);<br />

– Put icon in tab label with<br />

• tabSpec.setIndicator("Some Text", tabIcon);<br />

436<br />

jeudi 26 janvier 12


XML Co<strong>de</strong> for Dual-Image Icon<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

437<br />

jeudi 26 janvier 12<br />

The file names of the two images are arbitrary. They need not end in _selected and _normal, although this<br />

can be a useful convention so that you know what the images are for.


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Invoking Loan Calculator<br />

(Each Tab Sends<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Example: Overview<br />

• Initial Activity<br />

–Has tabs that, when pressed, invoke the<br />

loan calculator with different data<br />

• Activity specified either with class name or URI<br />

– But either way, initial Activity must be in same project as new one<br />

• Data sent via either in extras Bundle or in URI<br />

• Approach<br />

439<br />

jeudi 26 janvier 12<br />

–Intents and data created in same way as before<br />

–Intent associated with tab via tabHost.setContent<br />

–Put entry for LoanCalculatorActivity in manifest<br />

• Same as shown previously


XML: Icon File<br />

(res/drawable/calculator.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

440<br />

jeudi 26 janvier 12


XML: Manifest File<br />

Action Declaration<br />

<br />

<br />

<br />

<br />

... <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

441<br />

jeudi 26 janvier 12<br />

Unchanged from previous examples.


Java<br />

(TabbedActivity: Tab 1)<br />

public class TabbedActivity extends TabActivity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

Resources resources = getResources();<br />

TabHost host = getTabHost();<br />

Intent intent1 =<br />

new Intent(this, LoanCalculatorActivity.class);<br />

Bundle loanBundle1 =<br />

LoanBundler.makeLoanInfoBundle(100000, 7.5, 120);<br />

intent1.putExtras(loanBundle1);<br />

Drawable tabIcon =<br />

resources.getDrawable(R.drawable.calculator);<br />

TabSpec tab1Spec = host.newTabSpec("Tab One")<br />

.setIndicator("10 Year", tabIcon)<br />

.setContent(intent1);<br />

host.addTab(tab1Spec);<br />

442<br />

jeudi 26 janvier 12<br />

This first tab uses an Intent that specifies the Activity by class name.<br />

It sends data via an extras Bundle. Remin<strong>de</strong>r: there is no layout file when using TabActivity.


Java<br />

(TabbedActivity: Tab 2)<br />

443<br />

jeudi 26 janvier 12<br />

Uri uriTwentyYear =<br />

Uri.parse("loan://coreservlets.com/calc");<br />

Intent intent2 =<br />

new Intent(Intent.ACTION_VIEW, uriTwentyYear);<br />

Bundle loanBundle2 =<br />

LoanBundler.makeLoanInfoBundle(100000, 7.5, 240);<br />

intent2.putExtras(loanBundle2);<br />

tabIcon = resources.getDrawable(R.drawable.calculator);<br />

TabSpec tab2Spec = host.newTabSpec("Tab Two")<br />

.setIndicator("20 Year", tabIcon)<br />

.setContent(intent2);<br />

host.addTab(tab2Spec);<br />

This second tab uses an Intent that specifies the Activity with a URI.<br />

It sends data via an extras Bundle.


Java<br />

(TabbedActivity: Tab 3)<br />

444<br />

jeudi 26 janvier 12<br />

String baseAddress = "loan://coreservlets.com/calc";<br />

String address =<br />

String.format("%s?%s&%s&%s",<br />

baseAddress,<br />

"loanAmount=100000",<br />

"annualInterestRateInPercent=7.5",<br />

"loanPeriodInMonths=360");<br />

Uri uriThirtyYear = Uri.parse(address);<br />

Intent intent3 =<br />

new Intent(Intent.ACTION_VIEW, uriThirtyYear);<br />

tabIcon = resources.getDrawable(R.drawable.calculator);<br />

TabSpec tab3Spec = host.newTabSpec("Tab Three")<br />

.setIndicator("30 Year", tabIcon)<br />

.setContent(intent3);<br />

host.addTab(tab3Spec);<br />

This second tab uses an Intent that specifies the Activity with a URI.<br />

It sends data via parameters embed<strong>de</strong>d in the URI.


Example: Results<br />

445<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary<br />

• Java (extends TabActivity)<br />

TabHost host = getTabHost();<br />

Intent intent1= ...; // Refers to Activity in same project<br />

Drawable tabIcon = resources.getDrawable(R.drawable.some_icon);<br />

TabSpec tab1Spec = host.newTabSpec("Tab One")<br />

.setIndicator("Some Text", tabIcon)<br />

.setContent(intent1);<br />

host.addTab(tab1Spec);<br />

// Repeat for other tabs<br />

• Icon (res/drawable/some_icon.xml)<br />

<br />

<br />

<br />

<br />

<br />

447<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Localization and Resources<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Localization overview<br />

• Localization options<br />

–Language<br />

–Country/region language variations<br />

–Screen orientation<br />

–Display resolution<br />

–Others<br />

• Configuration qualifier prece<strong>de</strong>nce<br />

449<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Big I<strong>de</strong>a<br />

• Good news<br />

– Android’s use of resource files (res/layout/main.xml, res/values/<br />

strings.xml, etc.) simplifies GUI <strong>de</strong>velopment<br />

• Bad news<br />

– Descriptions in English won’t work in German<br />

– What fits in portrait orientation won’t fit in landscape<br />

– Images for high-<strong>de</strong>nsity screens are too large for low-<strong>de</strong>nsity ones<br />

• Solution<br />

– Make multiple layout and resource files<br />

• For different languages, orientations, etc.<br />

– Have Android automatically switch among or combine them<br />

• Notes<br />

– Localization sometimes called L10N (L, 10 letters, N)<br />

– Also sometimes called Internationalization (I18N)<br />

451<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Process<br />

• Make qualified versions of resource files<br />

– Find the settings that affect your application<br />

• Language, orientation, touchscreen type, dock mo<strong>de</strong>, etc.<br />

– Find qualifier names that correspond to each setting<br />

• Language: en, en-rUS, es, es-rMX, etc.<br />

• Screen orientation: port, land<br />

• Display <strong>de</strong>nsity: xhdpi, hdpi, mdpi, ldpi<br />

• Dock mo<strong>de</strong>: car, <strong>de</strong>sk<br />

• Etc.<br />

– Append qualifier names to fol<strong>de</strong>r names<br />

• res/values/strings.xml, res/values-es/strings.xml,<br />

res/values-es-rMX/main.xml<br />

• res/layout/main.xml, res/layout-land/main.xml<br />

• Load the resource normally<br />

– R.string.title, R.layout.main, etc.<br />

– Android will switch among layout files automatically<br />

– Android will combine values files automatically<br />

• More specific values will replace earlier ones<br />

452


jeudi 26 janvier 12<br />

Language<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Overview<br />

• I<strong>de</strong>a<br />

–Change the display based on the user’s language<br />

• Resources that typically change<br />

–Strings (in res/values, e.g., in res/values/strings.xml)<br />

–Images (in res/drawable – image file or XML file)<br />

–Colors (in res/values, e.g., in res/values/colors.xml)<br />

–Audio and vi<strong>de</strong>o (in res/raw)<br />

–Dimensions, arrays, and styles (in res/values, e.g., …/<br />

dimens.xml, …/arrays.xml, …/styles.xml)<br />

• Resources that do not usually change<br />

454<br />

jeudi 26 janvier 12<br />

–Layout files (in res/layout)<br />

• Changing layout based on language makes for hard-to-maintain<br />

apps. See best-practices sli<strong>de</strong>.


Steps<br />

• Make multiple fol<strong>de</strong>rs with language co<strong>de</strong>s<br />

– res/values, res/values-es, res/values-ja, etc.<br />

• Language co<strong>de</strong>s are specified by ISO 639-1<br />

– http://en.wikipedia.org/wiki/ISO_639-1<br />

• Define all strings in <strong>de</strong>fault fol<strong>de</strong>r<br />

– In res/values, <strong>de</strong>fine all names<br />

• Use the most common language<br />

– E.g., res/values/strings.xml (or other name in res/values)<br />

Apple<br />

Welcome!<br />

• Use similar approach for colors, images, etc.<br />

– Use res/values/ for all colors, dimensions, arrays, etc.<br />

– Use res/drawable for all image files<br />

– Use res/raw for all audio and vi<strong>de</strong>o files<br />

455<br />

jeudi 26 janvier 12


Steps (Continued)<br />

• In XML, refer to base string name<br />

– someAttribute="@string/company_name"<br />

– someAttribute="@ string/welcome_message"<br />

• No reference to fol<strong>de</strong>r or language.<br />

• Android will provi<strong>de</strong> the proper version automatically. It first loads values<br />

from res/values/strings.xml, then loads values from res/values-es/<br />

strings.xml. Any names in second file that are common to first file are<br />

replaced.<br />

• In Java, refer to base string name<br />

– getString(R.string.company_name)<br />

– getString(R.string.welcome_message)<br />

• No reference to fol<strong>de</strong>r or language. Same process as above.<br />

• Use similar approach for other resources<br />

– XML: @drawable/flag, @color/<strong>de</strong>fault_foreground, etc.<br />

– Java: R.drawable.flag, R.color.<strong>de</strong>fault_foreground, etc.<br />

457<br />

jeudi 26 janvier 12


How User Changes Device<br />

Language<br />

• On phone (or other physical Android <strong>de</strong>vice)<br />

458<br />

jeudi 26 janvier 12<br />

–Go to home screen, press Menu button, select Settings<br />

• (Most people also have the Settings app on <strong>de</strong>sktop)<br />

–Choose Language and Keyboard<br />

–Choose Select locale at the top<br />

• Most phones will have a very<br />

limited number of choices,<br />

based on what <strong>de</strong>vice<br />

manufacturer supports<br />

– Android cannot (easily) use<br />

localization within apps unless<br />

entire OS supports that language.<br />

Major Android failing.<br />

– But, see upcoming sli<strong>de</strong>s on<br />

programmatic Locale changes.


How User Changes Device<br />

Language<br />

• On emulator<br />

459<br />

jeudi 26 janvier 12<br />

–Option 1: use same approach as<br />

above<br />

• You will have a limited number of<br />

choices, based on what was<br />

installed in your Android SDK image.<br />

But, it will almost certainly be a<br />

bigger set than the real phone.<br />

–Option 2: use Custom Locale app<br />

on app screen<br />

• If Locale you want is not there, add it<br />

(even regional ones)<br />

• Long-press the Locale to choose it<br />

To go to app screen, go to home<br />

screen and press this.


Example: The Android Resort<br />

• I<strong>de</strong>a<br />

–Make an app that advertises a luxury resort where visitors can<br />

sit insi<strong>de</strong> all day and play with their smart phones<br />

• Approach<br />

460<br />

jeudi 26 janvier 12<br />

–res/values/strings.xml <strong>de</strong>fines<br />

• resort_name, welcome, our, pool, reserve, confirmed<br />

–res/values-es/strings.xml <strong>de</strong>fines<br />

• welcome, our, pool, reserve, confirmed<br />

– Does not re<strong>de</strong>fine resort_name<br />

–Also uses dimensions, colors, images, and layout files<br />

• But these do not change based on language, so localized<br />

versions are not shown until a later example


Strings File: English/Other<br />

(res/values/strings.xml)<br />

<br />

<br />

AndroidResort.com<br />

Welcome to&#160;<br />

Our&#160;<br />

swimming pool<br />

Reserve Now!<br />

Registration Confirmed<br />

<br />

461<br />

jeudi 26 janvier 12<br />

Remin<strong>de</strong>r from intents lecture: &#160; is a non-breaking space.<br />

Android does not preserve whitespace at the beginning and end of<br />

strings in resource files.


Strings File: Spanish<br />

(res/values-es/strings.xml)<br />

<br />

<br />

Bienvenido a&#160;<br />

Nuestra&#160;<br />

piscina<br />

¡Reserva Ahora!<br />

Registro Confirmado<br />

<br />

462<br />

jeudi 26 janvier 12<br />

Note that there is not an entry for resort_name.<br />

The value from res/values/strings.xml carries over.


Layout File res/layout/main.xml<br />

(No Language-Based Versions)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

463<br />

jeudi 26 janvier 12


Manifest File<br />

(No Language-Based Versions)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

464<br />

jeudi 26 janvier 12


Java Co<strong>de</strong><br />

public class AndroidResortActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

}<br />

}<br />

465<br />

jeudi 26 janvier 12<br />

public void confirmRegistration(View clickedButton) {<br />

String message = getString(R.string.confirmed);<br />

showToast(message);<br />

}<br />

private void showToast(String text) {<br />

Toast.makeText(this, text, Toast.LENGTH_LONG).show();<br />

}


Project Layout<br />

466<br />

jeudi 26 janvier 12<br />

Uses the named strings via getString(R.string.string_name). Uses same<br />

syntax regardless of whether the string came from values/strings.xml or<br />

was overrid<strong>de</strong>n in values-es/strings.xml<br />

Uses the named strings via @string/string_name. Uses same syntax regardless of<br />

whether the string came from values/strings.xml or was overrid<strong>de</strong>n in values-es/<br />

strings.xml<br />

Defines all named strings. Applies to all languages except Spanish, and even one of<br />

the names applies to Spanish, since the Spanish version does not overri<strong>de</strong><br />

resort_name.<br />

Overri<strong>de</strong>s the named strings that are different in Spanish.


Results: English<br />

467<br />

jeudi 26 janvier 12<br />

res/values/strings.xml<br />

• resort_name<br />

• welcome<br />

• our<br />

• pool<br />

• reserve<br />

• confirmed<br />

This is the result not just for English, but for any language other than Spanish.


Results: Spanish<br />

468<br />

jeudi 26 janvier 12<br />

res/values/strings.xml<br />

• resort_name<br />

res/values-es/strings.xml<br />

• welcome<br />

• our<br />

• pool<br />

• reserve<br />

• confirmed


Best Practices<br />

• Provi<strong>de</strong> unlocalized <strong>de</strong>faults for all values<br />

–So if Locale is unexpected, it displays in <strong>de</strong>fault language<br />

• E.g., if English is main language, use res/values, not res/valuesen.<br />

Also, test your app in unsupported Locale.<br />

• Use graphical layout editor for testing<br />

–For layout file, it lets you interactively change language,<br />

screen orientation, display resolution, and more<br />

• Avoid changing layouts based on language<br />

469<br />

jeudi 26 janvier 12<br />

–Might be necessary in some cases (e.g., US English asks for<br />

given name first and family name second, whereas Indian<br />

English asks for them in opposite or<strong>de</strong>r). However, makes for<br />

hard-to-maintain co<strong>de</strong>.<br />

• Consi<strong>de</strong>r putting the logic in Java co<strong>de</strong> instead


Graphical Layout Editor in<br />

Eclipse (Editing main.xml)<br />

470<br />

jeudi 26 janvier 12<br />

Changing display resolution<br />

Changing screen orientation<br />

Changing language (Eclipse will list all languages your<br />

app supports, based on your fol<strong>de</strong>r names)<br />

Also lets you change dock<br />

mo<strong>de</strong>, day/night mo<strong>de</strong>, style<br />

(theme), and Android version.


Changing the Language<br />

Programmatically<br />

• Letting user change Locale<br />

– Pros<br />

• Expected/recommen<strong>de</strong>d Android approach<br />

• All localization works gracefully<br />

– Cons<br />

• Can only use languages that <strong>de</strong>vice manufacturer supports for the<br />

entire OS<br />

• Requires user to take several steps they might not know<br />

• Changing Locale in your co<strong>de</strong><br />

– Pros<br />

• Can use any language you want<br />

• Can let user set language in app with simple button<br />

– Cons<br />

• Not expected/recommen<strong>de</strong>d approach<br />

• Settings do not live across app restarts (including rotations!), so<br />

requires you to remember and reuse it.<br />

471<br />

jeudi 26 janvier 12


Changing the Language<br />

Programmatically: Co<strong>de</strong><br />

• Steps<br />

Locale locale = new Locale("es"); // Language co<strong>de</strong><br />

Locale.setDefault(locale);<br />

Configuration config = new Configuration();<br />

config.locale = locale;<br />

context.getResources().updateConfiguration(config,<br />

–context above is reference to the main Activity<br />

• More <strong>de</strong>tails<br />

472<br />

jeudi 26 janvier 12<br />

–http://adrianvintu.com/blogengine/post/<br />

Force-Locale-on-Android.aspx<br />

null);


jeudi 26 janvier 12<br />

Region<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


I<strong>de</strong>a<br />

• Values can be specific to region<br />

– Not only to general language<br />

– Examples<br />

• Words<br />

– US English: garbage truck<br />

– Australian English: rubbish lorry<br />

• Images<br />

– Flag of the country<br />

• Colors<br />

– Colors matching flag<br />

• Audio files<br />

– US English: Yankee Doodle<br />

– Australian English: Waltzing Matilda<br />

• Good news<br />

– Android lets you <strong>de</strong>fine res/values-en-au, etc.<br />

• Bad news<br />

– Most phones support few or no regional settings<br />

474<br />

jeudi 26 janvier 12


Steps<br />

• Put <strong>de</strong>fault values in res/values<br />

–As before. List all the names<br />

• Put general lang. values in res/values-xx<br />

–Where xx is ISO 639-1 language co<strong>de</strong> as before<br />

–List only the names that change from the <strong>de</strong>fault language<br />

• Put regional values in res/values-xx-rYY<br />

–Where xx is the language co<strong>de</strong> and YY is the country co<strong>de</strong><br />

(case insensitive). Note the “r” for “region”.<br />

• Co<strong>de</strong>s are specified by ISO 3166-1<br />

– http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3<br />

–List only the names that change from the base language<br />

• Process<br />

475<br />

jeudi 26 janvier 12<br />

–Android will load from most general to most specific


Example: The Android Resort<br />

• I<strong>de</strong>a<br />

–Add support for Mexican Spanish, which uses “alberca”<br />

instead of “piscina” for “swimming pool”.<br />

• Approach<br />

476<br />

jeudi 26 janvier 12<br />

–res/values/strings.xml <strong>de</strong>fines<br />

• resort_name, welcome, our, pool, reserve, confirmed<br />

–res/values-es/strings.xml <strong>de</strong>fines<br />

• welcome, our, pool, reserve, confirmed<br />

–res/values-es-rMX/strings.xml <strong>de</strong>fines<br />

• pool


Strings File: English/Other<br />

(res/values/strings.xml)<br />

<br />

<br />

AndroidResort.com<br />

Welcome to&#160;<br />

Our&#160;<br />

swimming pool<br />

Reserve Now!<br />

Registration Confirmed<br />

<br />

477<br />

jeudi 26 janvier 12


Strings File: General Spanish<br />

(res/values-es/strings.xml)<br />

<br />

<br />

Bienvenido a&#160;<br />

Nuestra&#160;<br />

piscina<br />

¡Reserva Ahora!<br />

Registro Confirmado<br />

<br />

478<br />

jeudi 26 janvier 12


Strings File: Mexican Spanish<br />

(res/values-es-rMX/strings.xml)<br />

<br />

<br />

alberca<br />

<br />

479<br />

jeudi 26 janvier 12


Project Layout<br />

480<br />

jeudi 26 janvier 12<br />

Uses the named strings via getString(R.string.string_name). Uses same<br />

syntax regardless of whether the string came from values/strings.xml or<br />

was overrid<strong>de</strong>n in values-es/strings.xml or values-es-rMX/strings.xml.<br />

Uses the named strings via @string/string_name. Uses same syntax regardless of<br />

whether the string came from values/strings.xml or was overrid<strong>de</strong>n in values-es/<br />

strings.xml or values-es-rMX/strings.xml.<br />

Defines all named strings. Applies to all languages except Spanish, and even one of<br />

the names applies to Spanish, since the Spanish versions do not overri<strong>de</strong><br />

resort_name.<br />

Overri<strong>de</strong>s the named strings that are different in Spanish.<br />

Overri<strong>de</strong>s the named strings that are different in Mexican Spanish from in<br />

general Spanish.


Results<br />

481<br />

jeudi 26 janvier 12<br />

Any language other than Spanish General Spanish Mexican Spanish


jeudi 26 janvier 12<br />

Screen Orientation<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Overview<br />

• I<strong>de</strong>a<br />

–Change the display based on whether the <strong>de</strong>vice is being held<br />

in portrait or landscape mo<strong>de</strong>.<br />

• Resources that typically change<br />

–Layout files (in res/layout)<br />

–Images (in res/drawable – image file or XML file)<br />

–Dimensions (in res/values, e.g., …/dimens.xml)<br />

–Vi<strong>de</strong>o (in res/raw)<br />

• Resources that do not usually change<br />

483<br />

jeudi 26 janvier 12<br />

–Strings (in res/values, e.g., in res/values/strings.xml)<br />

–Colors (in res/values, e.g., in res/values/colors.xml)<br />

–Audio (in res/raw)


Steps<br />

• Make two fol<strong>de</strong>rs: <strong>de</strong>fault and landscape<br />

–res/layout and res/layout-land<br />

• You can do layout-port, but more common to use <strong>de</strong>fault<br />

• Define different layouts (of same name) in<br />

each<br />

–For portrait mo<strong>de</strong><br />

• res/layout/main.xml (and maybe other names)<br />

–For landscape mo<strong>de</strong><br />

• res/layout-land/main.xml (and maybe other names)<br />

• Use similar approach for dimensions, images,<br />

etc.<br />

–Use res/values/ and res/drawable for portrait mo<strong>de</strong> and for<br />

things that are the same in both orientations.<br />

484<br />

jeudi 26 janvier 12<br />

–Overri<strong>de</strong> in res/values-land and res/drawable-land


Steps (Continued)<br />

• In XML, refer to base dimensions or images<br />

–textSize="@dimen/heading_size"<br />

–src="@ drawable/some_image"<br />

• No reference to fol<strong>de</strong>r or orientation. Android handles.<br />

• In Java, refer to base layout name<br />

485<br />

jeudi 26 janvier 12<br />

–setContentView(R.layout.main)<br />

• Android will provi<strong>de</strong> the proper version automatically. For layout<br />

files, only one version applies. For values files, names are<br />

combined as before, with later values overriding earlier values of<br />

the same name.


Prece<strong>de</strong>nce of Fol<strong>de</strong>r Names<br />

• I<strong>de</strong>a<br />

– Many fol<strong>de</strong>rs with a single qualifier could apply (values, values-es,<br />

values-land, etc.).<br />

– You can also combine the names (e.g., values-es-land)<br />

• Language must be first, so use values-es-land, not values-land-es<br />

– So, which entries win?<br />

• Layout files and drawable files<br />

– Only one file applies. Language entries win over screen orientation, so if<br />

there is layout-es and layout-land, and you are in both Spanish and<br />

landscape, layout-es wins<br />

• But, remember advice to avoid language-based layouts<br />

• Values files<br />

– Many files may apply. They are loa<strong>de</strong>d from least specific to most<br />

specific, and later values overri<strong>de</strong> earlier ones of the same name.<br />

Language is more specific than orientation.<br />

486<br />

jeudi 26 janvier 12


How User Changes Screen<br />

Orientation<br />

• On phone (or other Android <strong>de</strong>vice)<br />

–Physically rotate the <strong>de</strong>vice<br />

• On emulator<br />

–Hit Control-F12 or<br />

–Hit 9 on the number keypad (Num Lock must be off)<br />

• In visual layout editor in Eclipse<br />

487<br />

jeudi 26 janvier 12<br />

–Choose Portrait or Landscape from the second combobox<br />

above the display


Example: The Android Resort<br />

• I<strong>de</strong>a<br />

–Use two layouts: one for portrait and one for landscape<br />

–Change font sizes for heading <strong>de</strong>pending on orientation<br />

–Keep support for English and Spanish<br />

• Approach<br />

488<br />

jeudi 26 janvier 12<br />

–res/layout/main.xml <strong>de</strong>fines layout for portrait mo<strong>de</strong><br />

–res/layout-land/main.xml <strong>de</strong>fines layout for landscape<br />

–res/values/dimens.xml <strong>de</strong>fines font size for portrait<br />

–res/values-land/dimens.xml <strong>de</strong>fines size for landscape<br />

–res/values, res/values-es, and res/values-es-rMX <strong>de</strong>fine strings<br />

and colors as shown previously


Layout File: Portrait Mo<strong>de</strong><br />

(res/layout/main.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

489<br />

jeudi 26 janvier 12


Layout File: Landscape Mo<strong>de</strong><br />

(res/layout-land/main.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

490<br />

jeudi 26 janvier 12<br />

Recall that horizontal is the <strong>de</strong>fault orientation.


Dimensions File: Portrait Mo<strong>de</strong><br />

(res/values/dimens.xml)<br />

<br />

<br />

32dp<br />

22dp<br />

<br />

491<br />

jeudi 26 janvier 12


Dimensions File: Landscape<br />

(res/values-land/dimens.xml)<br />

<br />

<br />

26dp<br />

24dp<br />

<br />

492<br />

jeudi 26 janvier 12


Project Layout<br />

493<br />

jeudi 26 janvier 12<br />

Defines the layout for portrait mo<strong>de</strong>. Uses @dimen/heading_size and @dimen/<br />

body_size, which are <strong>de</strong>fined in res/values/dimens.xml<br />

Defines the layout for landscape mo<strong>de</strong>. Uses @dimen/heading_size and @dimen/<br />

body_size, which are <strong>de</strong>fined in res/values-land/dimens.xml<br />

Defines heading_size and body_size for use in portrait mo<strong>de</strong>.<br />

Defines heading_size and body_size for use in landscape mo<strong>de</strong>.


Results: English<br />

(Really Non-Spanish)<br />

494<br />

jeudi 26 janvier 12


Results: General Spanish<br />

495<br />

jeudi 26 janvier 12


Results: Mexican Spanish<br />

496<br />

jeudi 26 janvier 12


Preventing Screen Rotations<br />

• Issue<br />

–Screen rotations usually require a new layout<br />

–They also cause the app to be shutdown and restarted<br />

• Handling this will be discussed in the next lecture<br />

• Problem<br />

–What if you do not have landscape layout?<br />

–Or have not yet handled shutdown and restart?<br />

• Solution<br />

497<br />

jeudi 26 janvier 12<br />

–Put an entry in AndroidManifest.xml saying that app runs<br />

only in portrait mo<strong>de</strong> (or only in landscape mo<strong>de</strong>)<br />


Example: Screen from Widgets<br />

Lecture (Manifest File)<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

498<br />

jeudi 26 janvier 12


Example: Results<br />

(in Landscape Mo<strong>de</strong>)<br />

499<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Display Resolution<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Overview<br />

• I<strong>de</strong>a<br />

–Change images based on the resolution of the display<br />

• Resources that typically change<br />

–Images (in res/drawable – image file or XML file)<br />

–Vi<strong>de</strong>o (in res/raw)<br />

• Resources that do not usually change<br />

501<br />

jeudi 26 janvier 12<br />

–Dimensions<br />

• If you use xxdp, then it will scale to screen resolution<br />

– There are also small, normal, large, and xlarge qualifiers for screen size. Even<br />

with xxdp, you might want to adapt to those<br />

• But if you use yypx or zzin or aamm, then you need to change<br />

the dimensions to match the resolution<br />

–Layout files, strings, colors, audio, etc.


Common Approaches<br />

• Alternative 1: Default plus two others<br />

– drawable<br />

• Put images for high-res and extra-high-res (dots-per-inch) here<br />

– drawable-mdpi<br />

• Put images for medium-res (dots-per-inch) here<br />

– drawable-ldpi<br />

• Put images for low-res (dots-per-inch) here<br />

• Alternative 2: Three res-specific fol<strong>de</strong>rs<br />

– drawable-hdpi<br />

• Put images for high-res and extra-high-res (dots-per-inch) here<br />

– drawable-mdpi<br />

• Put images for medium-res (dots-per-inch) here<br />

– drawable-ldpi<br />

• Put images for low-res (dots-per-inch) here<br />

502<br />

jeudi 26 janvier 12


Meanings of Resolution Qualifiers<br />

• xhdpi (extra-high dpi)<br />

–320 dots per inch<br />

–But, Android uses best match, so if you put images in<br />

drawable-hdpi and it is extra-high, images are still used.<br />

• Another common option is to use a single set of images for both<br />

extra-high and high, and put them in drawable<br />

• hdpi (high dpi)<br />

–240 dots per inch<br />

• mdpi (medium dpi)<br />

–160 dots per inch<br />

• ldpi (low dpi)<br />

503<br />

jeudi 26 janvier 12<br />

–120 dots per inch


Best Practices<br />

• For small icons (e.g., for ImageButton)<br />

–Use multiple versions<br />

–Realize that the size will be slightly different on different<br />

displays, so leave enough room to compensate<br />

• For larger images (e.g., for ImageView)<br />

504<br />

jeudi 26 janvier 12<br />

–Use multiple versions<br />

–Scale the image if it is larger than the available space<br />


Prece<strong>de</strong>nce of Fol<strong>de</strong>r Names<br />

• I<strong>de</strong>a<br />

– You may have many fol<strong>de</strong>rs that apply<br />

• drawable, drawable-mdpi, drawable-es, drawable-es-land-hdpi…<br />

– So, which entries win?<br />

• Prece<strong>de</strong>nce rules<br />

505<br />

jeudi 26 janvier 12<br />

– Language is highest prece<strong>de</strong>nce<br />

• drawable-es wins over drawable-land or drawable-mdpi<br />

– Orientation is second highest<br />

• drawable-land wins over drawable-hdpi<br />

– Density is last (of these three)<br />

• But, try to chain the qualifiers so there is never a conflict.<br />

– drawable-land-hdpi, drawable-land-mdpi, etc.


Example: The Android Resort<br />

• I<strong>de</strong>a<br />

–Have three versions of the swimming pool image: for low,<br />

medium, and high (or extra-high) resolution <strong>de</strong>vices<br />

• Approach<br />

506<br />

jeudi 26 janvier 12<br />

–drawable/android_resort_pool.jpg<br />

• For high-res or extra-high-res <strong>de</strong>vices<br />

–drawable-mdpi/android_resort_pool.jpg<br />

• For medium-res <strong>de</strong>vices<br />

–drawable-ldpi/android_resort_pool.jpg<br />

• For low-res <strong>de</strong>vices<br />

–Scale the image so that if it is still too big, it will not be<br />

cropped


Results (Choosing Different<br />

Densities in Visual Editor)<br />

507<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Configuration Types<br />

• Most common qualifiers (in or<strong>de</strong>r of prece<strong>de</strong>nce)<br />

– Language and region<br />

• es, es-rMX, etc.<br />

– Screen size<br />

• small, normal, large, xlarge<br />

– Orientation<br />

• port, land<br />

– Resolution (<strong>de</strong>nsity)<br />

• ldpi, mdpi, hdpi, xhdpi<br />

– Touchscreen type<br />

• notouch, stylus, finger<br />

– Full list<br />

• http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/resources/<br />

providing-resources.html<br />

• Using multiple qualifiers<br />

– Or<strong>de</strong>r of qualifiers must match prece<strong>de</strong>nce or<strong>de</strong>r above<br />

• values-es-port-ldpi, not values-es-ldpi-port or values-port-es-ldpi<br />

509<br />

jeudi 26 janvier 12


More Reading<br />

• Developer’s Gui<strong>de</strong>: Localization<br />

–http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/resources/<br />

localization.html<br />

• Developer’s Gui<strong>de</strong>: Application Resources<br />

–http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/resources/<br />

• Tutorial: Hello L10N<br />

–http://<strong>de</strong>veloper.android.com/resources/tutorials/<br />

localization/in<strong>de</strong>x.html<br />

• Chapter: Localization<br />

510<br />

jeudi 26 janvier 12<br />

–From Android in Action by Ableson et al


Summary<br />

• Language<br />

–Provi<strong>de</strong> multiple versions of strings file<br />

• Maybe images, colors, and sounds as well<br />

• Default fol<strong>de</strong>r should provi<strong>de</strong> values for all names<br />

• Screen orientation<br />

–Provi<strong>de</strong> multiple versions of layout files<br />

• Maybe dimension files and images as well<br />

• Screen <strong>de</strong>nsity<br />

–Provi<strong>de</strong> multiple versions of images (drawable files)<br />

• Maybe vi<strong>de</strong>os and dimension files as well<br />

• Best practices<br />

511<br />

jeudi 26 janvier 12<br />

–Test in all combinations, esp. unexpected languages<br />

–Use Eclipse graphical layout editor for initial testing


jeudi 26 janvier 12<br />

Handling Screen Rotations and<br />

Other App Restarts<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Motivation<br />

• Saving data<br />

• The Bundle class<br />

• Retrieving data<br />

• Activity lifecycle<br />

513<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Big I<strong>de</strong>a<br />

• Android can shut down and restart your app<br />

– When you rotate the screen<br />

– When you change languages<br />

– When app is in background and Android is short on memory<br />

– When you hit the Back button<br />

• Problem<br />

– You risk losing user changes<br />

• Solution<br />

– Save data in a Bundle in onSaveInstanceState<br />

– Read data out of Bundle in onRestoreInstanceState<br />

(or in onCreate)<br />

• Does not handle Back button scenario.<br />

App restarts from scratch with no saved data in that case.<br />

515<br />

jeudi 26 janvier 12


Remin<strong>de</strong>r:<br />

Preventing Screen Rotations<br />

• Issue<br />

–Screen rotations usually require a new layout<br />

–They also cause the app to be shutdown and restarted<br />

• Handling this is the topic of this lecture<br />

• Problem<br />

–What if you do not have landscape layout?<br />

–Or have not yet handled shutdown and restart?<br />

• Solution<br />

516<br />

jeudi 26 janvier 12<br />

–Put an entry in AndroidManifest.xml saying that app runs<br />

only in portrait mo<strong>de</strong> (or only in landscape mo<strong>de</strong>).<br />


jeudi 26 janvier 12<br />

Steps<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Summary: Saving Data<br />

• Overri<strong>de</strong> onSaveInstanceState<br />

– And pass the Bundle to the superclass method<br />

protected void onSaveInstanceState(Bundle outState) {<br />

super.onSaveInstanceState(outState);<br />

outState.putBlah(someData);<br />

}<br />

• Called<br />

– When user rotates screen<br />

– When user changes language<br />

– When app is hid<strong>de</strong>n and Android needs the memory<br />

• Not called<br />

– When user hits Back button<br />

• Note<br />

– Superclass method automatically stores state of GUI widgets (EditText<br />

data, CheckBox state, etc.)<br />

518<br />

jeudi 26 janvier 12


Summary: Restoring Data<br />

• Overri<strong>de</strong> onRestoreInstanceState<br />

–Pass Bundle to superclass method<br />

–Look for data by name, check for null, use the data<br />

protected void onRestoreInstanceState(Bundle savedInstanceState) {<br />

super.onRestoreInstanceState(savedInstanceState);<br />

SomeType data = savedInstanceState.getBlah(key);<br />

if (data != null) { doSomethingWith(data); }<br />

}<br />

• Called<br />

–Any time app is restarted after onSaveInstanceState<br />

• Note<br />

519<br />

jeudi 26 janvier 12<br />

–The same Bundle is passed to onCreate.<br />

–Superclass method automatically restores widget state


The Bundle Class: Details<br />

• Putting data in a Bundle<br />

– putBoolean, putBooleanArray, putDouble, putDoubleArray,<br />

putString, putStringArray, etc.<br />

• These all take keys and values as arguments.<br />

The keys must be Strings. The values must be of the standard types<br />

(int, double, etc.) or array of them.<br />

– putSerializable, putParceleable<br />

• Lets you store custom objects. Note that ArrayList and most other<br />

builtin Java types are already Serializable<br />

• Retrieving data from a Bundle<br />

– getBoolean, getBooleanArray, getDouble, getDoubleArray,<br />

getString, getStringArray, etc.<br />

• No typecast required on retrieval. Numbers are 0 if no match.<br />

– getSerializable, getParceleable<br />

• Typecast required on retrieval. Values are null if no match.<br />

520<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Example<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Loan Payment Comparisons<br />

• I<strong>de</strong>a<br />

–User can enter various interest rates to compare the resultant<br />

monthly and total payments for a $100K,<br />

30 year, fixed-rate loan<br />

–Different layouts for portrait and landscape mo<strong>de</strong>s<br />

–Uses the PaymentInfo class that was shown in the first Intents<br />

lecture<br />

• Approach<br />

522<br />

jeudi 26 janvier 12<br />

–Keep an ArrayList of PaymentInfo<br />

• Also put results in a TableView<br />

–In onSaveInstanceState, store the ArrayList<br />

–In onRestoreInstanceState, retrieve the ArrayList<br />

• Also put results in a TableView


Layout File: Portrait Mo<strong>de</strong><br />

(res/layout/main.xml)<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

(Has heading and divi<strong>de</strong>r, but no body rows.)<br />

<br />

<br />

523<br />

jeudi 26 janvier 12


Layout File: Landscape Mo<strong>de</strong><br />

(res/layout-land/main.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

<br />

(Has heading and divi<strong>de</strong>r, but no body rows.)<br />

<br />

<br />

524<br />

jeudi 26 janvier 12


Values Files<br />

• res/values/strings.xml<br />

–Defines intro text, prompt, table headings,<br />

and button label.<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/dimens.xml<br />

–Gives font sizes.<br />

• Used in portrait mo<strong>de</strong>.<br />

• res/values-land/dimens.xml<br />

525<br />

jeudi 26 janvier 12<br />

–Gives font sizes.<br />

• Used in landscape mo<strong>de</strong>.


Core Java Co<strong>de</strong><br />

public class RotationsActivity extends Activity {<br />

private final static double LOAN_AMOUNT = 100000;<br />

private final static long LOAN_PERIOD = 360; // In months<br />

private TableLayout mPaymentsTable;<br />

private EditText mInterestRateField;<br />

private float mTableSize;<br />

private ArrayList mRowData =<br />

new ArrayList();<br />

526<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mPaymentsTable = (TableLayout)findViewById(R.id.payment_table);<br />

mInterestRateField =<br />

(EditText)findViewById(R.id.interest_rate_field);<br />

Resources resources = getResources();<br />

mTableSize = resources.getDimension(R.dimen.table_body_size);<br />

}<br />

Looks up the ID of the table so that it can later programmatically add rows to it. Note that the<br />

PaymentInfo data is <strong>de</strong>clared as ArrayList instead of List. This is because we will later store it in a<br />

Bundle, and ArrayList is Serializable whereas List is not.


Core Java Co<strong>de</strong> (Continued)<br />

527<br />

jeudi 26 janvier 12<br />

// Attached to the Button via the android:onClick attribute<br />

public void addComparisonRow(View clickedButton) {<br />

double interestRate = 5.0;<br />

try {<br />

interestRate = Double.parseDouble<br />

(mInterestRateField.getText().toString());<br />

} catch(Exception e) {}<br />

PaymentInfo info =<br />

new PaymentInfo(LOAN_AMOUNT, interestRate, LOAN_PERIOD);<br />

mRowData.add(info);<br />

addRow(info);<br />

mInterestRateField.setText("");<br />

}<br />

Reads the textfield value, converts to a number (5.0 <strong>de</strong>fault if field is empty or value is illegal), computes payment info,<br />

stores payment info in an ArrayList, then calls co<strong>de</strong> to add data to bottom of table.


Core Java Co<strong>de</strong> (Continued)<br />

528<br />

jeudi 26 janvier 12<br />

private void addRow(PaymentInfo info) {<br />

TableRow row = new TableRow(this);<br />

row.addView(makeColumn<br />

(info.getFormattedAnnualInterestRateInPercent()));<br />

row.addView(makeColumn(info.getFormattedMonthlyPayment()));<br />

row.addView(makeColumn(info.getFormattedTotalPayments()));<br />

mPaymentsTable.addView(row);<br />

}<br />

private TextView makeColumn(String text) {<br />

TextView col = new TextView(this);<br />

col.setGravity(Gravity.RIGHT);<br />

col.setTextSize(mTableSize);<br />

col.setText(text);<br />

return(col);<br />

}<br />

Creates a TableRow and inserts it into bottom of TableView.


Results (Without Saving State)<br />

529<br />

jeudi 26 janvier 12<br />

User enters some interest rates to<br />

get this result<br />

After entering the data as on the left,<br />

user rotates the screen. Data is lost!


Java Co<strong>de</strong>: Saving State<br />

530<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

protected void onSaveInstanceState(Bundle outState) {<br />

super.onSaveInstanceState(outState);<br />

outState.putSerializable("rowData", mRowData);<br />

}<br />

ArrayList is already Serializable. But, I had to make PaymentInfo (the data insi<strong>de</strong>) Serializable as well.


Java Co<strong>de</strong>: Saving State<br />

531<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

protected void onRestoreInstanceState(Bundle savedInstanceState) {<br />

super.onRestoreInstanceState(savedInstanceState);<br />

@SuppressWarnings("unchecked")<br />

ArrayList rowData =<br />

(ArrayList)<br />

savedInstanceState.getSerializable("rowData");<br />

if (rowData != null) {<br />

mRowData = rowData;<br />

for(PaymentInfo info: rowData) {<br />

addRow(info);<br />

}<br />

}<br />

}<br />

Since generics are implemented by erasure (all work done at compile time, no work done at run time), casting to ArrayList will<br />

give a warning that Java cannot verify that the list contains only Blahs. So, suppress that warning.


Java Co<strong>de</strong>: PaymentInfo<br />

public class PaymentInfo implements Serializable {<br />

private final double mLoanAmount,<br />

mAnnualInterestRateInPercent,<br />

mMonthlyPayment, mTotalPayments;<br />

private final long mLoanPeriodInMonths;<br />

private final String mCurrencySymbol;<br />

}<br />

532<br />

jeudi 26 janvier 12<br />

// Calculates and stores monthly payment and total payments<br />

// Has methods to print out values with nice formatting<br />

Custom data stored in a Bundle must be Serializable or Parceleable.


Results (Saving State)<br />

533<br />

jeudi 26 janvier 12<br />

User enters some interest rates to<br />

get this result<br />

After entering the data as on the left, user<br />

rotates the screen. Data is preserved!


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

More Lifecycle Events<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Overview<br />

• I<strong>de</strong>a<br />

–You can respond to situations other than app being killed and<br />

app being restarted<br />

• Situations<br />

535<br />

jeudi 26 janvier 12<br />

–Another Activity partially obscures Activity<br />

• Use onPause<br />

–Activity is no longer visible at all<br />

• Use onStop<br />

–A stopped Activity is restarted<br />

• Use onStart (every time including first) or<br />

onRestart (every time except first)<br />

–An Activity is killed for good (no saved state Bundle)<br />

• Use onDestroy


Lifecycle Summary<br />

onSaveInstanceState is called<br />

here<br />

536<br />

jeudi 26 janvier 12<br />

If state was saved before,<br />

onRestoreInstanceState is<br />

called here<br />

Diagram taken from top of http://<strong>de</strong>veloper.android.com/reference/android/app/<br />

Activity.html


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• JavaDoc: Activity<br />

–http://<strong>de</strong>veloper.android.com/reference/android/app/<br />

Activity.html<br />

• Introductory parts give lots of <strong>de</strong>tails<br />

• Chapters<br />

538<br />

jeudi 26 janvier 12<br />

–Handling Activity Lifecycle Events and<br />

–Handling Rotation<br />

• From The Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development<br />

by Mark Murphy.<br />

– http://commonsware.com/Android/


Summary<br />

• Save data in onSaveInstanceState<br />

–Can put individual pieces of data in the Bundle, or can add a<br />

composite data structure.<br />

–Custom classes must implement Serializable or Parceleable<br />

• Load data in onRestoreInstanceState<br />

or in onCreate<br />

539<br />

jeudi 26 janvier 12<br />

–Look in Bundle for property of given name<br />

–For Object types, check for null<br />

–For number types, check for 0


jeudi 26 janvier 12<br />

Network Programming:<br />

Part I (General Techniques)<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Part I (this section): general networking<br />

– Socket basics<br />

– Requesting Internet permission<br />

– Example: NIST atomic time<br />

– Asi<strong>de</strong>: simple String formatting and parsing<br />

– Example: FTP welcome messages<br />

– Example: validating URLs with HEAD<br />

• Part II (next section): HTTP-specific approaches<br />

– HttpURLConnection<br />

– HttpClient<br />

– Examples: Searching Web pages<br />

– Using JSON<br />

– Example: remote loan calculations<br />

– Example: Google translation services<br />

541<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Big I<strong>de</strong>a<br />

• Many ways to communicate with a server<br />

543<br />

jeudi 26 janvier 12<br />

–Socket class<br />

• Lets you do general-purpose network programming<br />

– Same as with <strong>de</strong>sktop Java programming<br />

–HttpURLConnection<br />

• Simplifies connections to HTTP servers<br />

– Same as with <strong>de</strong>sktop Java programming<br />

–HttpClient<br />

• Simplest way to download entire content of a URL<br />

– Not standard in Java SE, but standard in Android<br />

–JSONObject<br />

• Simplifies creation and parsing of JSON data<br />

– Not standard in Java SE, but standard in Android


jeudi 26 janvier 12<br />

Socket Basics<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Steps for Talking to Server<br />

1. Create a Socket object<br />

Socket client = new Socket("hostname", portNumber);<br />

2. Create output stream to send data to the Socket<br />

// Last arg of true means autoflush -- flush stream<br />

// when println is called<br />

PrintWriter out =<br />

new PrintWriter(client.getOutputStream(), true);<br />

3. Create input stream to read response from server<br />

545<br />

jeudi 26 janvier 12<br />

BufferedRea<strong>de</strong>r in =<br />

new BufferedRea<strong>de</strong>r<br />

(new InputStreamRea<strong>de</strong>r(client.getInputStream()));


Steps for Implementing a Client<br />

(Continued)<br />

4. Do I/O with the input and output Streams<br />

– For the output stream, PrintWriter, use print, println, and printf, similar to<br />

System.out.print/println/printf<br />

• The main difference is that you can create PrintWriters for different<br />

Unico<strong>de</strong> characters sets, and you can’t with PrintStream (the class<br />

of System.out).<br />

– For input stream, BufferedRea<strong>de</strong>r, call read to get a single char or an<br />

array of characters, or call readLine to get a whole line<br />

• Note that readLine returns null if the connection was terminated (i.e.<br />

on EOF), but waits otherwise<br />

– You can use ObjectInputStream and ObjectOutputStream for<br />

Java-to-Java communication. Very powerful and simple.<br />

5. Close the socket when done<br />

client.close();<br />

• Also closes the associated input and output streams<br />

546<br />

jeudi 26 janvier 12


Exceptions<br />

• UnknownHostException<br />

–If host passed to Socket constructor is not known to DNS<br />

server.<br />

• Note that you may use an IP address string for the host<br />

• IOException<br />

547<br />

jeudi 26 janvier 12<br />

–Timeout<br />

–Connection refused by server<br />

–Interruption or other unexpected problem<br />

• Server closing connection does not cause an error when reading:<br />

null is returned from readLine


Helper Class: SocketUtils<br />

• I<strong>de</strong>a<br />

–It is common to make BufferedRea<strong>de</strong>r and PrintWriter from a<br />

Socket, so simplify the syntax slightly<br />

• Co<strong>de</strong><br />

public class SocketUtils {<br />

}<br />

548<br />

jeudi 26 janvier 12<br />

public static BufferedRea<strong>de</strong>r getRea<strong>de</strong>r(Socket s) throws IOException {<br />

return(new BufferedRea<strong>de</strong>r<br />

(new InputStreamRea<strong>de</strong>r(s.getInputStream())));<br />

}<br />

public static PrintWriter getWriter(Socket s) throws IOException {<br />

// Second argument of true means autoflush.<br />

return (new PrintWriter(s.getOutputStream(), true));<br />

}


Requesting Internet Permission<br />

• Apps that use internet must say so<br />

–User will be notified that app wants internet permission, and<br />

can <strong>de</strong>ny it. Apps that do not request permission will be<br />

<strong>de</strong>nied access by the Android OS<br />

• It is possible with effort to circumvent this by launching a hid<strong>de</strong>n<br />

Web browser that has data embed<strong>de</strong>d in URL<br />

– See http://dtors.org/2010/08/06/circumventing-android-permissions/<br />

• AndroidManifest.xml<br />

<br />

<br />

<br />

<br />

…<br />

<br />

549<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Example:<br />

NIST Time Server<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Time from US National Inst. of<br />

Standards & Technology (NIST)<br />

• I<strong>de</strong>a<br />

–NIST sponsors several servers with high-precision time<br />

• The simplest to read is Daytime Protocol (RFC-867), which<br />

returns the time on the second line of the response to a<br />

connection. Runs on port 13.<br />

– See http://www.nist.gov/pml/div688/grp40/its.cfm<br />

– One popular host name is time-b.nist.gov<br />

• Approach<br />

551<br />

jeudi 26 janvier 12<br />

–Make a Socket connection to time-b.nist.gov on port 13<br />

–Create a BufferedRea<strong>de</strong>r (no PrintWriter nee<strong>de</strong>d)<br />

–Read first line of result and ignore it<br />

–Read second line of result and print it out


Manifest File<br />

(AndroidManifest.xml)<br />

<br />

<br />

<br />

...<br />

<br />

552<br />

jeudi 26 janvier 12


Layout File<br />

(res/layout/nist_time.xml)<br />

<br />

<br />

<br />

<br />

<br />

553<br />

jeudi 26 janvier 12


Values Files<br />

• res/values/strings.xml<br />

–Defines title, prompts, and button labels for all Activities in<br />

this section.<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/colors.xml<br />

–Defines foreground color for some of the results<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/dimens.xml<br />

–Gives font sizes.<br />

• Used in portrait mo<strong>de</strong>.<br />

• res/values-land/dimens.xml<br />

554<br />

jeudi 26 janvier 12<br />

–Gives font sizes.<br />

• Used in landscape mo<strong>de</strong>.


Main Activity<br />

(NistTimeActivity.java)<br />

public class NistTimeActivity extends Activity {<br />

private String mHost = "time-b.nist.gov";<br />

private int mPort = 13;<br />

private TextView mResultDisplay;<br />

555<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.nist_time);<br />

mResultDisplay =<br />

(TextView)findViewById(R.id.time_display);<br />

}


}<br />

Main Activity, Continued<br />

(NistTimeActivity.java)<br />

556<br />

jeudi 26 janvier 12<br />

public void showTime(View clickedButton) {<br />

try {<br />

Socket socket = new Socket(mHost, mPort);<br />

BufferedRea<strong>de</strong>r in = SocketUtils.getRea<strong>de</strong>r(socket);<br />

in.readLine(); // Ignore leading blank line<br />

String timeResult = in.readLine();<br />

mResultDisplay.setText(timeResult);<br />

socket.close();<br />

} catch (UnknownHostException uhe) {<br />

mResultDisplay.setText("Unknown host: " + mHost);<br />

uhe.printStackTrace(); // View this in DDMS window<br />

} catch (IOException ioe) {<br />

mResultDisplay.setText("IOException: " + ioe);<br />

ioe.printStackTrace(); // View this in DDMS window<br />

}<br />

}


Results<br />

557<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Asi<strong>de</strong>:<br />

String Formatting and<br />

Parsing<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Formatting and Parsing<br />

Strategies<br />

• I<strong>de</strong>a<br />

–Simple to connect to a server and create Rea<strong>de</strong>r/Writer<br />

–So, hard parts are formatting request and parsing response<br />

• Approach<br />

559<br />

jeudi 26 janvier 12<br />

–Formatting requests<br />

• Use printf (aka String.format)<br />

–Parsing response: simplest<br />

• Use StringTokenizer<br />

–Parsing response: more powerful<br />

• Use String.split with regular expressions<br />

–Parsing response: most powerful<br />

• Use Pattern and full regex library<br />

– Not covered in this tutorial


Formatted Output: printf<br />

• Takes a variable number of arguments<br />

–System.out.printf("Formatting String", arg1, arg2, …);<br />

• Advantages<br />

–Lets you insert values into output without much clumsier<br />

String concatenation.<br />

–Lets you control the width of results so things line up<br />

–Lets you control the number of digits after the <strong>de</strong>cimal point<br />

in numbers, for consistent-looking output<br />

• Very similar to C/C++ printf function<br />

560<br />

jeudi 26 janvier 12<br />

–If you know printf in C/C++, you can probably use Java's<br />

printf immediately without reading any documentation<br />

• Although some additions in time formatting and locales<br />

–Use String.format to get the equivalent of C’s sprintf


Simple Example: printf vs. println<br />

• General i<strong>de</strong>a<br />

– Each %s entry in formatting string is replaced by next argument in<br />

argument list. %n means newline.<br />

• Example<br />

public static void printSomeStrings() {<br />

String firstName = "John";<br />

String lastName = "Doe";<br />

int numPets = 7;<br />

String petType = "chickens";<br />

System.out.printf("%s %s has %s %s.%n",<br />

firstName, lastName, numPets, petType);<br />

System.out.println(firstName + " " + lastName +<br />

" has " + numPets + " " +<br />

petType + ".");<br />

}<br />

• Result:<br />

John Doe has 7 chickens.<br />

John Doe has 7 chickens.<br />

561<br />

jeudi 26 janvier 12


Controlling Formatting<br />

• Different flags<br />

–%s for strings, %f for floats/doubles, %t for dates, etc.<br />

• Unlike in C/C++, you can use %s for any type (even nums)<br />

• Various extra entries can be inserted<br />

–To control width, number of digits, commas, justification,<br />

type of date format, and more<br />

• Complete <strong>de</strong>tails<br />

–printf uses mini-language<br />

• Complete coverage would take an entire lecture<br />

• However, basic usage is straightforward<br />

–For complete coverage, see<br />

http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax<br />

• Most common errors<br />

– Using + instead of , between arguments (printf uses varargs)<br />

– Forgetting to add %n at the end if you want a newline (not automatic)<br />

562<br />

jeudi 26 janvier 12


Printf Formatting Options<br />

%s<br />

%d<br />

Stands For Options Example<br />

String. Can output any data<br />

type. If arg is Object, toString is<br />

called.<br />

Decimal. Outputs whole<br />

number in base 10. Also %x<br />

and %o for hex and octal.<br />

%f Floating point. Lets you line<br />

up <strong>de</strong>cimal point and control<br />

precision.<br />

%tx<br />

563<br />

jeudi 26 janvier 12<br />

Time (or date). %tA for day,<br />

%tB for month, %tY for year,<br />

and many more.<br />

%widths<br />

Gives min num of chars.<br />

Spaces ad<strong>de</strong>d to left if<br />

nee<strong>de</strong>d.<br />

%widthd %,widthd<br />

Gives min width; inserts<br />

commas.<br />

%width.precisionf<br />

%,width.precisionf<br />

width inclu<strong>de</strong>s comma and<br />

<strong>de</strong>cimal point.<br />

Date now = new Date();<br />

printf("%8s", "Hi")<br />

outputs<br />

" Hi"<br />

printf("%tA, %tB ,%tY", now, now, now)<br />

outputs<br />

"Thursday, November 17, 2005"<br />

printf("%,9d", 1234)<br />

outputs<br />

" 1,234"<br />

printf("%6.2f", Math.PI)<br />

outputs<br />

" 3.14"<br />

%n Outputs OS-specific end of line (linefeed on Linux/Unix, CR/LF pair on Windows)


Printf Example: Controlling Width<br />

and Precision<br />

public class CEO {<br />

private String name;<br />

private double salary; // In billions<br />

}<br />

564<br />

jeudi 26 janvier 12<br />

public CEO(String name, double salary) {<br />

this.name = name;<br />

this.salary = salary;<br />

}<br />

public String getName() { return(name); }<br />

public double getSalary() { return(salary); }<br />

Note that you cannot make a class with a “main” method in an Android app and run it from Eclipse in the<br />

usual way (R-click, Run As � Java Application). So, the printf and parsing examples are in a separate<br />

project called NetworkingSupport. This project also contains the servlet used in the second networking<br />

lecture.


Printf Example: Controlling Width<br />

and Precision<br />

public static void printSomeSalaries() {<br />

CEO[] softwareCEOs =<br />

{ new CEO("Steve Jobs", 3.1234),<br />

new CEO("Scott McNealy", 45.5678),<br />

new CEO("Jeff Bezos", 567.982323),<br />

new CEO("Larry Ellison", 6789.0),<br />

new CEO("Bill Gates", 78901234567890.12)};<br />

System.out.println("SALARIES:");<br />

for(CEO ceo: softwareCEOs) {<br />

System.out.printf("%15s: $%,8.2f%n",<br />

ceo.getName(), ceo.getSalary());<br />

}}<br />

SALARIES:<br />

Steve Jobs: $ 3.12<br />

Scott McNealy: $ 45.57<br />

Jeff Bezos: $ 567.98<br />

Larry Ellison: $6,789.00<br />

Bill Gates: $78,901,234,567,890.12<br />

565<br />

jeudi 26 janvier 12


Parsing Strings Using<br />

StringTokenizer<br />

• I<strong>de</strong>a<br />

566<br />

jeudi 26 janvier 12<br />

–Build a tokenizer from an initial string<br />

–Retrieve tokens one at a time with nextToken<br />

–You can also see how many tokens are remaining<br />

(countTokens) or simply test if the number of tokens<br />

remaining is nonzero (hasMoreTokens)<br />

StringTokenizer tok<br />

= new StringTokenizer(input, <strong>de</strong>limiters);<br />

while (tok.hasMoreTokens()) {<br />

doSomethingWith(tok.nextToken());<br />

}


StringTokenizer<br />

• Constructors<br />

– StringTokenizer(String input, String <strong>de</strong>limiters)<br />

– StringTokenizer(String input, String <strong>de</strong>limiters,<br />

boolean inclu<strong>de</strong>Delimiters)<br />

– StringTokenizer(String input)<br />

• Default <strong>de</strong>limiter set is " \t\n\r\f" (whitespace)<br />

• Methods<br />

– nextToken(), nextToken(String <strong>de</strong>limiters)<br />

– countTokens()<br />

– hasMoreTokens()<br />

• Also see methods in String class<br />

– split, substring, in<strong>de</strong>xOf, startsWith, endsWith, compareTo, …<br />

– Java has good support for regular expressions<br />

567<br />

jeudi 26 janvier 12


Interactive Tokenizer: Example<br />

import java.util.StringTokenizer;<br />

public class TokTest {<br />

public static void main(String[] args) {<br />

if (args.length == 2) {<br />

String input = args[0], <strong>de</strong>limiters = args[1];<br />

StringTokenizer tok<br />

= new StringTokenizer(input, <strong>de</strong>limiters);<br />

while (tok.hasMoreTokens()) {<br />

System.out.println(tok.nextToken());<br />

}<br />

} else {<br />

System.out.println<br />

("Usage: java TokTest string <strong>de</strong>limiters");<br />

}<br />

}<br />

}<br />

568<br />

jeudi 26 janvier 12


Interactive Tokenizer: Result<br />

> java TokTest http://www.microsoft.com/~gates/ :/.<br />

http<br />

www<br />

microsoft<br />

com<br />

~gates<br />

> java TokTest "if (tok.hasMoreTokens()) {" "(){. "<br />

if<br />

tok<br />

hasMoreTokens<br />

569<br />

jeudi 26 janvier 12


Parsing Strings using the split<br />

method of String<br />

• Basic usage<br />

– String[] tokens = mainString.split(<strong>de</strong>limiterString);<br />

• Differences from StringTokenizer<br />

– Entire string is the <strong>de</strong>limiter (not one-char <strong>de</strong>limiters)<br />

• "foobar".split("ob") returns "fo" and "ar"<br />

• "foobar".split("bo") returns "foobar"<br />

– You can use regular expressions in the <strong>de</strong>limiter<br />

• ^, $, *, +, ., etc for beginning of String, end of String, 0 or more, 1 or more,<br />

any one character, etc.<br />

• See http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum<br />

– Unless you use "+", an empty string is returned between <strong>de</strong>limiters<br />

• "foobar".split("o") returns "f", "", and "bar"<br />

• "foobar".split("o+") returns "f" and "bar"<br />

– You can supply second argument to split<br />

• Giving max splits; any extras go in final string<br />

570<br />

jeudi 26 janvier 12


Importance of Regular<br />

Expressions<br />

• I<strong>de</strong>a<br />

–String.split and other<br />

methods use regular<br />

expressions<br />

–So do many other languages.<br />

Knowing regex syntax is<br />

an important part of every<br />

programmer’s repertoire.<br />

• Tutorials<br />

571<br />

jeudi 26 janvier 12<br />

From Randall Munroe and xkcd.com<br />

– http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum<br />

– http://download.oracle.com/javase/tutorial/essential/regex/


Interactive Tokenizer: Example<br />

public class SplitTest {<br />

public static void main(String[] args) {<br />

if (args.length == 2) {<br />

String[] tokens = args[0].split(args[1]);<br />

for(String token: tokens) {<br />

if (token.length() != 0) {<br />

System.out.println(token);<br />

}<br />

}<br />

} else {<br />

System.out.println<br />

("Usage: java SplitTest string <strong>de</strong>limeters");<br />

}<br />

}<br />

}<br />

572<br />

jeudi 26 janvier 12


Interactive Tokenizer: Result<br />

> java TokTest http://www.microsoft.com/~gates/ :/.<br />

http<br />

www<br />

microsoft<br />

com<br />

~gates<br />

> java SplitTest http://www.microsoft.com/~gates/ :/.<br />

http<br />

www.microsoft.com/~gates/<br />

> java SplitTest http://www.microsoft.com/~gates/ [:/.]+<br />

http<br />

www<br />

microsoft<br />

com<br />

~gates<br />

573<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

FTP Welcome Messages<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


FTP Server Welcome Messages<br />

• I<strong>de</strong>a<br />

–When you connect to an FTP server, you usually get a<br />

welcome message. The problem is that it can be a variable<br />

number of lines long.<br />

• If multiline, first line should start with "220-" (220 dash) and last<br />

line should start with "220 " (220 space)<br />

• Approach<br />

575<br />

jeudi 26 janvier 12<br />

–Connect to server on port 21 and read first line<br />

• If it does not start with "220-", print it and exit<br />

–If first line does start with "220-", read and echo lines until<br />

you find one that starts with "220 ".


Example Welcome Messages<br />

• ftp.microsoft.com<br />

> ftp ftp.microsoft.com<br />

220 Microsoft FTP Service<br />

• ftp.oracle.com<br />

> ftp ftp.oracle.com<br />

220-***********************************************************************<br />

220-Oracle FTP Server<br />

220-<br />

220-The use of this FTP server is governed by United States Export Admini-<br />

220-stration Regulations. Details of the U.S. Commercial Encryption Export<br />

220-Controls can be found at the Bureau of Industry and Security web site.<br />

220-All Oracle products are subject to U.S. Export Laws. Diversion contrary<br />

220-to U.S. law is prohibited.<br />

...<br />

220-<br />

220-****************************************************************************<br />

220-<br />

220<br />

576<br />

jeudi 26 janvier 12


Example Welcome Message<br />

> ftp ftp.ngc.com<br />

220-***************************************************************************<br />

* Access Restricted *<br />

* The Northrop Grumman computer network is for use, only by authorized *<br />

* users, and only for authorized purposes. Unauthorized sending, *<br />

* transmitting, or otherwise disseminating proprietary data or tra<strong>de</strong> *<br />

* secrets, private company information or classified data is strictly *<br />

* prohibited. The network and its contents are the exclusive property of *<br />

* the company. There is no right of privacy on the part of any<br />

*<br />

* individual, regarding any information transmitted, stored or received<br />

*<br />

* via the network. Employees may access the Northrop Grumman Global *<br />

* Network only by using tools provi<strong>de</strong>d by IT Solutions. Use of other *<br />

* remote access services is strictly prohibited. Use or access to the<br />

*<br />

* network constitutes consent to the company's acceptable use provisions *<br />

* contained in Corporate Procedure R1, and to the monitoring, storage, *<br />

* retrieval or disclosure or any information transmitted, stored or *<br />

* received via the network for any purpose, including employee *<br />

* discipline, contractual remedies or criminal prosecutions. *<br />

* Passwords must comply with Corporate policy UO J104. *<br />

***************************************************************************<br />

220 FTP server ready<br />

577<br />

jeudi 26 janvier 12


Manifest File<br />

(AndroidManifest.xml)<br />

<br />

<br />

<br />

...<br />

<br />

578<br />

jeudi 26 janvier 12


Layout File: Portrait Mo<strong>de</strong><br />

(res/layout/ftp_message.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

579<br />

jeudi 26 janvier 12


Layout File: Landscape Mo<strong>de</strong><br />

(res/layout-land/ftp_message.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

580<br />

jeudi 26 janvier 12


Values Files<br />

• res/values/strings.xml<br />

–Defines title, prompts, and button labels for all Activities in<br />

this section.<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/colors.xml<br />

–Defines foreground color for some of the results<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/dimens.xml<br />

–Gives font sizes.<br />

• Used in portrait mo<strong>de</strong>.<br />

• res/values-land/dimens.xml<br />

581<br />

jeudi 26 janvier 12<br />

–Gives font sizes.<br />

• Used in landscape mo<strong>de</strong>.


Main Activity<br />

(FtpMessageActivity.java)<br />

public class FtpMessageActivity extends Activity {<br />

private EditText mFtpHost;<br />

private TextView mFtpMessageResult;<br />

private static final int FTP_PORT = 21;<br />

582<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.ftp_message);<br />

mFtpHost = (EditText)findViewById(R.id.ftp_host);<br />

mFtpMessageResult =<br />

(TextView)findViewById(R.id.ftp_message_result);<br />

}


Main Activity, Continued<br />

(FtpMessageActivity.java)<br />

583<br />

jeudi 26 janvier 12<br />

public void showMessage(View clickedButton) {<br />

String host = mFtpHost.getText().toString();<br />

try {<br />

Socket socket = new Socket(host, FTP_PORT);<br />

BufferedRea<strong>de</strong>r in = SocketUtils.getRea<strong>de</strong>r(socket);<br />

List results = new ArrayList();<br />

String line = in.readLine();<br />

results.add(line);<br />

if (line.startsWith("220-")) {<br />

while((line = in.readLine()) != null) {<br />

results.add(line);<br />

if ((line.equals("220") ||<br />

line.startsWith("220 "))) {<br />

break;<br />

}<br />

}<br />

}<br />

String output = makeOutputString(results);<br />

mFtpMessageResult.setText(output);<br />

socket.close();


}<br />

Main Activity, Continued<br />

(FtpMessageActivity.java)<br />

584<br />

jeudi 26 janvier 12<br />

}<br />

} catch (UnknownHostException uhe) {<br />

mFtpMessageResult.setText("Unknown host: " + host);<br />

uhe.printStackTrace(); // View this in DDMS window<br />

} catch (IOException ioe) {<br />

mFtpMessageResult.setText("IOException: " + ioe);<br />

ioe.printStackTrace(); // View this in DDMS window<br />

}<br />

private String makeOutputString(List results) {<br />

StringBuil<strong>de</strong>r output = new StringBuil<strong>de</strong>r();<br />

for (String s: results) {<br />

output.append(s + "\n");<br />

}<br />

return(output.toString());<br />

}


Results<br />

585<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example: Verifying URLs<br />

with the HEAD Command<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


The HEAD Command<br />

• I<strong>de</strong>a<br />

– Web browsers normally send GET or POST requests<br />

• Server responds with status line, response hea<strong>de</strong>rs, blank line, and<br />

then the document<br />

– If you only care about status line, send HEAD instead<br />

• Server responds only with status line and response hea<strong>de</strong>rs<br />

• Approach<br />

– Parse a URL into the host, port (80 if none) and URI<br />

– Connect to host on port. Send request for URI plus Host request<br />

hea<strong>de</strong>r (for servers with virtual hosting)<br />

– Read status line and see if it is 2xx (good), 3xx (forwar<strong>de</strong>d) or<br />

anything else (bad).<br />

• If forwar<strong>de</strong>d, keep reading to find Location hea<strong>de</strong>r<br />

• Note<br />

– Here we use no HTTP-specific classes. Next tutorial section<br />

covers HttpURLConnection and other HTTP-specific classes.<br />

587<br />

jeudi 26 janvier 12


HTTP Request/Response:<br />

GET<br />

• Request<br />

GET /foo/bar.html HTTP/1.1<br />

Host: ...<br />

Hea<strong>de</strong>r2: ...<br />

...<br />

Hea<strong>de</strong>rN:<br />

(Blank Line)<br />

588<br />

jeudi 26 janvier 12<br />

• Response<br />

HTTP/1.1 200 OK<br />

Content-Type: text/html<br />

Hea<strong>de</strong>r2: ...<br />

...<br />

Hea<strong>de</strong>rN: ...<br />

(Blank Line)<br />

<br />

<br />

...<br />

<br />

...<br />


HTTP Request/Response:<br />

HEAD<br />

• Request<br />

HEAD /foo/bar.html HTTP/1.1<br />

Host: ...<br />

Hea<strong>de</strong>r2: ...<br />

...<br />

Hea<strong>de</strong>rN:<br />

(Blank Line)<br />

589<br />

jeudi 26 janvier 12<br />

• Response<br />

HTTP/1.1 200 OK<br />

Content-Type: text/html<br />

Hea<strong>de</strong>r2: ...<br />

...<br />

Hea<strong>de</strong>rN: ...


Using Telnet to Test Server<br />

Commands<br />

• Telnet<br />

–Most people think of telnet as a tool for logging into a remote<br />

server on <strong>de</strong>fault login port (23)<br />

–But, it is really more general: a tool for connecting to a<br />

remote server on any port and interactively sending<br />

commands and looking at results<br />

• Enabling telnet on Windows 7 or Vista<br />

590<br />

jeudi 26 janvier 12<br />

–Starting with Windows Vista, telnet is disabled by <strong>de</strong>fault<br />

• To enable it, see http://technet.microsoft.com/<br />

en-us/library/cc771275(WS.10).aspx<br />

• Or Google for “install telnet windows 7” and above page will<br />

come up #1<br />

• You may also need to turn on local echo – Unix telnet clients are<br />

much more convenient


Example: Steve Ballmer’s Home<br />

Page at Microsoft<br />

> telnet www.microsoft.com 80<br />

Trying 207.46.19.254...<br />

Connected to lb1.www.ms.akadns.net.<br />

Escape character is '^]'.<br />

HEAD /presspass/exec/steve/<strong>de</strong>fault.aspx HTTP/1.0<br />

HTTP/1.1 200 OK<br />

Cache-Control: private<br />

Content-Length: 182105<br />

Content-Type: text/html; charset=utf-8<br />

Server: Microsoft-IIS/7.5<br />

X-AspNet-Version: 2.0.50727<br />

VTag: 279105531500000000<br />

P3P: CP="..."<br />

X-Powered-By: ASP.NET<br />

Date: Tue, 02 Aug 2011 17:58:43 GMT<br />

Connection: keep-alive<br />

Connection to lb1.www.ms.akadns.net<br />

closed by foreign host.<br />

591<br />

jeudi 26 janvier 12<br />

This URI corresponds to the full URL http://www.microsoft.com/<br />

presspass/exec/steve/<strong>de</strong>fault.aspx, which is the real bio page for<br />

Steve Ballmer.<br />

Also, since microsoft.com is using <strong>de</strong>dicated hosting, I can use the<br />

simpler HTTP 1.0 HEAD request (with no Host hea<strong>de</strong>r). The Java<br />

co<strong>de</strong> will use HTTP 1.1 with the Host hea<strong>de</strong>r, so that it can also<br />

handler sites that use virtual (shared) hosting.


Example: Larry Ellison’s Home<br />

Page at Microsoft<br />

> telnet www.microsoft.com 80<br />

Trying 207.46.19.254...<br />

Connected to lb1.www.ms.akadns.net.<br />

Escape character is '^]'.<br />

HEAD /presspass/exec/larry/<strong>de</strong>fault.aspx HTTP/1.0<br />

HTTP/1.1 302 Found<br />

Content-Length: 293<br />

Content-Type: text/html; charset=utf-8<br />

Location: http://www.microsoft.com/library/errorpages/<br />

smarterror.aspx?aspxerrorpath=http%3a%2f<br />

%2f207.46.21.164%2fpresspass%2fexec%2flarry%2f<strong>de</strong>fault.aspx<br />

...<br />

Date: Tue, 02 Aug 2011 18:06:11 GMT<br />

Connection: keep-alive<br />

Connection to lb1.www.ms.akadns.net closed by foreign host.<br />

592<br />

jeudi 26 janvier 12<br />

This corresponds to http://www.microsoft.com/presspass/exec/larry/<br />

<strong>de</strong>fault.aspx, which is a nonexistent page. The page they forward to<br />

should return 404 to prevent in<strong>de</strong>xing by search engines.


Manifest File<br />

(AndroidManifest.xml)<br />

<br />

<br />

<br />

...<br />

<br />

593<br />

jeudi 26 janvier 12


Layout File: Portrait Mo<strong>de</strong><br />

(res/layout/url_checker.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

594<br />

jeudi 26 janvier 12


Layout File: Landscape Mo<strong>de</strong><br />

(res/layout-land/url_checker.xml)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

595<br />

jeudi 26 janvier 12


Values Files<br />

• res/values/strings.xml<br />

–Defines title, prompts, and button labels for all Activities in<br />

this section.<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/colors.xml<br />

–Defines foreground color for some of the results<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/dimens.xml<br />

–Gives font sizes.<br />

• Used in portrait mo<strong>de</strong>.<br />

• res/values-land/dimens.xml<br />

596<br />

jeudi 26 janvier 12<br />

–Gives font sizes.<br />

• Used in landscape mo<strong>de</strong>.


Main Activity<br />

(UrlCheckerActivity.java)<br />

public class UrlCheckerActivity extends Activity {<br />

private EditText mUrlToTest;<br />

private TextView mUrlMessageResult;<br />

597<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.url_checker);<br />

mUrlToTest =<br />

(EditText)findViewById(R.id.url_to_test);<br />

mUrlMessageResult =<br />

(TextView)findViewById<br />

(R.id.url_validation_result);<br />

}


Main Activity, Continued<br />

(UrlCheckerActivity.java)<br />

598<br />

jeudi 26 janvier 12<br />

public void checkUrl(View clickedButton) {<br />

String url = mUrlToTest.getText().toString();<br />

UrlParser parser = new UrlParser(url);<br />

String host = parser.getHost();<br />

int port = parser.getPort();<br />

String uri = parser.getUri();<br />

try {<br />

Socket socket = new Socket(host, port);<br />

PrintWriter out = SocketUtils.getWriter(socket);<br />

BufferedRea<strong>de</strong>r in = SocketUtils.getRea<strong>de</strong>r(socket);<br />

out.printf("HEAD %s HTTP/1.1\r\n", uri);<br />

out.printf("Host: %s\r\n", host);<br />

out.printf("Connection: close\r\n\r\n");<br />

String serverResult = in.readLine();<br />

String info = statusInfo(serverResult, in);<br />

mUrlMessageResult.setText(info);<br />

socket.close();


Main Activity, Continued<br />

(UrlCheckerActivity.java)<br />

599<br />

jeudi 26 janvier 12<br />

}<br />

} catch (UnknownHostException uhe) {<br />

mUrlMessageResult.setText("Unknown host: " + host);<br />

uhe.printStackTrace(); // View this in DDMS window<br />

} catch (IOException ioe) {<br />

mUrlMessageResult.setText("IOException: " + ioe);<br />

ioe.printStackTrace(); // View this in DDMS window<br />

}


Main Activity, Continued<br />

(UrlCheckerActivity.java)<br />

600<br />

jeudi 26 janvier 12<br />

private String statusInfo(String serverResult, BufferedRea<strong>de</strong>r in)<br />

throws IOException {<br />

StatusLineParser statusLine = new StatusLineParser(serverResult);<br />

String result;<br />

if (statusLine.isGood()) {<br />

result = String.format("Good URL: %s -- %s",<br />

statusLine.getStatusCo<strong>de</strong>(),<br />

statusLine.getMessage());<br />

} else if (statusLine.isForwar<strong>de</strong>d()) {<br />

result = String.format("URL forwar<strong>de</strong>d to %s",<br />

location(in));<br />

} else {<br />

result = String.format("Bad URL: %s -- %s",<br />

statusLine.getStatusCo<strong>de</strong>(),<br />

statusLine.getMessage());<br />

}<br />

return(result);<br />

}


Main Activity, Continued<br />

(UrlCheckerActivity.java)<br />

601<br />

jeudi 26 janvier 12<br />

private String location(BufferedRea<strong>de</strong>r in) throws IOException {<br />

String line;<br />

while((line = in.readLine()) != null) {<br />

if (line.toUpperCase().startsWith("LOCATION")) {<br />

String[] results = line.split("\\s+", 2);<br />

return(results[1]);<br />

}<br />

}<br />

return("(Unknown Location)");<br />

}


Helper Classes<br />

• StatusLineParser<br />

–Reads status line and breaks it into three parts: HTTP version,<br />

status co<strong>de</strong>, and message<br />

• Also isGood (status co<strong>de</strong> in the 200’s), isForwar<strong>de</strong>d (301/302)<br />

and isBad (anything else) methods<br />

• UrlParser<br />

602<br />

jeudi 26 janvier 12<br />

–Breaks a URL like http://host:port/path into the host, port, and<br />

path parts. Uses 80 if no port specified.<br />

–Note that the builtin URL class already does this. See next<br />

lecture. But Android has no builtin support for protocols other<br />

than HTTP, so learning to do it yourself is important.


Results<br />

603<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• JavaDoc<br />

– Socket<br />

• http://<strong>de</strong>veloper.android.com/reference/java/net/Socket.html<br />

– Pattern (gives regular expression <strong>de</strong>tails)<br />

• http://<strong>de</strong>veloper.android.com/reference/java/util/regex/Pattern.html<br />

• Tutorial: Networking<br />

– http://download.oracle.com/javase/tutorial/networking/<br />

• Not Android specific, but still very good networking coverage<br />

• Chapters<br />

– Networking and Web Services<br />

• From Android in Action by Ableson et al<br />

– Communicating via the Internet<br />

• From The Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development<br />

by Mark Murphy (http://commonsware.com/Android/)<br />

605<br />

jeudi 26 janvier 12


Summary<br />

• Basics<br />

– Socket socket = new Socket(host, port);<br />

– PrintWriter out = SocketUtils.getWriter(socket);<br />

– BufferedRea<strong>de</strong>r in = SocketUtils.getRea<strong>de</strong>r(socket);<br />

• Slightly longer if you don’t use SocketUtils<br />

• Catch UnknownHostException and IOException<br />

– Ask for Internet permission in AndroidManifest.xml<br />

• Formatting and parsing<br />

– Format request: printf<br />

– Handle response<br />

• Read lines with readLine. Remember it blocks and waits for either<br />

end-of-line (String) or closed connection (null).<br />

• Parse the line with StringTokenizer or String.split<br />

606<br />

jeudi 26 janvier 12<br />

– To use the split method, learn regular expressions


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Network Programming:<br />

Part II (HTTP-Specific Techniques)<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Part I (previous section): general networking<br />

– Socket basics<br />

– Requesting Internet permission<br />

– Example: NIST atomic time<br />

– Asi<strong>de</strong>: simple String formatting and parsing<br />

– Example: FTP welcome messages<br />

– Example: validating URLs with HEAD<br />

• Part II (this section): HTTP-specific approaches<br />

– HttpURLConnection<br />

– HttpClient<br />

– Examples: Searching Web pages<br />

– Using JSON<br />

– Example: remote loan calculations<br />

– Example: Google translation services<br />

608<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Big I<strong>de</strong>a<br />

• Many ways to communicate with a server<br />

610<br />

jeudi 26 janvier 12<br />

–Socket class<br />

• Lets you do general-purpose network programming<br />

– Same as with <strong>de</strong>sktop Java programming<br />

–HttpURLConnection<br />

• Simplifies connections to HTTP servers<br />

– Same as with <strong>de</strong>sktop Java programming<br />

–HttpClient<br />

• Simplest way to download entire content of a URL<br />

– Not standard in Java SE, but standard in Android<br />

–JSONObject<br />

• Simplifies creation and parsing of JSON data<br />

– Not standard in Java SE, but standard in Android


jeudi 26 janvier 12<br />

HttpURLConnection<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


URL and HttpURLConnection:<br />

Overview<br />

• URL<br />

– The URL class can parse a URL and extract its components<br />

(protocol, host, port, URI, etc.)<br />

– You can use openConnection to get a stream to the URL<br />

• HttpURLConnection<br />

– If the URL’s protocol is HTTP, cast the result of openConnection<br />

to HttpURLConnection<br />

• Lets you read the status co<strong>de</strong><br />

612<br />

jeudi 26 janvier 12<br />

– 200, 301, 404, etc.<br />

• Lets you set request hea<strong>de</strong>rs<br />

– Accept, Referer, User-Agent, etc.<br />

• Lets you read response hea<strong>de</strong>rs<br />

– Content-Type, Location, etc.<br />

• Special case for cookies<br />

– Use CookieManager instead of raw hea<strong>de</strong>rs


URL: Details<br />

• openConnection<br />

–Establishes connection to server.<br />

• Cast result to HttpURLConnection for more control<br />

• Uses GET by <strong>de</strong>fault. To use POST, call setDoOutput(true) and<br />

send data via openOutputStream<br />

• openInputStream<br />

–Gets a Stream for reading data. Wrap in InputStreamRea<strong>de</strong>r<br />

(usually buffered) to use readLine.<br />

• getProtocol, getHost, getPort, getFile, getRef<br />

613<br />

jeudi 26 janvier 12<br />

–Returns the different components of the URL.<br />

• The port is -1 if none specified, so you can distinguish an omitted<br />

port from an explicit 80.


Simple URL Methods: Example<br />

import java.net.*;<br />

public class UrlTest {<br />

public static void main(String[] args) {<br />

if (args.length == 1) {<br />

try {<br />

URL url = new URL(args[0]);<br />

System.out.println<br />

("URL: " + url.toExternalForm() + "\n" +<br />

" File: " + url.getFile() + "\n" +<br />

" Host: " + url.getHost() + "\n" +<br />

" Port: " + url.getPort() + "\n" +<br />

" Protocol: " + url.getProtocol() + "\n" +<br />

" Reference: " + url.getRef());<br />

} catch(MalformedURLException mue) {<br />

System.out.println("Bad URL.");<br />

}<br />

} else<br />

System.out.println("Usage: UrlTest ");<br />

}<br />

}<br />

614<br />

jeudi 26 janvier 12


Simple URL Methods: Results<br />

> java UrlTest http://www.irs.gov/mission/#squeezing-them-dry<br />

URL: http://www.irs.gov/mission/#squeezing-them-dry<br />

File: /mission/<br />

Host: www.irs.gov<br />

Port: -1<br />

Protocol: http<br />

Reference: squeezing-them-dry<br />

615<br />

jeudi 26 janvier 12<br />

What month do you think it was when I first wrote this example?


HttpURLConnection: Details<br />

• Getting a connection from a URL<br />

URL url = new URL("http://…");<br />

HttpURLConnection urlConnection =<br />

(HttpURLConnection)url.openConnection();<br />

• Reading data<br />

BufferedRea<strong>de</strong>r in =<br />

new BufferedRea<strong>de</strong>r(new InputStreamRea<strong>de</strong>r<br />

(urlConnection.getInputStream()));<br />

while ((line = in.readLine()) != null) {<br />

doSomethingWith(line);<br />

}<br />

• Other methods<br />

616<br />

jeudi 26 janvier 12<br />

–disconnect, getResponseCo<strong>de</strong>, getHea<strong>de</strong>rField<br />

• Call disconnect when done


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example: Searching Web<br />

Pages for Keywords<br />

(Version 1)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


URL Searcher<br />

• I<strong>de</strong>a<br />

–Print out all lines in a given URL that contain keyword<br />

• Approach<br />

618<br />

jeudi 26 janvier 12<br />

–Read URL and keyword from user<br />

–Call theUrl.openConnection and cast result to<br />

HttpURLConnection<br />

–Attach BufferedRea<strong>de</strong>r to the HttpURLConnection<br />

–Read one line at a time (until null), checking if the line<br />

contains the keyword<br />

–Catch MalformedURLException and IOException<br />

–Call disconnect() when done


Manifest File<br />

(AndroidManifest.xml)<br />

<br />

<br />

<br />

...<br />

<br />

619<br />

jeudi 26 janvier 12


Layout File (res/layout/<br />

url_searcher.xml)<br />

<br />

<br />

<br />

<br />

...<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

620<br />

jeudi 26 janvier 12


Values Files<br />

• res/values/strings.xml<br />

–Defines title, prompts, and button labels for all Activities in<br />

this section.<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/colors.xml<br />

–Defines foreground color for some of the results<br />

• Used in both portrait and landscape mo<strong>de</strong>.<br />

• res/values/dimens.xml<br />

–Gives font sizes.<br />

• Used in portrait mo<strong>de</strong>.<br />

• res/values-land/dimens.xml<br />

621<br />

jeudi 26 janvier 12<br />

–Gives font sizes.<br />

• Used in landscape mo<strong>de</strong>.


Main Activity<br />

(UrlSearcher1Activity.java)<br />

public class UrlSearcher1Activity extends Activity {<br />

protected EditText mUrlToSearch, mSearchString;<br />

protected TextView mUrlMessageResult;<br />

protected float mResultTextSize, mErrorTextSize;<br />

622<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.url_searcher);<br />

mUrlToSearch = (EditText)findViewById(R.id.url_to_search);<br />

mSearchString = (EditText)findViewById(R.id.search_string);<br />

mUrlMessageResult =<br />

(TextView)findViewById(R.id.url_search_result);<br />

Resources resources = getResources();<br />

mResultTextSize =<br />

resources.getDimension(R.dimen.url_search_results_size);<br />

mErrorTextSize =<br />

resources.getDimension(R.dimen.url_search_error_size);<br />

}<br />

Note the protected fields and (next sli<strong>de</strong>s) methods – next example will extend this class and share much of the co<strong>de</strong>.


Main Activity, Continued<br />

(UrlSearcher1Activity.java)<br />

623<br />

jeudi 26 janvier 12<br />

public void searchInUrl(View clickedButton) {<br />

String urlString =<br />

mUrlToSearch.getText().toString();<br />

String searchString =<br />

mSearchString.getText().toString();<br />

showResults(urlString, searchString);<br />

}<br />

This is the method called by the Button. Next example will inherit it unchanged.


Main Activity, Continued<br />

(UrlSearcher1Activity.java)<br />

624<br />

jeudi 26 janvier 12<br />

protected void showResults(String urlString, String searchString) {<br />

HttpURLConnection urlConnection = null;<br />

try {<br />

URL url = new URL(urlString);<br />

urlConnection = (HttpURLConnection)url.openConnection();<br />

BufferedRea<strong>de</strong>r in =<br />

new BufferedRea<strong>de</strong>r<br />

(new InputStreamRea<strong>de</strong>r(urlConnection.getInputStream()));<br />

String line;<br />

StringBuil<strong>de</strong>r matches = new StringBuil<strong>de</strong>r("");<br />

int lineNum = 0;<br />

int numMatches = 0;<br />

while ((line = in.readLine()) != null) {<br />

lineNum++;<br />

if(line.contains(searchString)) {<br />

numMatches++;<br />

matches.append(makeMatch(line, lineNum));<br />

}<br />

}<br />

displayResults(matches, numMatches);<br />

This is the method that is overrid<strong>de</strong>n in the next example.


Main Activity, Continued<br />

(UrlSearcher1Activity.java)<br />

625<br />

jeudi 26 janvier 12<br />

}<br />

} catch (MalformedURLException mue) {<br />

showError("Bad URL: " + urlString);<br />

mue.printStackTrace(); // View this in DDMS window<br />

} catch (IOException ioe) {<br />

showError("Error in connection: " + ioe);<br />

ioe.printStackTrace(); // View this in DDMS window<br />

} finally {<br />

if (urlConnection != null) {<br />

urlConnection.disconnect();<br />

}<br />

}<br />

This is a continuation of the showResults method started on previous sli<strong>de</strong>.


Main Activity, Continued<br />

(UrlSearcher1Activity.java)<br />

626<br />

jeudi 26 janvier 12<br />

protected String makeMatch(String text, int lineNum) {<br />

return(String.format("LINE %s: %s%n", lineNum, text));<br />

}<br />

protected void displayResults(StringBuil<strong>de</strong>r matches,<br />

int numMatches) {<br />

if (numMatches > 0) {<br />

showMatches(matches, numMatches);<br />

} else {<br />

showError("No matches");<br />

}<br />

}


}<br />

Main Activity, Continued<br />

(UrlSearcher1Activity.java)<br />

627<br />

jeudi 26 janvier 12<br />

protected void showMatches(StringBuil<strong>de</strong>r matches,<br />

int numMatches) {<br />

String introMessage =<br />

String.format("FOUND %s MATCHES:%n%n",<br />

numMatches);<br />

matches.insert(0, introMessage);<br />

mUrlMessageResult.setTextSize(mResultTextSize);<br />

mUrlMessageResult.setText(matches);<br />

}<br />

protected void showError(String text) {<br />

mUrlMessageResult.setTextSize(mErrorTextSize);<br />

mUrlMessageResult.setText("\n\n" + text);<br />

}


Results<br />

628<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

HttpClient<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


HttpClient<br />

• I<strong>de</strong>a<br />

–A popular class from the Apache HttpComponents suite that is<br />

bundled with Android.<br />

• Minor problem: Android does not document precisely which<br />

version it uses, so hard to use Apache tutorials<br />

• Capabilities<br />

630<br />

jeudi 26 janvier 12<br />

–Simple way to read an entire URL (via GET) into String<br />

–Mo<strong>de</strong>rately simple way to send POST parameters, then read<br />

entire result into a String<br />

–Many, many other capabilities<br />

• But only the simple reading of content is shown in this tutorial.<br />

For other capabilities, see http://hc.apache.org/httpclient-3.x/<br />

tutorial.html


HttpClient: Reading Result of GET<br />

Request<br />

• Make a <strong>de</strong>fault client<br />

–HttpClient client = new DefaultHttpClient();<br />

• Make an HttpGet with address<br />

–HttpGet httpGet = new HttpGet(address);<br />

• Make a String ResponseHandler<br />

–ResponseHandler handler =<br />

new BasicResponseHandler();<br />

• Call client.execute<br />

631<br />

jeudi 26 janvier 12<br />

–String content = client.execute(httpGet, handler);


HttpClient: Reading Result of<br />

POST Request<br />

• Make a <strong>de</strong>fault client<br />

HttpClient client = new DefaultHttpClient();<br />

• Make an HttpPost with address<br />

HttpPost httpPost = new HttpPost(address);<br />

• Make a List of name/value pairs<br />

List params = new ArrayList();<br />

params.add(new BasicNameValuePair(paramName1, paramValue1));<br />

params.add(…); // More names and values. NOT URL-enco<strong>de</strong>d<br />

• Attach POST data<br />

UrlEnco<strong>de</strong>dFormEntity entity = new UrlEnco<strong>de</strong>dFormEntity(params, "UTF-8");<br />

httpPost.setEntity(entity);<br />

• Make a String ResponseHandler<br />

ResponseHandler handler = new BasicResponseHandler();<br />

• Call client.execute<br />

String content = client.execute(httpPost, handler);<br />

632<br />

jeudi 26 janvier 12


HttpUtils<br />

• I<strong>de</strong>a<br />

–A class <strong>de</strong>veloped for this tutorial that wraps up some simple<br />

HttpClient functionality<br />

• Static methods<br />

633<br />

jeudi 26 janvier 12<br />

–urlContent(String address)<br />

• Returns a String containing entire content of address<br />

• Uses GET. If you want query data, URL enco<strong>de</strong> it and attach it to<br />

the end of URL after question mark<br />

–urlContentPost(String address,<br />

String ... paramNamesAndValues)<br />

• Returns a String containing entire content of address<br />

• Uses POST. All args after the first are alternating parameter<br />

names and unenco<strong>de</strong>d parameter values.


HttpUtils<br />

634<br />

jeudi 26 janvier 12<br />

public static String urlContent(String address)<br />

throws IOException, ClientProtocolException {<br />

HttpClient client = new DefaultHttpClient();<br />

HttpGet httpGet = new HttpGet(address);<br />

ResponseHandler handler =<br />

new BasicResponseHandler();<br />

return(client.execute(httpGet, handler));<br />

}


HttpUtils, Continued<br />

635<br />

jeudi 26 janvier 12<br />

public static String urlContentPost(String address,<br />

String ... paramNamesAndValues)<br />

throws IOException, ClientProtocolException {<br />

HttpClient client = new DefaultHttpClient();<br />

HttpPost httpPost = new HttpPost(address);<br />

List params = new ArrayList();<br />

for(int i=0; i


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example: Searching Web<br />

Pages for Keywords<br />

(Version 2)<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


URL Searcher<br />

• I<strong>de</strong>a<br />

–Redo the previous example, but read URL content with<br />

HttpClient instead of HttpURLConnection<br />

• Approach<br />

637<br />

jeudi 26 janvier 12<br />

–Read URL and keyword from user<br />

–Call HttpUtils.urlContent(address) to get entire content of<br />

address as a single String<br />

–Use String.split to split String on CR or LF<br />

–Test each array entry to see if it contains keyword<br />

–Reuse most of the co<strong>de</strong> from the previous example


XML Files<br />

• AndroidManifest.xml<br />

–Requests Internet permission as shown previously. Also<br />

<strong>de</strong>clares the new Activity.<br />

• res/layout/url_searcher.xml<br />

–Reuses previous layout file with no changes<br />

• Values files<br />

638<br />

jeudi 26 janvier 12<br />

–Reuses previous files with no changes<br />

• strings.xml<br />

• colors.xml<br />

• dimens.xml


Main Activity<br />

(UrlSearcher2Activity.java)<br />

public class UrlSearcher2Activity extends UrlSearcher1Activity {<br />

@Overri<strong>de</strong><br />

protected void showResults(String urlString,<br />

String searchString) {<br />

try {<br />

String urlBody = HttpUtils.urlContent(urlString);<br />

String[] lines = urlBody.split("[\\n\\r]+");<br />

StringBuil<strong>de</strong>r matches = new StringBuil<strong>de</strong>r("");<br />

int lineNum = 0;<br />

int numMatches = 0;<br />

for (String line: lines) {<br />

lineNum++;<br />

if(line.contains(searchString)) {<br />

numMatches++;<br />

matches.append(makeMatch(line, lineNum));<br />

}<br />

}<br />

displayResults(matches, numMatches);<br />

639<br />

jeudi 26 janvier 12<br />

All methods except showResults are inherited from previous class.


}<br />

Main Activity, Continued<br />

(UrlSearcher2Activity.java)<br />

640<br />

jeudi 26 janvier 12<br />

}<br />

} catch (ClientProtocolException cpe) {<br />

showError("Bad URL: " + urlString);<br />

cpe.printStackTrace(); // View this in DDMS window<br />

} catch (IOException ioe) {<br />

showError("Error in connection: " + ioe);<br />

ioe.printStackTrace(); // View this in DDMS window<br />

}


Results<br />

641<br />

jeudi 26 janvier 12<br />

I<strong>de</strong>ntical to previous example.


jeudi 26 janvier 12<br />

Asi<strong>de</strong>: JSON Format<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


JSON (JavaScript Object Notation)<br />

• I<strong>de</strong>a<br />

–A simple textual representation of (JavaScript) objects<br />

• Called “object literals” or “anonymous objects”<br />

–Main applications in JavaScript<br />

• One-time-use objects (rather than reusable classes)<br />

• Objects received via strings<br />

• Directly in JavaScript<br />

– var someObject = { property1: value1,<br />

property2: value2,<br />

... };<br />

• Wi<strong>de</strong>ly used in other languages<br />

643<br />

jeudi 26 janvier 12<br />

–Lightweight alternative to XML<br />

–Android has a builtin class (JSONObject) that will both build<br />

and parse strings representing JSON


JSON: Example in JavaScript<br />

var person =<br />

{ firstName: 'Brendan',<br />

lastName: 'Eich',<br />

bestFriend: { firstName: 'Chris',<br />

lastName: 'Wilson' },<br />

greeting: function() {<br />

return("Hi, I am " + this.firstName +<br />

" " + this.lastName + ".");<br />

}<br />

};<br />

644<br />

jeudi 26 janvier 12


Strict JSON<br />

• Object literals in JavaScript<br />

–Any way you would type a data structure into JavaScript.<br />

– { firstName: 'Larry', lastName: 'Page'}<br />

• Strict JSON according to json.org<br />

–Subset of JavaScript where:<br />

• Object property names must be in double quotes<br />

• Strings are represented with double quotes only (not single<br />

quotes)<br />

– { "firstName": "Larry", "lastName": "Page"}<br />

–This is what Android’s JSONObject supports<br />

• MIME type for JSON from server<br />

645<br />

jeudi 26 janvier 12<br />

–RFC 4627 says JSON should have "application/json" type<br />

–No known libraries enforce this


Popular Web Services that Send<br />

JSON Data<br />

• Google APIs<br />

– Search, translate, data, and many more<br />

• http://co<strong>de</strong>.google.com/apis/customsearch/v1/overview.html<br />

• Yahoo APIs<br />

– Search, travel, answers<br />

• http://<strong>de</strong>veloper.yahoo.com/<br />

• Twitter APIs<br />

– https://<strong>de</strong>v.twitter.com/<br />

• GeoNames<br />

– http://www.geonames.org/export/web-services.html<br />

• Flickr<br />

– http://www.flickr.com/services/api/<br />

• Thousands of others<br />

– See list here<br />

• http://www.programmableweb.com/apis/directory/1?format=JSON<br />

646<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

The JSONObject Class<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


JSONObject<br />

• I<strong>de</strong>a<br />

–A popular JSON-in-Java library from json.org that is bundled<br />

with Android.<br />

• Major problem: Android does not document precisely which<br />

version it uses, and the version it does use is long-obsolete and<br />

lacks JSON-from-bean capability<br />

• Capabilities<br />

648<br />

jeudi 26 janvier 12<br />

–Builds a JSONObject<br />

• From String, Map, or bean<br />

–Lets you extract data from JSONObject<br />

• getString(name), getDouble(name), etc<br />

–Lets you output string representing a JSONObject<br />

• toString


Building a JSONObject<br />

• Constructors<br />

649<br />

jeudi 26 janvier 12<br />

–new JSONObject(jsonString)<br />

• Reads a JSON string and builds JSONObject from it.<br />

– This is most important constructor for use directly on Android, since main<br />

Android use of JSON is handling JSON from Web services<br />

–new JSONObject(nameValueMap)<br />

• Takes a Map and builds JSON from it. Used on Android if you<br />

want to send JSON to a Web service<br />

–new JSONObject(bean) [not in Android version!]<br />

• Takes a bean and builds JSON based on bean properties.<br />

Cannot use directly on Android, but very useful on server that<br />

sends JSON to Android<br />

– If Android had supported this version, would have been much better way to<br />

send JSON to a Web service


Extracting Data From a<br />

JSONObject<br />

• Accessors<br />

650<br />

jeudi 26 janvier 12<br />

–get(propertyName)<br />

• Returns Object associated with name<br />

–getString(propertyName)<br />

• Returns String associated with name. Works for any type (if<br />

Object, uses its toString method)<br />

–getDouble(propertyName)<br />

• Returns double associated with name. Throws JSONException if<br />

value cannot be converted to double.<br />

–getBlah(propertyName)<br />

• getInt, getBoolean, etc. Similar in spirit to getDouble.<br />

–getJSONArray(propertyName)<br />

• Returns JSONArray (not native Java array!) associated with<br />

name


Other Capabilities<br />

• toString<br />

–Builds strict-JSON string from JSONObject<br />

• The JSONArray class<br />

651<br />

jeudi 26 janvier 12<br />

–Represents an array of JSON.<br />

–Although it can be used to send data from Android, it is<br />

usually used for received data.<br />

• { "names": ["larry", "curly", "moe"],<br />

"primes": [2, 3, 5, 7, 11] }


jeudi 26 janvier 12<br />

Using JSONObject<br />

on Server<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Steps for Servlet Outputting<br />

JSON (for Android Use)<br />

• Usual tasks<br />

– response.setContentType("application/json");<br />

– PrintWriter out = response.getWriter<br />

– Call normal business logic co<strong>de</strong> to get bean, array, or Map<br />

• New tasks<br />

653<br />

jeudi 26 janvier 12<br />

– Turn Java object into JSONObject<br />

• JSONObject result = new JSONObject(bean);<br />

• JSONArray result = new JSONArray(arrayOfBeans, false);<br />

• JSONObject result = new JSONObject(map);<br />

– Output JSONObject with print<br />

• out.print(result);<br />

– Automatically calls toString, which does the real JSONification


JSONObject’s Algorithm for<br />

JSONifying a Java Object<br />

• Find the bean properties<br />

–E.g., Name class has getFirstName, and getLastName<br />

methods, so properties are firstName and lastName<br />

• Call the associated accessor methods<br />

–Call each of getFirstName and getLastName on object<br />

• Build JSON representation<br />

–JavaScript property names are bean property names<br />

–Values are results of getter methods<br />

• Mini Example<br />

654<br />

jeudi 26 janvier 12<br />

–toString of a JSONObject representing a Name<br />

• Java: make new Name("John", "Resig").<br />

Pass to JSONObject, then call print (which uses toString)<br />

• Result: { "firstName": "John", "lastName": "Resig"}


Finding Bean Property Name<br />

Based on Method Name<br />

• Usual rule<br />

–Drop the word “get” and change the next letter to lowercase.<br />

Instance variable name is irrelevant.<br />

• Method name: getUserFirstName<br />

• Property name: userFirstName<br />

• Exception 1: boolean properties<br />

–If getter returns boolean or Boolean<br />

• Method name: getPrime or isPrime<br />

• Property name: prime<br />

• Exception 2: consecutive uppercase letters<br />

655<br />

jeudi 26 janvier 12<br />

–If two uppercase letters in a row after “get”<br />

• Method name: getURL<br />

• Property name: URL (not uRL)


Bean Properties: Examples<br />

Method Name Property Name Example JSON Output<br />

getFirstName firstName { "firstName": "Joe", … }<br />

isExecutive<br />

(boolean property)<br />

656<br />

jeudi 26 janvier 12<br />

getExecutive<br />

(boolean property)<br />

executive { "executive": true, … }<br />

executive { "executive": true, … }<br />

getZIP ZIP { "ZIP": "12345", … }<br />

Note 1: property name does not exist anywhere in your co<strong>de</strong>. It is just a shortcut for the method name.<br />

Note 2: property name is <strong>de</strong>rived only from method name. Instance variable name is irrelevant.


Steps for Using JSON Utilities:<br />

Sample Servlet Co<strong>de</strong><br />

public void doPost(HttpServletRequest request,<br />

HttpServletResponse response)<br />

throws ServletException, IOException {<br />

response.setContentType("application/json");<br />

PrintWriter out = response.getWriter();<br />

SomeBean javaResult = callSomeBusinessLogic(…);<br />

JSONObject jsonResult =<br />

new JSONObject(javaResult);<br />

out.print(jsonResult);<br />

}<br />

657<br />

jeudi 26 janvier 12<br />

Lines in red are the only ones that typically change<br />

from application to application. Other lines stay exactly as is.<br />

Calling print automatically calls toString behind the scenes


Drawbacks of JSONification<br />

• Sends state, not behavior, of object<br />

–So, properties that are <strong>de</strong>rived from other properties will be<br />

inconsistent on client if other properties are changed<br />

• Example: Java “Circle” class<br />

–getRadius<br />

• Returns instance variable<br />

–getArea<br />

• Returns Math.PI*radius*radius<br />

• JSONified instance<br />

658<br />

jeudi 26 janvier 12<br />

–Example<br />

• Make new Circle(10). Pass to JSONObject, call toString<br />

• Result: { "radius": 10.0, "area": 314.15927…}<br />

–Problem<br />

• If client-si<strong>de</strong> co<strong>de</strong> changes radius, area doesn’t match


JSONObject from Bean: Example<br />

Co<strong>de</strong><br />

public class CityTest1 {<br />

public static void main(String[] args) {<br />

City sf = CityUtils.getCity("San Francisco");<br />

JSONObject sfJSON = new JSONObject(sf);<br />

System.out.println("JSON version of SF is:\n" +<br />

sfJSON);<br />

}<br />

}<br />

659<br />

jeudi 26 janvier 12<br />

City is a simple class with a bunch of getter methods<br />

(getTime, getName, getPopulation, etc.)<br />

Note: toString is automatically called when you print an Object in Java. It is the<br />

toString method of JSONObject that builds the JSON representation.


JSONObject from Bean: Example<br />

Result<br />

JSON version of SF is:<br />

{"time": "06:00:55 AM",<br />

"name": "San Francisco",<br />

"timeZone": -3,<br />

"pop": 744041,<br />

"population": " 744,041"}<br />

660<br />

jeudi 26 janvier 12<br />

(White space ad<strong>de</strong>d for readability)


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Example:<br />

Remote Loan Calculator<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


JSON-Based Loan Calculator<br />

Service<br />

• I<strong>de</strong>a<br />

– Make servlet for doing loan calculations<br />

• Input: JSON object with amount, period, and interest rate<br />

• Output: JSON object with inputs plus monthly payment and total<br />

payments<br />

• Approach<br />

– Server<br />

• Read parameter and pass to JSONObject constructor<br />

• Extract values with getDouble and getLong<br />

• Use same PaymentInfo class as in several previous examples<br />

• Turn PaymentInfo into JSON via JSONObject<br />

– Client (Android)<br />

• Build Map and turn into JSONObject, send to server<br />

• Read String, turn into JSONObject<br />

• Extract info with getString<br />

662<br />

jeudi 26 janvier 12


Servlet<br />

@WebServlet("/loan-calculator")<br />

public class LoanCalculator extends HttpServlet {<br />

@Overri<strong>de</strong><br />

public void doGet(HttpServletRequest request, HttpServletResponse response)<br />

throws ServletException, IOException {<br />

String inputString = request.getParameter("loanInputs");<br />

double loanAmount = 200000;<br />

double annualInterestRateInPercent = 5.5;<br />

long loanPeriodInMonths = 360;<br />

try {<br />

JSONObject inputValues = new JSONObject(inputString);<br />

loanAmount = inputValues.getDouble("amount");<br />

annualInterestRateInPercent = inputValues.getDouble("rate");<br />

loanPeriodInMonths = inputValues.getLong("months");<br />

} catch (Exception e) { // NullPointerException & JSONException<br />

// Use <strong>de</strong>fault values assigned before the try block<br />

}<br />

PaymentInfo info = new PaymentInfo(loanAmount,<br />

annualInterestRateInPercent,<br />

loanPeriodInMonths);<br />

PrintWriter out = response.getWriter();<br />

out.println(new JSONObject(info));<br />

}<br />

663<br />

jeudi 26 janvier 12<br />

If you are unfamiliar with servlets, see extensive tutorial series<br />

at http://www.coreservlets.com/


Servlet, Continued<br />

664<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void doPost(HttpServletRequest request,<br />

HttpServletResponse response)<br />

throws ServletException, IOException {<br />

doGet(request, response);<br />

}<br />

Makes the most sense to send the data via POST. However, it also supports GET to simplify interactive testing by editing the browser line.<br />

This app is installed on apps.coreservlets.com, so URL is http://apps.coreservlets.com/NetworkingSupport/loan-calculator<br />

You can experiment interactively by calling<br />

http://apps.coreservlets.com/NetworkingSupport/loan-calculator?loanInputs={amount: 200000, rate: 6.5, months: 180}<br />

The tutorial Web site has the servlet co<strong>de</strong> as well as the Android co<strong>de</strong>, so you can install the servlet on a local Java server (requires Tomcat 7<br />

or equivalent). However, note that the Android emulator does not un<strong>de</strong>rstand localhost as a host name, since it acts like in<strong>de</strong>pen<strong>de</strong>nt <strong>de</strong>vice.<br />

So, you must use real domain name or IP address.


Android Activity<br />

public class LoanCalculatorActivity extends Activity {<br />

private EditText mBaseUrl, mLoanAmount, mInterestRate, mLoanPeriod;<br />

private TextView mMontlyPaymentResult, mTotalPaymentsResult;<br />

665<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.loan_calculator);<br />

mBaseUrl = (EditText)findViewById(R.id.base_url);<br />

mLoanAmount = (EditText)findViewById(R.id.loan_amount);<br />

mInterestRate = (EditText)findViewById(R.id.interest_rate);<br />

mLoanPeriod = (EditText)findViewById(R.id.loan_period);<br />

mMontlyPaymentResult =<br />

(TextView)findViewById(R.id.monthly_payment_result);<br />

mTotalPaymentsResult =<br />

(TextView)findViewById(R.id.total_payments_result);<br />

}


Android Activity, Continued<br />

666<br />

jeudi 26 janvier 12<br />

public void showLoanPayments(View clickedButton) {<br />

String baseUrl = mBaseUrl.getText().toString();<br />

String loanAmount = mLoanAmount.getText().toString();<br />

String interestRate = mInterestRate.getText().toString();<br />

String loanPeriod = mLoanPeriod.getText().toString();<br />

LoanInputs inputs =<br />

new LoanInputs(loanAmount, interestRate, loanPeriod);<br />

JSONObject inputsJson = new JSONObject(inputs.getInputMap());<br />

try {<br />

String jsonString =<br />

HttpUtils.urlContentPost(baseUrl, "loanInputs",<br />

inputsJson.toString());<br />

JSONObject jsonResult = new JSONObject(jsonString);<br />

mMontlyPaymentResult.setText<br />

(jsonResult.getString("formattedMonthlyPayment"));<br />

mTotalPaymentsResult.setText<br />

(jsonResult.getString("formattedTotalPayments"));<br />

mLoanAmount.setText<br />

(jsonResult.getString("loanAmount"));<br />

mInterestRate.setText<br />

(jsonResult.getString("annualInterestRateInPercent"));<br />

mLoanPeriod.setText<br />

(jsonResult.getString("loanPeriodInMonths"));


Helper Class<br />

public class LoanInputs {<br />

private Map mInputMap;<br />

}<br />

667<br />

jeudi 26 janvier 12<br />

public LoanInputs(String amount, String rate,<br />

String months) {<br />

mInputMap = new HashMap();<br />

mInputMap.put("amount", amount);<br />

mInputMap.put("rate", rate);<br />

mInputMap.put("months", months);<br />

}<br />

public Map getInputMap() {<br />

return(mInputMap);<br />

}


Results<br />

668<br />

jeudi 26 janvier 12<br />

http://apps.coreservlets.com/NetworkingSupport/loan-calculator


jeudi 26 janvier 12<br />

Example: Google<br />

Translation Services<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Double Translate App<br />

• I<strong>de</strong>a<br />

– The Google Translate services has a JSON-based API<br />

– http://co<strong>de</strong>.google.com/apis/language/translate/v2/using_rest.html<br />

• Can look up all the supported languages<br />

• Can translate from any supported language into any other<br />

– Translate from English to foreign and then back to English to see<br />

how well the translation works<br />

• Very good for literal text with simple grammar.<br />

• Approach<br />

– Get JSONArray representing supported lanuages.<br />

• Put in Spinner<br />

– Get JSONObject representing intermediate translation<br />

• Send back to server to get final translation<br />

– Only selected co<strong>de</strong> will be shown here. Full co<strong>de</strong> online.<br />

670<br />

jeudi 26 janvier 12


Main Activity<br />

public class DoubleTranslateActivity extends Activity {<br />

private EditText mText;<br />

private Spinner mLanguageChoices;<br />

private TextView mIntermediateResult, mFinalResult;<br />

private String apiKey = "...";<br />

671<br />

jeudi 26 janvier 12<br />

The translate API requires you to apply for<br />

a free API key and send the key with every<br />

request.


Main Activity, Continued<br />

672<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.main);<br />

mText = (EditText)findViewById(R.id.text);<br />

mLanguageChoices = (Spinner)findViewById(R.id.language_choices);<br />

List supportedLanguages =<br />

TranslateUtils.supportedLanguages(apiKey);<br />

ArrayAdapter spinner2Adapter =<br />

new ArrayAdapter(this,<br />

android.R.layout.simple_spinner_item,<br />

supportedLanguages);<br />

spinner2Adapter.setDropDownViewResource<br />

(android.R.layout.simple_spinner_dropdown_item);<br />

mLanguageChoices.setAdapter(spinner2Adapter);<br />

mIntermediateResult = (TextView)findViewById(R.id.intermediate_result);<br />

mFinalResult = (TextView)findViewById(R.id.final_result);<br />

}


Main Activity, Continued<br />

673<br />

jeudi 26 janvier 12<br />

public void doubleTranslate(View clickedButton) {<br />

String sourceLanguageCo<strong>de</strong> = "en";<br />

Language targetLanguage =<br />

(Language)mLanguageChoices.getSelectedItem();<br />

String targetLanguageCo<strong>de</strong> = targetLanguage.getCo<strong>de</strong>();<br />

String textToTranslate = mText.getText().toString();<br />

Translator translator =<br />

new Translator(apiKey, sourceLanguageCo<strong>de</strong>,<br />

targetLanguageCo<strong>de</strong>, textToTranslate);<br />

String firstTranslation = translator.getFirstTranslation();<br />

mIntermediateResult.setText(firstTranslation);<br />

String secondTranslation =<br />

translator.getSecondTranslation();<br />

mFinalResult.setText(secondTranslation);<br />

}


Key Helper Class<br />

(TranslationUtils)<br />

public static String translationString<br />

(String apiKey, String sourceLanguage,<br />

String targetLanguage, String textToTranslate) {<br />

try {<br />

String jsonString = translationJson(apiKey, sourceLanguage,<br />

targetLanguage, textToTranslate);<br />

JSONObject jsonObject = new JSONObject(jsonString);<br />

String text =<br />

jsonObject.getJSONObject("data").getJSONArray("translations")<br />

.getJSONObject(0).getString("translatedText");<br />

return(text);<br />

} catch(HttpResponseException hre) {<br />

int errorCo<strong>de</strong> = hre.getStatusCo<strong>de</strong>();<br />

if (errorCo<strong>de</strong> == 403) { // 403 is "Forbid<strong>de</strong>n"<br />

return(ERROR_FORBIDDEN);<br />

} else { // Probably 400, "Bad Request"<br />

return(ERROR_BAD_REQUEST);<br />

}<br />

} catch(IOException ioe) {<br />

return(ERROR_BAD_CONNECTION);<br />

} catch(JSONException jse) {<br />

return(ERROR_JSON_PROBLEM);<br />

}<br />

}<br />

674<br />

jeudi 26 janvier 12


Results: Very Simple Text<br />

675<br />

jeudi 26 janvier 12


Results: Medium-Difficulty Text<br />

676<br />

jeudi 26 janvier 12


Results: Deliberately-Tricky Text<br />

677<br />

jeudi 26 janvier 12<br />

The proper interpretation is “old people crew (work on) the boat”. This is an<br />

example of a gar<strong>de</strong>n-path sentence and is taken from http://<br />

en.wikipedia.org/wiki/Gar<strong>de</strong>n_path_sentence


Results: More Deliberately-Tricky<br />

Text<br />

678<br />

jeudi 26 janvier 12<br />

The proper interpretation is “baby <strong>de</strong>er die when hunters (who are in the<br />

burning forest) shoot at them”.


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• JavaDoc<br />

–HttpURLConnection<br />

• http://<strong>de</strong>veloper.android.com/reference/java/net/<br />

HttpURLConnection.html<br />

• HttpClient Tutorial<br />

–http://hc.apache.org/httpclient-3.x/tutorial.html<br />

• JSON Tutorials<br />

680<br />

jeudi 26 janvier 12<br />

–http://json.org/<br />

–http://www.webmonkey.com/2010/02/<br />

get_started_with_json/<br />

–http://www.hunlock.com/blogs/<br />

Mastering_JSON_(_JavaScript_Object_Notation_)


Summary<br />

• Read individual lines from a URL<br />

–Use HttpURLConnection<br />

• Read an entire URL as a String<br />

–Use HttpClient<br />

• Particularly useful if result is JSON<br />

• JSON<br />

–Simple format wi<strong>de</strong>ly used in Ajax and Web services<br />

• JSONObject<br />

681<br />

jeudi 26 janvier 12<br />

–Converts string into JSON<br />

–Outputs JSON string<br />

• But builtin Android version lacks most important method, for<br />

building JSON string from a bean


jeudi 26 janvier 12<br />

Multithrea<strong>de</strong>d Programming<br />

Part I: General Techniques<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• Why threads?<br />

• Basic approach<br />

–Make a task list with Executors.newFixedThreadPool<br />

–Add tasks to list with taskList.execute(someRunnable)<br />

• Three variations on the theme<br />

–Separate classes that implement Runnable<br />

–Main Activity implements Runnable<br />

–Inner classes that implement Runnable<br />

• Related topics<br />

683<br />

jeudi 26 janvier 12<br />

–Race conditions and synchronization<br />

–Helpful Thread-related methods<br />

–Advanced topics in concurrency


684<br />

jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Motivation for Concurrent<br />

Programming<br />

• Pros<br />

–Advantages even on single-processor systems<br />

• Efficiency<br />

– Downloading image files<br />

• Convenience<br />

– A clock icon<br />

• Responsiveness<br />

– If you block the main thread, event handlers will not respond<br />

–Some <strong>de</strong>vices have multiple cpus or cores<br />

• Find out via Runtime.getRuntime().availableProcessors()<br />

• Cons<br />

685<br />

jeudi 26 janvier 12<br />

–Significantly har<strong>de</strong>r to <strong>de</strong>bug and maintain than single-<br />

threa<strong>de</strong>d apps


Steps for<br />

Concurrent Programming<br />

• First, make a task list<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(poolSize);<br />

• The poolSize is the maximum number of simultaneous threads. For<br />

many apps, it is higher than the number of tasks, so each task has a<br />

separate thread.<br />

• There are other types of thread pools, but this is simplest<br />

• Second, add tasks to the list (three options)<br />

– Make a separate class that implements Runnable.<br />

• Make instances of this class and start threading via<br />

taskList.execute(new MySeparateRunnableClass(…))<br />

– Have your existing class implement Runnable.<br />

• Start threading via taskList.execute(this)<br />

– Use an inner class.<br />

• taskList.execute(new MyInnerRunnableClass(…))<br />

686<br />

jeudi 26 janvier 12


687<br />

jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Approach One: Separate<br />

Classes that Implement<br />

Runnable<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Thread Mechanism One:<br />

Separate Runnable Class<br />

• Make class that implements Runnable<br />

–No import statements nee<strong>de</strong>d: Runnable is in java.lang<br />

• Put actions to be performed in run method<br />

–public class MyRunnableClass implements Runnable {<br />

}<br />

public void run() { … }<br />

• Create instance of your class<br />

–Or lots of instances if you want lots of threads<br />

• Pass instance to ExecutorService.execute<br />

688<br />

jeudi 26 janvier 12<br />

–taskList.execute(new MyRunnableClass(…));<br />

• The number of simultaneous threads won’t exceed the maximum<br />

size of the pool.


Separate Runnable Class:<br />

Template Co<strong>de</strong><br />

689<br />

jeudi 26 janvier 12<br />

public class MainClass extends Activity {<br />

...<br />

public void startSomeThreads() {<br />

int poolSize = ...;<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(poolSize);<br />

for(int i=0; i


Thread Mechanism One: Example<br />

public class ThreadingBasicsActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.threading_basics);<br />

}<br />

}<br />

690<br />

jeudi 26 janvier 12<br />

public void separateClass(View clickedButton) {<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(50);<br />

taskList.execute(new SeparateCounter(6));<br />

taskList.execute(new SeparateCounter(5));<br />

taskList.execute(new SeparateCounter(4));<br />

}<br />

This method is associated with<br />

a Button via the<br />

android:onClick attribute in the<br />

layout file.


Thread Mechanism One: Example<br />

(Continued)<br />

public class SeparateCounter implements Runnable {<br />

private final int mLoopLimit;<br />

}<br />

691<br />

jeudi 26 janvier 12<br />

public SeparateCounter(int loopLimit) {<br />

this.mLoopLimit = loopLimit;<br />

}<br />

public void run() {<br />

for (int i = 0; i < mLoopLimit; i++) {<br />

String threadName =<br />

Thread.currentThread().getName();<br />

System.out.printf("%s: %s%n", threadName, i);<br />

// Sleep for up to 1 second<br />

ThreadUtils.pause(Math.random());<br />

}<br />

}<br />

This example is just for testing, so the output will go in the DDMS window. The next tutorial section will talk about what to do if<br />

the results of the background threads directly affect the user interface.


Helper Class<br />

public class ThreadUtils {<br />

public static void pause(double seconds) {<br />

try {<br />

Thread.sleep(Math.round(1000.0 * seconds));<br />

} catch (InterruptedException ie) {}<br />

}<br />

}<br />

692<br />

jeudi 26 janvier 12<br />

// Uninstantiable class: static methods only<br />

private ThreadUtils() {}


Thread Mechanism One: Results<br />

pool-2-thread-1: 0<br />

pool-2-thread-2: 0<br />

pool-2-thread-3: 0<br />

pool-2-thread-1: 1<br />

pool-2-thread-3: 1<br />

pool-2-thread-3: 2<br />

pool-2-thread-2: 1<br />

pool-2-thread-3: 3<br />

pool-2-thread-1: 2<br />

pool-2-thread-2: 2<br />

pool-2-thread-2: 3<br />

pool-2-thread-1: 3<br />

pool-2-thread-1: 4<br />

pool-2-thread-1: 5<br />

pool-2-thread-2: 4<br />

693<br />

jeudi 26 janvier 12


Pros and Cons of Approach<br />

• Advantages<br />

– Loose coupling<br />

• Can change pieces in<strong>de</strong>pen<strong>de</strong>ntly<br />

• Can reuse Runnable class in more than one application<br />

– Passing arguments<br />

• If you want different threads to do different things, you pass args to<br />

constructor, which stores them in instance variables that run method uses<br />

– Little danger of race conditions<br />

• You usually use this approach when there is no data shared among<br />

threads, so no need to synchronize.<br />

• Disadvantages<br />

– Hard to access main Activity<br />

• If you want to call methods in main app, you must<br />

694<br />

jeudi 26 janvier 12<br />

– Pass reference to main app to the Runnable’s constructor, which stores it<br />

– Make methods in main app be public


695<br />

jeudi 26 janvier 12<br />

Approach Two: Main<br />

App Implements<br />

Runnable<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Review of Interfaces: Syntax<br />

• Shape interface<br />

public interface Shape {<br />

}<br />

public double getArea(); // No body, just specification<br />

• Circle class<br />

public class Circle implements Shape {<br />

}<br />

• Note<br />

696<br />

jeudi 26 janvier 12<br />

public double getArea() { some real co<strong>de</strong> }<br />

–You can implement many interfaces<br />

• public class MyClass implements Foo, Bar, Baz { … }


Review of Interfaces: Benefits<br />

• Class can be treated as interface type<br />

697<br />

jeudi 26 janvier 12<br />

–public interface Shape {<br />

public double getArea();<br />

}<br />

–public class Circle implements Shape { … }<br />

–public class Rectangle implements Shape { … }<br />

Shape[] shapes =<br />

{ new Circle(…), new Rectangle(…) … };<br />

double sum = 0;<br />

for(Shape s: shapes) {<br />

sum = sum + s.getArea(); // All Shapes have getArea<br />

}


Thread Mechanism Two:<br />

Main App Implements Runnable<br />

• Have main class implement Runnable<br />

– Put actions in run method of existing class<br />

• public class MyClass extends Activity implements Runnable {<br />

…<br />

public void run() { … }<br />

}<br />

• Pass the instance of main class to execute<br />

– taskList.execute(this);<br />

• Main differences from previous approach<br />

– Good<br />

• run can easily call methods in main class, since it is in that class<br />

– Bad<br />

• If run accesses any shared data (instance variables), you have to<br />

worry about conflicts (race conditions)<br />

• Very hard to pass arguments, so each task starts off the same<br />

698<br />

jeudi 26 janvier 12


Main App Implements Runnable:<br />

Template Co<strong>de</strong><br />

699<br />

public class Threa<strong>de</strong>dActivity extends Activity<br />

implements Runnable {<br />

public void run() {<br />

// Co<strong>de</strong> to run in background. Don’t update UI.<br />

}<br />

}<br />

jeudi 26 janvier 12<br />

public void startSomeThreads() {<br />

int poolSize = ...;<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(poolSize);<br />

for(int i=0; i


Thread Mechanism Two: Example<br />

public class ThreadingBasicsActivity extends Activity<br />

implements Runnable {<br />

private final static int LOOP_LIMIT = 5;<br />

700<br />

jeudi 26 janvier 12<br />

public void implementsInterface(View clickedButton) {<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(50);<br />

taskList.execute(this);<br />

taskList.execute(this);<br />

}<br />

taskList.execute(this);<br />

This method is associated with<br />

a Button via the<br />

android:onClick attribute in the<br />

layout file.<br />

@Overri<strong>de</strong><br />

public void run() {<br />

for (int i = 0; i < LOOP_LIMIT; i++) {<br />

String threadName = Thread.currentThread().getName();<br />

System.out.printf("%s: %s%n", threadName, i);<br />

ThreadUtils.pause(Math.random());<br />

}<br />

}


Thread Mechanism Two: Results<br />

pool-3-thread-1: 0<br />

pool-3-thread-2: 0<br />

pool-3-thread-3: 0<br />

pool-3-thread-3: 1<br />

pool-3-thread-1: 1<br />

pool-3-thread-2: 1<br />

pool-3-thread-1: 2<br />

pool-3-thread-3: 2<br />

pool-3-thread-2: 2<br />

pool-3-thread-3: 3<br />

pool-3-thread-1: 3<br />

pool-3-thread-3: 4<br />

pool-3-thread-2: 3<br />

pool-3-thread-1: 4<br />

pool-3-thread-2: 4<br />

701<br />

jeudi 26 janvier 12


Pros and Cons of Approach<br />

• Advantages<br />

–Easy to access main app.<br />

• The run method is already insi<strong>de</strong> main app. Can access any<br />

public or private methods or instance variables.<br />

• Disadvantages<br />

702<br />

jeudi 26 janvier 12<br />

–Tight coupling<br />

• run method tied closely to this application<br />

–Cannot pass arguments to run<br />

• So, you either start a single thread only (quite common), or all<br />

the threads do very similar tasks<br />

–Danger of race conditions<br />

• You usually use this approach specifically because you want to<br />

access data in main application. So, if run modifies some shared<br />

data, you must synchronize.


703<br />

jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Approach Three: Inner<br />

Class that Implements<br />

Runnable<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Review of Inner Classes<br />

• Class can be <strong>de</strong>fined insi<strong>de</strong> another class<br />

– Methods in the inner class can access all methods and instance<br />

variables of surrounding class<br />

• Even private methods and variables<br />

• Example<br />

public class OuterClass {<br />

private int count = …;<br />

704<br />

jeudi 26 janvier 12<br />

}<br />

public void foo(…) {<br />

InnerClass inner = new InnerClass();<br />

inner.bar();<br />

}<br />

private class InnerClass {<br />

public void bar() {<br />

doSomethingWith(count);<br />

}<br />

}


Thread Mechanism Three:<br />

Runnable Inner Class<br />

• Have inner class implement Runnable<br />

–Put actions in run method of inner class<br />

• public class MyClass extends Activity {<br />

…<br />

private class SomeInnerClass implements Runnable {<br />

public void run() { … }<br />

}<br />

}<br />

• Pass instances of inner class to execute<br />

705<br />

jeudi 26 janvier 12<br />

–taskList.execute(new SomeInnerClass(…));


Inner Class Implements<br />

Runnable: Template Co<strong>de</strong><br />

706<br />

jeudi 26 janvier 12<br />

public class MainClass extends Activity {<br />

public void startSomeThreads() {<br />

int poolSize = ...;<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(poolSize);<br />

for(int i=0; i


Thread Mechanism Three:<br />

Example<br />

public class ThreadingBasicsActivity extends Activity {<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.threading_basics);<br />

}<br />

707<br />

jeudi 26 janvier 12<br />

public void innerClass(View clickedButton) {<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(50);<br />

taskList.execute(new InnerCounter(6));<br />

taskList.execute(new InnerCounter(5));<br />

taskList.execute(new InnerCounter(4));<br />

}<br />

This method is associated with a Button via the<br />

android:onClick attribute in the layout file. Note<br />

also that the class is not yet finished – inner class<br />

on next page is still insi<strong>de</strong> this class.


}<br />

Thread Mechanism Three:<br />

Example (Continued)<br />

708<br />

jeudi 26 janvier 12<br />

private class InnerCounter implements Runnable {<br />

private final int mLoopLimit;<br />

}<br />

public InnerCounter(int loopLimit) {<br />

this.mLoopLimit = loopLimit;<br />

}<br />

public void run() {<br />

for (int i = 0; i < mLoopLimit; i++) {<br />

String threadName =<br />

Thread.currentThread().getName();<br />

System.out.printf("%s: %s%n", threadName, i);<br />

ThreadUtils.pause(Math.random());<br />

}<br />

}<br />

You can also use anonymous inner classes. This is not different enough to warrant a separate<br />

example here, especially since we showed examples in the section on Widget event handling.


Thread Mechanism Three:<br />

Results<br />

pool-5-thread-1: 0<br />

pool-5-thread-2: 0<br />

pool-5-thread-3: 0<br />

pool-5-thread-3: 1<br />

pool-5-thread-1: 1<br />

pool-5-thread-2: 1<br />

pool-5-thread-1: 2<br />

pool-5-thread-1: 3<br />

pool-5-thread-3: 2<br />

pool-5-thread-2: 2<br />

pool-5-thread-2: 3<br />

pool-5-thread-3: 3<br />

pool-5-thread-1: 4<br />

pool-5-thread-2: 4<br />

pool-5-thread-1: 5<br />

709<br />

jeudi 26 janvier 12


Pros and Cons of Approach<br />

• Advantages<br />

–Easy to access main app.<br />

• Methods in inner classes can access any public or private<br />

methods or instance variables of outer class.<br />

–Can pass arguments to run<br />

• As with separate classes, you pass args to constructor, which<br />

stores them in instance variables that run uses<br />

• Disadvantages<br />

710<br />

jeudi 26 janvier 12<br />

–Tight coupling<br />

• run method tied closely to this application<br />

–Danger of race conditions<br />

• You usually use this approach specifically because you want to<br />

access data from main application. So, if run modifies some<br />

shared data, you must synchronize.


711<br />

jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Summary of Approaches<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Pros and Cons<br />

• Separate class that implements Runnable<br />

–Can pass args to run<br />

–Cannot easily access data in main class<br />

–Usually no worry about race conditions<br />

• Main class implements Runnable<br />

–Can easily access data in main class<br />

–Cannot pass args to run<br />

–Must worry about race conditions<br />

• Inner class implements Runnable<br />

712<br />

jeudi 26 janvier 12<br />

–Can easily access data in main class<br />

–Can pass args to run<br />

–Must worry about race conditions


713<br />

jeudi 26 janvier 12<br />

Race Conditions and<br />

Synchronization<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Race Conditions<br />

• I<strong>de</strong>a<br />

– You write co<strong>de</strong> that assumes no other threads run between certain<br />

steps. But, if your thread is interrupted in the wrong place and<br />

another thread changes some data, you get the wrong answer.<br />

• Typical scenarios<br />

– You modify shared data & assume next thread sees new result.<br />

• You read a value and then increment it. You assume no thread runs<br />

between when you read it and when you increment it.<br />

– You read shared data and then use it, forgetting that it could<br />

change between when you read it and when you use it<br />

• You look up size of a List, then loop from 0 to size-1. But, another<br />

thread could remove elements in between.<br />

714<br />

jeudi 26 janvier 12


Race Conditions: Example<br />

public class RaceConditionsActivity extends Activity<br />

implements Runnable {<br />

private final static int LOOP_LIMIT = 3;<br />

private final static int POOL_SIZE = 4;<br />

private int mLatestThreadNum = 0;<br />

715<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.race_conditions);<br />

}<br />

public void tryRace(View clickedButton) {<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(POOL_SIZE);<br />

for(int i=0; i


}<br />

Race Conditions: Example<br />

(Continued)<br />

public void run() {<br />

int currentThreadNum = mLatestThreadNum;<br />

System.out.printf("Setting currentNum to %s%n",<br />

currentThreadNum);<br />

mLatestThreadNum = mLatestThreadNum + 1;<br />

for (int i = 0; i < LOOP_LIMIT; i++) {<br />

System.out.printf("I am Counter %s; i is %s%n",<br />

currentThreadNum, i);<br />

ThreadUtils.pause(0.5 * Math.random());<br />

}<br />

}<br />

• What’s wrong with this co<strong>de</strong>?<br />

716<br />

jeudi 26 janvier 12


Race Conditions: Result<br />

• Usual Output<br />

Setting currentNum to 0<br />

I am Counter 0; i is 0<br />

Setting currentNum to 1<br />

I am Counter 1; i is 0<br />

Setting currentNum to 2<br />

I am Counter 2; i is 0<br />

Setting currentNum to 3<br />

I am Counter 3; i is 0<br />

I am Counter 0; i is 1<br />

I am Counter 2; i is 1<br />

I am Counter 3; i is 1<br />

I am Counter 1; i is 1<br />

I am Counter 0; i is 2<br />

I am Counter 1; i is 2<br />

I am Counter 3; i is 2<br />

I am Counter 2; i is 2<br />

717<br />

jeudi 26 janvier 12<br />

• Occasional Output<br />

Setting currentNum to 36<br />

I am Counter 36; i is 0<br />

Setting currentNum to 37<br />

I am Counter 37; i is 0<br />

Setting currentNum to 38<br />

Setting currentNum to 38<br />

I am Counter 38; i is 0<br />

I am Counter 38; i is 0<br />

I am Counter 36; i is 1<br />

I am Counter 38; i is 1<br />

I am Counter 37; i is 1<br />

I am Counter 38; i is 1<br />

I am Counter 36; i is 2<br />

I am Counter 38; i is 2<br />

I am Counter 37; i is 2<br />

I am Counter 38; i is 2


Race Conditions: Solution?<br />

• Do things in a single step<br />

718<br />

jeudi 26 janvier 12<br />

public void run() {<br />

int currentThreadNum = mLatestThreadNum++;<br />

System.out.printf("Setting currentNum to %s%n",<br />

currentThreadNum);<br />

for (int i = 0; i < LOOP_LIMIT; i++) {<br />

System.out.printf("I am Counter %s; i is %s%n",<br />

currentThreadNum, i);<br />

ThreadUtils.pause(0.5 * Math.random());<br />

}<br />

}<br />

This “solution” does not fix the problem. In some ways, it makes it worse!


Arbitrating Contention for Shared<br />

Resources<br />

• Synchronizing a section of co<strong>de</strong><br />

synchronized(someObject) {<br />

co<strong>de</strong><br />

}<br />

• Fixing the previous race condition<br />

public void run() {<br />

int currentThreadNum;<br />

synchronized(this) {<br />

currentThreadNum = mLatestThreadNum;<br />

System.out.printf("Setting currentNum to %s%n",<br />

currentThreadNum);<br />

mLatestThreadNum = mLatestThreadNum + 1;<br />

}<br />

for (int i = 0; i < LOOP_LIMIT; i++) {<br />

...<br />

}<br />

}<br />

719<br />

jeudi 26 janvier 12


Arbitrating Contention for Shared<br />

Resources<br />

• Synchronizing a section of co<strong>de</strong><br />

synchronized(someObject) {<br />

co<strong>de</strong><br />

}<br />

• Simplistic interpretation<br />

–Once a thread enters the co<strong>de</strong>, no other thread can enter until<br />

the first thread exits.<br />

• Stronger interpretation<br />

720<br />

jeudi 26 janvier 12<br />

–Once a thread enters the co<strong>de</strong>, no other thread can enter any<br />

section of co<strong>de</strong> that is synchronized using the same “lock”<br />

object<br />

• If two pieces of co<strong>de</strong> say “synchronized(blah)”, the question is if<br />

the blah’s are the same object instance.


Arbitrating Contention for Shared<br />

Resources<br />

• Synchronizing an entire method<br />

public synchronized void someMethod() {<br />

body<br />

}<br />

• Note that this is equivalent to<br />

721<br />

jeudi 26 janvier 12<br />

public void someMethod() {<br />

synchronized(this) {<br />

body<br />

}<br />

}


722<br />

jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Helpful Thread-Related<br />

Methods<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Methods in Thread Class<br />

• Thread.currentThread()<br />

–Gives instance of Thread that is running current co<strong>de</strong><br />

• Thread.sleep(milliseconds)<br />

–Puts calling co<strong>de</strong> to sleep. Useful for non-busy waiting in all<br />

kinds of co<strong>de</strong>, not just multithrea<strong>de</strong>d co<strong>de</strong>. You must catch<br />

InterruptedException, but you can ignore it:<br />

• try { Thread.sleep(someMilliseconds); }<br />

catch (InterruptedException ie) { }<br />

–See also TimeUnit.SECONDS.sleep,<br />

TimeUnit.MINUTES.sleep, etc.<br />

• Same i<strong>de</strong>a except takes sleep time in different units.<br />

• someThread.getName(), someThread.getId()<br />

723<br />

jeudi 26 janvier 12<br />

–Useful for printing/<strong>de</strong>bugging, to tell threads apart


Methods in ExecutorService<br />

Class<br />

• execute(Runnable)<br />

– Adds Runnable to the queue of tasks<br />

• shutdown<br />

– Prevents any more tasks from being ad<strong>de</strong>d with execute (or<br />

submit), but lets current tasks finish.<br />

• shutdownNow<br />

– Attempts to halt current tasks. But author of tasks must have them<br />

respond to interrupts (ie, catch InterruptedException), or this is<br />

no different from shutdown.<br />

• awaitTermination<br />

– Blocks until all tasks are complete. Must shutdown() first.<br />

• submit, invokeAny, invokeAll<br />

– Variations that use Callable instead of Runnable. See next sli<strong>de</strong><br />

on Callable.<br />

724<br />

jeudi 26 janvier 12


Callable<br />

• Runnable<br />

–“run” method runs in background. No return values, but run<br />

can do si<strong>de</strong> effects.<br />

–Use “execute” to put in task queue<br />

• Callable<br />

725<br />

jeudi 26 janvier 12<br />

–“call” method runs in background. It returns a value that can<br />

be retrieved after termination with “get”.<br />

–Use “submit” to put in task queue.<br />

–Use invokeAny and invokeAll to block until value or values<br />

are available<br />

• Example: you have a list of links from a Web page and want to<br />

check status (404 vs. good). Submit them to a task queue to run<br />

concurrently, then invokeAll will let you see return values when<br />

all links are done being checked.


Lower-Level Threading<br />

• Use Thread.start(someRunnable)<br />

– Implement Runnable, pass to Thread constructor, call start<br />

• Thread t = new Thread(someRunnable);<br />

• t.start();<br />

– About same effect as taskList.execute(someRunnable), except<br />

that you cannot put bound on number of simultaneous threads.<br />

– Mostly a carryover from pre-Java-5 days; still wi<strong>de</strong>ly used.<br />

• Extend Thread<br />

– Put run method in Thread subclass, instantiate, call start<br />

• SomeThreadSubclass t = new SomeThreadSubclass(…);<br />

• t.start();<br />

– A holdover from pre-Java-5; has little use in mo<strong>de</strong>rn Java<br />

applications (Android or otherwise)<br />

726<br />

jeudi 26 janvier 12


727<br />

jeudi 26 janvier 12<br />

Advanced Topics<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Types of Task Queues<br />

• Executors.newFixedThreadPool(nThreads)<br />

– Simplest and most wi<strong>de</strong>ly used type. Makes a list of tasks to be run in the<br />

background, but with caveat that there are never more than nThreads<br />

simultaneous threads running.<br />

• Executors.newScheduledThreadPool<br />

– Lets you <strong>de</strong>fine tasks that run after a <strong>de</strong>lay, or that run periodically.<br />

Replacement for pre-Java-5 “Timer” class.<br />

• Executors.newCachedThreadPool<br />

– Optimized version for apps that start many short-running threads. Reuses<br />

thread instances.<br />

• Executors.newSingleThreadExecutor<br />

– Makes queue of tasks and executes one at a time<br />

• ExecutorService (subclass) constructors<br />

– Lets you build FIFO, LIFO, and priority queues<br />

728<br />

jeudi 26 janvier 12


Stopping a Thread<br />

public class SomeTask implements Runnable {<br />

private volatile boolean running;<br />

}<br />

729<br />

jeudi 26 janvier 12<br />

public void run(){<br />

running = true;<br />

while (running) {<br />

...<br />

}<br />

doCleanup();<br />

}<br />

public void setRunning(boolean running) {<br />

this.running = running;<br />

}<br />

Compilers on multicore systems often do optimizations that prevent changes to<br />

variables from one thread from being seen by another thread. To guarantee that<br />

other threads see your changes, either use synchronized methods, <strong>de</strong>clare the<br />

variable “volatile”, or use AtomicBoolean.


Nasty Synchronization Bug<br />

public class Driver {<br />

public void startThreads() {<br />

…<br />

for(…) {<br />

taskList.execute(new SomeThrea<strong>de</strong>dClass());<br />

}}}<br />

public class SomeThrea<strong>de</strong>dClass implements Runnable {<br />

public synchronized void doSomeOperation() {<br />

accessSomeSharedObject();<br />

}<br />

...<br />

public void run() {<br />

while(someCondition) {<br />

doSomeOperation(); // Accesses shared data<br />

doSomeOtherOperation();// No shared data<br />

}<br />

}<br />

}<br />

730<br />

jeudi 26 janvier 12


Synchronization Solution<br />

• Solution 1: synchronize on the shared data<br />

public void doSomeOperation() {<br />

synchronized(someSharedObject) {<br />

accessSomeSharedObject();<br />

}<br />

}<br />

• Solution 2: synchronize on the class object<br />

public void doSomeOperation() {<br />

synchronized(SomeThrea<strong>de</strong>dClass.class) {<br />

accessSomeSharedObject();<br />

}<br />

}<br />

731<br />

jeudi 26 janvier 12<br />

– Note that if you synchronize a static method, the lock is the<br />

corresponding Class object, not this


Synchronization Solution<br />

(Continued)<br />

• Solution 3: synchronize on arbitrary object<br />

732<br />

jeudi 26 janvier 12<br />

public class SomeThrea<strong>de</strong>dClass<br />

implements Runnable{<br />

private static Object lockObject<br />

= new Object();<br />

...<br />

public void doSomeOperation() {<br />

synchronized(lockObject) {<br />

accessSomeSharedObject();<br />

}<br />

}<br />

...<br />

}<br />

– Why doesn’t this problem usually occur with thread mechanism<br />

two (with run method in main class)?


Determining Maximum Thread<br />

Pool Size<br />

• In most apps, a reasonable guess is fine<br />

int maxThreads = 50;<br />

ExecutorService tasks =<br />

Executors.newFixedThreadPool(maxThreads);<br />

• For more precision, you can use equation<br />

733<br />

jeudi 26 janvier 12<br />

maxThreads = numCpus * targetUtilization *<br />

(1 + avgWaitTime/avgComputeTime)<br />

• Compute numCpus with<br />

Runtime.getRuntime().availableProcessors()<br />

• targetUtilization is from 0.0 to 1.0<br />

• Find ratio of wait to compute time with profiling<br />

• Equation taken from Java Concurrency in Practice


Other Advanced Topics<br />

• wait/waitForAll<br />

– Releases the lock for other threads and suspends itself (placed in a wait<br />

queue associated with the lock)<br />

– Very important in some applications, but very, very hard to get right. Try<br />

to use the newer Executor services if possible.<br />

• notify/notifyAll<br />

– Wakes up all threads waiting for the lock<br />

– A notified thread doesn’t begin immediate execution, but is placed in the<br />

runnable thread queue<br />

• Concurrency utilities in java.util.concurrency<br />

– Advanced threading utilities including semaphores, collections <strong>de</strong>signed<br />

for multithrea<strong>de</strong>d applications, atomic operations, etc.<br />

• Debugging thread problems<br />

– Use JConsole (bundled with Java 5; officially part of Java 6)<br />

• http://java.sun.com/<strong>de</strong>veloper/technicalArticles/J2SE/jconsole.html<br />

734<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• Books<br />

–Java Concurrency in Practice (Goetz, et al)<br />

–Chapter 10 (“Concurrency”) of Effective Java, 2 nd Ed (Josh<br />

Bloch)<br />

• Effective Java is the alltime best Java practices book<br />

–Java Threads (Oak and Wong)<br />

• Online references<br />

736<br />

jeudi 26 janvier 12<br />

–Lesson: Concurrency (Oracle Java Tutorial)<br />

• http://download.oracle.com/javase/tutorial/essential/concurrency/<br />

–Jacob Jenkov’s Concurrency Tutorial<br />

• http://tutorials.jenkov.com/java-concurrency/in<strong>de</strong>x.html<br />

–Lars Vogel’s Concurrency Tutorial<br />

• http://www.vogella.<strong>de</strong>/articles/JavaConcurrency/article.html


Summary<br />

• Basic approach<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(poolSize);<br />

• Three variations<br />

–taskList.execute(new SeparateClass(…));<br />

–taskList.execute(this);<br />

–taskList.execute(new InnerClass(…));<br />

• Handling shared data<br />

737<br />

jeudi 26 janvier 12<br />

synchronized(referenceSharedByThreads) {<br />

}<br />

getSharedData();<br />

modifySharedData();<br />

doOtherStuff();


jeudi 26 janvier 12<br />

© 2011 Marty Hall<br />

Multithrea<strong>de</strong>d Programming Part II:<br />

Android-Specific Techniques<br />

Originals of Sli<strong>de</strong>s and Source Co<strong>de</strong> for Examples:<br />

http://www.coreservlets.com/android-tutorial/<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Topics in This Section<br />

• GUI update gui<strong>de</strong>lines<br />

• Updating UI after threads complete<br />

• Downloading images from Internet<br />

• Updating UI with View.post<br />

• Updating UI with AsyncTask<br />

739<br />

jeudi 26 janvier 12


740<br />

jeudi 26 janvier 12<br />

Overview<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Issues<br />

• Nonresponsive GUI controls<br />

–Long-running co<strong>de</strong> in main thread will make GUI controls<br />

nonresponsive.<br />

• Threads cannot update user interface<br />

741<br />

jeudi 26 janvier 12<br />

–Background threads are prohibited from updating UI.


Nonresponsive GUI Controls<br />

• Problem<br />

–Long-running co<strong>de</strong> in main thread will make GUI controls<br />

nonresponsive.<br />

• For example, if a Button’s onClick handler takes 5 seconds, then<br />

none of the other controls will respond for 5 seconds.<br />

• Solution<br />

742<br />

jeudi 26 janvier 12<br />

–Move time-consuming operations to background threads<br />

• This was the entire point of the previous lecture on the basics of<br />

multithrea<strong>de</strong>d programming


Threads Cannot Update UI<br />

• Problem<br />

– Background threads are prohibited from updating UI.<br />

• E.g., background threads cannot add a new View to the display, nor can<br />

they call setText on a visible View.<br />

• Solutions (alternatives)<br />

– Wait until all threads are done, then update UI<br />

743<br />

jeudi 26 janvier 12<br />

• When multithreading improves performance, but total wait time is small<br />

– Have background threads use View.post to send UI-updating operations<br />

back to UI thread<br />

• Especially when transitioning standard threading co<strong>de</strong> to Android<br />

– Use AsyncTask to divi<strong>de</strong> tasks between background and UI threads<br />

• Especially when <strong>de</strong>veloping for Android from beginning and you have a lot<br />

of incremental GUI updates.


jeudi 26 janvier 12<br />

Updating UI After<br />

Threads Complete<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Updating UI All at Once<br />

• Scenario<br />

–Using threads improves performance.<br />

–Total wait time is small, so no need to display intermediate<br />

results.<br />

• Approach<br />

745<br />

jeudi 26 janvier 12<br />

–Add threads to ExecutorService task list.<br />

–Use awaitTermination to wait until all tasks are finished (or a<br />

timeout is excee<strong>de</strong>d)<br />

–Update UI. You are in UI thread, so this is safe/legal.


Example: Multi-URL Validator<br />

• I<strong>de</strong>a<br />

–Let user enter any number of URLs<br />

–Check if they are legal by making HTTP HEAD requests and<br />

checking the server status line<br />

• Approach<br />

746<br />

jeudi 26 janvier 12<br />

–Make a List of URL result hol<strong>de</strong>rs<br />

–For each URL, pass result hol<strong>de</strong>r to background thread.<br />

Background thread stores result in hol<strong>de</strong>r. Use inner class for<br />

background thread implementation.<br />

–After all tasks are complete or 10 seconds have elapsed<br />

(whichever is sooner), show results in ScrollView


Main Activity: Setup Co<strong>de</strong><br />

public class UrlCheckerActivity extends Activity {<br />

private LinearLayout mResultsRegion;<br />

private EditText mUrlsToTest;<br />

private int mGoodUrlColor, mForwar<strong>de</strong>dUrlColor,<br />

mBadUrlColor;<br />

private Drawable mGoodUrlIcon, mForwar<strong>de</strong>dUrlIcon,<br />

mBadUrlIcon;<br />

List mResultsHol<strong>de</strong>r =<br />

new ArrayList();<br />

private final static int HEAD_TIMEOUT = 10;<br />

private float mResultTextSize;<br />

private int mResultPaddingSize;<br />

747<br />

jeudi 26 janvier 12


Main Activity: Setup Co<strong>de</strong><br />

(Continued)<br />

748<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.url_checker);<br />

mUrlsToTest = (EditText)findViewById(R.id.urls_to_test);<br />

mResultsRegion = (LinearLayout)findViewById(R.id.results_region);<br />

Resources resources = getResources();<br />

mGoodUrlColor = resources.getColor(R.color.url_good);<br />

mForwar<strong>de</strong>dUrlColor = resources.getColor(R.color.url_forwar<strong>de</strong>d);<br />

mBadUrlColor = resources.getColor(R.color.url_bad);<br />

mGoodUrlIcon = resources.getDrawable(R.drawable.emo_im_happy);<br />

mForwar<strong>de</strong>dUrlIcon = resources.getDrawable(R.drawable.emo_im_wtf);<br />

mBadUrlIcon = resources.getDrawable(R.drawable.emo_im_sad);<br />

mResultTextSize =<br />

resources.getDimension(R.dimen.url_checker_result_size);<br />

mResultPaddingSize =<br />

(int)resources.getDimension(R.dimen.url_checker_padding_size);


Main Activity: Button Handler<br />

(Starts Threads)<br />

749<br />

jeudi 26 janvier 12<br />

public void checkUrls(View clickedButton) {<br />

mResultsRegion.removeAllViews();<br />

mResultsRegion.requestLayout();<br />

String[] urls =<br />

mUrlsToTest.getText().toString().split("\\s+");<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(50);<br />

for (String url: urls) {<br />

UrlCheckerResult resultHol<strong>de</strong>r =<br />

new UrlCheckerResult(url);<br />

mResultsHol<strong>de</strong>r.add(resultHol<strong>de</strong>r);<br />

taskList.execute(new UrlTester(resultHol<strong>de</strong>r));<br />

}<br />

try {<br />

taskList.shutdown();<br />

taskList.awaitTermination(HEAD_TIMEOUT,<br />

TimeUnit.SECONDS);<br />

} catch (InterruptedException e) {}


Main Activity: Button Handler<br />

(After Threads Complete)<br />

750<br />

jeudi 26 janvier 12<br />

for(UrlCheckerResult resultHol<strong>de</strong>r: mResultsHol<strong>de</strong>r) {<br />

UrlChecker result = resultHol<strong>de</strong>r.getUrlResult();<br />

if (result == null) {<br />

result =<br />

new UrlChecker(resultHol<strong>de</strong>r.getUrlString(),<br />

HEAD_TIMEOUT);<br />

}<br />

TextView displayedResult = new TextView(this);<br />

displayedResult.setTextColor(chooseColor(result));<br />

displayedResult.setTextSize(mResultTextSize);<br />

displayedResult.setText(result.toString());<br />

displayedResult.setCompoundDrawablesWithIntrinsicBounds<br />

(chooseIcon(result), null, null, null);<br />

displayedResult.setCompoundDrawablePadding<br />

(mResultPaddingSize);<br />

mResultsRegion.addView(displayedResult);<br />

}<br />

}<br />

It would have been be illegal to do this in the background<br />

thread, because it changes the visible UI. Creating the<br />

TextView would have been legal, but adding it to the<br />

vertical LinearLayout insi<strong>de</strong> the ScrollView (as done here)<br />

would have been illegal.


Main Activity:<br />

Runnable Inner Class<br />

751<br />

jeudi 26 janvier 12<br />

private class UrlTester implements Runnable {<br />

private UrlCheckerResult mResultHol<strong>de</strong>r;<br />

}<br />

public UrlTester(UrlCheckerResult resultHol<strong>de</strong>r) {<br />

mResultHol<strong>de</strong>r = resultHol<strong>de</strong>r;<br />

}<br />

public void run() {<br />

UrlChecker result =<br />

new UrlChecker(mResultHol<strong>de</strong>r.getUrlString());<br />

mResultHol<strong>de</strong>r.setUrlResult(result);<br />

}<br />

The run method does not update the UI directly. Instead, it updates a data<br />

structure that will later be read and then used to update the UI (co<strong>de</strong> that<br />

does this was shown on previous sli<strong>de</strong>).<br />

The UrlChecker class does the actual network calls. Since different servers can respond<br />

at different speeds, calling UrlChecker in a background thread can substantially improve<br />

performance.


Main Activity:<br />

Helper Methods<br />

752<br />

jeudi 26 janvier 12<br />

private int chooseColor(UrlChecker urlResult) {<br />

if (urlResult.isGood()) {<br />

return(mGoodUrlColor);<br />

} else if (urlResult.isForwar<strong>de</strong>d()) {<br />

return(mForwar<strong>de</strong>dUrlColor);<br />

} else {<br />

return(mBadUrlColor);<br />

}<br />

}<br />

private Drawable chooseIcon(UrlChecker urlResult) {<br />

if (urlResult.isGood()) {<br />

return(mGoodUrlIcon);<br />

} else if (urlResult.isForwar<strong>de</strong>d()) {<br />

return(mForwar<strong>de</strong>dUrlIcon);<br />

} else {<br />

return(mBadUrlIcon);<br />

}<br />

}<br />

I use different text colors and different icons <strong>de</strong>pending on<br />

whether the URL is good, forwar<strong>de</strong>d, or bad.


Main Helper Classes<br />

• UrlChecker<br />

–Makes a HEAD request and parses status line. If status co<strong>de</strong><br />

is 301 or 302, looks up Location hea<strong>de</strong>r.<br />

• Most of the co<strong>de</strong> shown in earlier lecture on Networking<br />

• UrlCheckerResult<br />

753<br />

jeudi 26 janvier 12<br />

–Stores a URL and the associated UrlChecker result.<br />

• The timeout could be excee<strong>de</strong>d before the results are found, in<br />

which case the UrlChecker is null. In that scenario, we display a<br />

message that shows the URL and says that no result was found<br />

within the allotted time.


Results<br />

754<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Downloading<br />

Web Images<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


Displaying a Network Image<br />

• I<strong>de</strong>a<br />

–The <strong>de</strong>co<strong>de</strong>Stream method of BitmapFactory can take an<br />

InputStream and produce a Bitmap. You can put a Bitmap into<br />

an ImageView<br />

• Approach<br />

756<br />

jeudi 26 janvier 12<br />

–Get an HttpURLConnection (as explained in second<br />

networking lecture)<br />

–Get the input stream with connection.getInputStream()<br />

–Pass the stream to BitmapFactory.<strong>de</strong>co<strong>de</strong>Stream and store<br />

result in Bitmap<br />

–Get a reference to an ImageView and pass new Bitmap to<br />

setImageBitmap


BitmapUtils: Getting a Bitmap<br />

public class BitmapUtils {<br />

public static Bitmap bitmapFromUrl(String urlString)<br />

throws MalformedURLException, IOException {<br />

URL url = new URL(urlString);<br />

HttpURLConnection urlConnection =<br />

(HttpURLConnection)url.openConnection();<br />

InputStream in = urlConnection.getInputStream();<br />

Bitmap bitmapImage = BitmapFactory.<strong>de</strong>co<strong>de</strong>Stream(in);<br />

urlConnection.disconnect();<br />

return(bitmapImage);<br />

}<br />

757<br />

jeudi 26 janvier 12


Making a View for an Image<br />

• I<strong>de</strong>a<br />

–Given an address, try to load a Bitmap from it. If successful,<br />

make an ImageView showing the Bitmap. If unsuccessful,<br />

make a TextView showing information on the error.<br />

• Approach<br />

758<br />

jeudi 26 janvier 12<br />

–Call BitmapUtils.bitmapFromUrl.<br />

• If no Exception, instantiate ImageView and pass Bitmap to<br />

setImageBitmap.<br />

• If Exception, instantiate TextView and store an error message in<br />

it.


BitmapUtils:<br />

Getting a View for an Image<br />

public static View viewForImage(String urlString, Context context) {<br />

Bitmap bitmapImage = null;<br />

String errorMessage = "";<br />

try {<br />

bitmapImage = BitmapUtils.bitmapFromUrl(urlString);<br />

} catch (MalformedURLException mue) {<br />

errorMessage = String.format("Malformed URL %s", urlString);<br />

} catch (IOException ioe) {<br />

errorMessage = String.format("Error downloading image: %s",<br />

ioe.getMessage());<br />

}<br />

if (bitmapImage != null) {<br />

ImageView displayedImage = new ImageView(context);<br />

displayedImage.setImageBitmap(bitmapImage);<br />

displayedImage.setPadding(5, 5, 5, 5);<br />

return(displayedImage);<br />

} else {<br />

TextView displayedMessage = new TextView(context);<br />

displayedMessage.setText(errorMessage);<br />

return(displayedMessage);<br />

}<br />

}<br />

759<br />

jeudi 26 janvier 12


Example:<br />

Unthrea<strong>de</strong>d Image Viewer<br />

• I<strong>de</strong>a<br />

–Let user enter URL of an image to be displayed<br />

–Either show that image, or show error message<br />

• Approach<br />

760<br />

jeudi 26 janvier 12<br />

–Read the address from EditText, pass to<br />

BitmapUtils.viewForImage<br />

–Add resultant View to the layout


Activity<br />

public class SimpleImageDownloa<strong>de</strong>rActivity extends Activity {<br />

private LinearLayout mMainWindow;<br />

private EditText mImageToDownload;<br />

private View mViewForImage;<br />

}<br />

761<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.simple_image_downloa<strong>de</strong>r);<br />

mMainWindow = (LinearLayout)findViewById(R.id.main_window);<br />

mImageToDownload =<br />

(EditText)findViewById(R.id.image_to_download);<br />

}<br />

public void downloadImage(View clickedButton) {<br />

if (mViewForImage != null) {<br />

mMainWindow.removeView(mViewForImage);<br />

}<br />

String imageUrl = mImageToDownload.getText().toString();<br />

mViewForImage = BitmapUtils.viewForImage(imageUrl, this);<br />

mMainWindow.addView(mViewForImage);<br />

}


Results<br />

762<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Updating UI with<br />

View.post<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


View.post<br />

• Scenario<br />

–Total wait time might be large, so you want to show<br />

intermediate results<br />

–You have a lot of normal threading co<strong>de</strong> but you occasionally<br />

need to update UI.<br />

• Approach<br />

764<br />

jeudi 26 janvier 12<br />

–When background thread has result that should affect UI,<br />

create a Runnable and pass to post<br />

public void run() { // Background thread<br />

doStuffButDontUpdateUI();<br />

someView.post(new Runnable() {<br />

public void run() { updateUI(); }});<br />

}


Example: Multithrea<strong>de</strong>d Image<br />

Viewer (Version 1)<br />

• I<strong>de</strong>a<br />

–Let user enter URLs of images to be displayed<br />

–Download and display them insi<strong>de</strong> a scrolling horizontal<br />

LinearLayout<br />

• Approach<br />

765<br />

jeudi 26 janvier 12<br />

–Download images and associate them with ImageView, as<br />

shown in the previous subsection. If there was an error, create<br />

a TextView saying so.<br />

–Create a Runnable that will add the resultant View to the<br />

LinearLayout<br />

–Pass that Runnable to the post method of the LinearLayout


Main Activity: Setup Co<strong>de</strong><br />

public class ImageDownloa<strong>de</strong>r1Activity extends Activity {<br />

protected LinearLayout mResultsRegion;<br />

protected EditText mImagesToDownload;<br />

766<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onCreate(Bundle savedInstanceState) {<br />

super.onCreate(savedInstanceState);<br />

setContentView(R.layout.image_downloa<strong>de</strong>r);<br />

mImagesToDownload =<br />

(EditText)findViewById(R.id.images_to_download);<br />

mResultsRegion =<br />

(LinearLayout)findViewById(R.id.results_region);<br />

}


Main Activity: Button Handler<br />

767<br />

jeudi 26 janvier 12<br />

public void downloadImages(View clickedButton) {<br />

mResultsRegion.removeAllViews();<br />

mResultsRegion.requestLayout();<br />

String[] images =<br />

mImagesToDownload.getText().toString().split("\\s+");<br />

addImages(images);<br />

}<br />

protected void addImages(String[] images) {<br />

ExecutorService taskList =<br />

Executors.newFixedThreadPool(50);<br />

for (String image: images) {<br />

taskList.execute(new ImageDownloa<strong>de</strong>r(image));<br />

}<br />

}<br />

The event handler is split into two methods because the next<br />

example will extend this class and overri<strong>de</strong> addImages, but<br />

will keep the inherited version of downloadImages<br />

unchanged.


Main Activity: Runnable Inner<br />

Class (For Background)<br />

768<br />

private class ImageDownloa<strong>de</strong>r implements Runnable {<br />

private String mImageUrl;<br />

}<br />

jeudi 26 janvier 12<br />

public ImageDownloa<strong>de</strong>r(String imageUrl) {<br />

mImageUrl = imageUrl;<br />

}<br />

public void run() {<br />

View viewToAdd =<br />

BitmapUtils.viewForImage(mImageUrl,<br />

ImageDownloa<strong>de</strong>r1Activity.this);<br />

mResultsRegion.post(new ViewAd<strong>de</strong>r(viewToAdd));<br />

}<br />

This is the task that the ExecutorService executes. It calls viewForImage, a time-consuming<br />

task that loads an image from the network and associates it with an ImageView (or a<br />

TextView if there was an error). The View is then sent to the main UI thread by putting it in a<br />

Runnable and passing the Runnable to the post method of a View that is in the main Activity.


Main Activity: Runnable Inner<br />

Class (For UI Thread)<br />

769<br />

jeudi 26 janvier 12<br />

private class ViewAd<strong>de</strong>r implements Runnable {<br />

private View mViewToAdd;<br />

}<br />

public ViewAd<strong>de</strong>r(View viewToAdd) {<br />

mViewToAdd = viewToAdd;<br />

}<br />

public void run() {<br />

mResultsRegion.addView(mViewToAdd);<br />

}<br />

This changes the UI, so could not have been<br />

done in the background.


Results<br />

770<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Updating UI with<br />

AsyncTask<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


AsyncTask<br />

• Scenario<br />

– Total wait time might be large, so you want to show intermediate<br />

results<br />

– You are <strong>de</strong>signing co<strong>de</strong> from the beginning to divi<strong>de</strong> the work<br />

between GUI and non-GUI co<strong>de</strong><br />

• Approach<br />

– Use AsyncTask with doInBackground & onPostExecute<br />

772<br />

jeudi 26 janvier 12<br />

private class MixedTask extends AsyncTask {<br />

public SomeType doInBackground(…) {<br />

doNonGuiStuff();<br />

return(valueForUiThread);<br />

}<br />

public void onPostExecute(SomeType valueForUiThread) {<br />

doGuiStuffWith(valueForUiThread);<br />

}<br />

}


AsyncTask: Quick Example<br />

• Task itself<br />

private class ImageDownloadTask extends AsyncTask {<br />

public View doInBackground(String... urls) {<br />

return(BitmapUtils.viewForImage(urls[0], MainActivity.this));<br />

}<br />

}<br />

public void onPostExecute(View viewToAdd) {<br />

mResultsRegion.addView(viewToAdd);<br />

}<br />

• Invoking task<br />

String imageAddress = "http://…";<br />

ImageDownloadTask task = new ImageDownloadTask();<br />

task.execute(imageAddress);<br />

773<br />

jeudi 26 janvier 12


AsyncTask Details: Constructor<br />

• Class is genericized with three arguments<br />

– AsyncTask<br />

• Interpretation<br />

– ParamType<br />

• This is the type you pass to execute, which in turn is the type that is<br />

send to doInBackground. Both methods use varargs, so you can send<br />

any number of params.<br />

– ProgressType<br />

• This is the type that you pass to publishProgress, which in turn is<br />

passed to onProgressUpdate (which is called in UI thread). Use Void<br />

if you do not need to display intermediate progress.<br />

– ResultType<br />

• This is the type that you should return from doInBackground, which in<br />

turn is passed to onPostExecute (which is called in UI thread).<br />

774<br />

jeudi 26 janvier 12


AsyncTask Details:<br />

doInBackground<br />

• I<strong>de</strong>a<br />

–This is the co<strong>de</strong> that gets executed in the background. It<br />

cannot update the UI.<br />

–It takes as arguments whatever was passed to execute<br />

–It returns a result that will be later passed to onPostExecute in<br />

the UI thread.<br />

• Co<strong>de</strong><br />

private class SomeTask extends AsyncTask {<br />

public Type2 doInBackground(Type1... params) {<br />

return(doNonUiStuffWith(params));<br />

} ...<br />

}<br />

…<br />

775<br />

jeudi 26 janvier 12<br />

new SomeTask().execute(type1VarA, type1VarB);<br />

The … in the doInBackground <strong>de</strong>claration is actually part<br />

of the Java syntax, indicating varargs.


AsyncTask Details:<br />

doPostExecute<br />

• I<strong>de</strong>a<br />

–This is the co<strong>de</strong> that gets executed by the UI thread. It can<br />

update the UI.<br />

–It takes as an argument whatever was returned by<br />

doInBackground<br />

• Co<strong>de</strong><br />

private class SomeTask extends AsyncTask {<br />

public Type2 doInBackground(Type1... params) {<br />

return(doNonUiStuffWith(params));<br />

}<br />

public void doPostExecute(Type2 result) { doUiStuff(result); }<br />

}<br />

…<br />

new SomeTask().execute(type1VarA, type1VarB);<br />

776<br />

jeudi 26 janvier 12


AsyncTask Details:<br />

Other Methods<br />

• onPreExecute<br />

–Invoked by the UI thread before doInBackground starts<br />

• publishProgress<br />

–Sends an intermediate update value to onProgressUpdate. You<br />

call this from co<strong>de</strong> that is in doInBackground. The type is the<br />

middle value of the class <strong>de</strong>claration.<br />

• onProgressUpdate<br />

–Invoked by the UI thread. Takes as input whatever was passed<br />

to publishProgress.<br />

• Note<br />

777<br />

jeudi 26 janvier 12<br />

–All of these methods can be omitted.


Example: Multithrea<strong>de</strong>d Image<br />

Viewer (Version 2)<br />

• I<strong>de</strong>a<br />

–Let user enter URLs of images to be displayed<br />

–Download and display them insi<strong>de</strong> a scrolling horizontal<br />

LinearLayout<br />

• Approach<br />

778<br />

jeudi 26 janvier 12<br />

–Extend previous example. Make an AsyncTask<br />

–doInBackground<br />

• Download images and associate them with ImageView, as shown<br />

in the previous subsection. If there was an error, create a<br />

TextView saying so. Return that View.<br />

–doPostExecute<br />

• Add the View to the LinearLayout


Activity<br />

public class ImageDownloa<strong>de</strong>r2Activity extends ImageDownloa<strong>de</strong>r1Activity {<br />

@Overri<strong>de</strong><br />

protected void addImages(String[] images) {<br />

for (String image: images) {<br />

ImageDownloadTask task = new ImageDownloadTask();<br />

task.execute(image);<br />

}<br />

}<br />

}<br />

779<br />

private class ImageDownloadTask extends AsyncTask {<br />

@Overri<strong>de</strong><br />

public View doInBackground(String... urls) {<br />

return(BitmapUtils.viewForImage(urls[0],<br />

ImageDownloa<strong>de</strong>r2Activity.this));<br />

}<br />

}<br />

jeudi 26 janvier 12<br />

@Overri<strong>de</strong><br />

public void onPostExecute(View viewToAdd) {<br />

mResultsRegion.addView(viewToAdd);<br />

}


Results<br />

780<br />

jeudi 26 janvier 12


jeudi 26 janvier 12<br />

Wrap-Up<br />

© 2011 Marty Hall<br />

Customized Java EE Training: http://courses.coreservlets.com/<br />

Servlets, JSP, JSF 2.0, Java 6, Ajax, jQuery, GWT, Spring, Hibernate, RESTful Web Services, Android.<br />

Developed and taught by well-known author and <strong>de</strong>veloper. At public venues or onsite at your location.


More Reading<br />

• JavaDoc<br />

–AsyncTask<br />

• http://<strong>de</strong>veloper.android.com/reference/android/os/AsyncTask.html<br />

• Tutorial: Processes and Threads<br />

–http://<strong>de</strong>veloper.android.com/gui<strong>de</strong>/topics/fundamentals/<br />

processes-and-threads.html<br />

• Chapters<br />

782<br />

jeudi 26 janvier 12<br />

–Threads, Services, Receivers, and Alerts<br />

• From The Android Developer’s Cookbook by Steele & To<br />

–Dealing with Threads<br />

• From The Busy Co<strong>de</strong>r’s Gui<strong>de</strong> to Android Development<br />

by Mark Murphy (http://commonsware.com/Android/)


Summary<br />

• Update UI after all threads done<br />

–Use taskList.awaitTermination<br />

• Update UI incrementally with post<br />

–Main thread does non-GUI stuff. Sends values for UI thread<br />

via someView.post(someRunnable)<br />

• Update UI incrementally with AsyncTask<br />

–doInBackground<br />

• Does non-GUI stuff. Returns value for UI thread.<br />

–doPostExecute<br />

• Does GUI stuff. Uses value from doInBackground<br />

• Loading images from network<br />

783<br />

jeudi 26 janvier 12<br />

–Use HttpURLConnection & BitmapFactory.<strong>de</strong>co<strong>de</strong>Stream

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!