SlideShare une entreprise Scribd logo
1  sur  43
vous présente :




Spécialiste Android Java J2EE




        Auteur du livre

disponible sur
•Android et le monde de l’IT




                               Android et le monde
                                     de l’IT




                                                     2
•Android et le monde de l’IT

•Mettre en place une activité
   oLes acteurs du système : Activity –
   ContentProvider – Service
   oLa structure d’un projet Android
   oLes IHM




                                          Mettre en place une
                                                Activité




                                                                3
•Android et le monde de l’IT
•Mettre en place une activité
•Autour de l’activité :
   oLes Intents
   oLes traitements : Thread et AsyncTask
   oLa gestion des ressources

                                                Autour de
                                                 l’activité




                                            Mettre en place une
                                                  Activité




                                                                  4
•Android et le monde de l’IT

•Mettre en place une activité
•Autour de l’activité
•Autres éléments d’une application:
   oApplication                       Autres éléments de
                                          l’application
   oPermissions
   oPersistance des données               Autour de
                                           l’activité
   oService


                                      Mettre en place une
                                            Activité




                                                            5
•Android et le monde de l’IT

•Mettre en place une activité
                                     Communiquer avec le
•Autour de l’activité                    système

•Autres éléments d’une application
•Communiquer avec le système:         Autres éléments de
                                          l’application
   oInternet
   oCapteur                               Autour de
                                           l’activité




                                     Mettre en place une
                                           Activité




                                                           6
•Android et le monde de l’IT
                                             Autour du projet

•Mettre en place une activité
                                           Communiquer avec le
•Autour de l’activité                          système

•Autres éléments d’une application
•Communiquer avec le système         Android et le monde
                                          Autres éléments de

•Autour du projet                          de l’IT
                                              l’application


   oSigner et Déployer                          Autour de
                                                 l’activité
   oStratégies de tests


                                           Mettre en place une
                                                 Activité




                                                                 7
Formateur Consultant Expert Android
                                           mathias.seguy.it@gmail.com (mail)
                                                 @android2ee (twitter)
                            Auteur d’EBooks sur la programmation Android (Android2ee.com)
                                          Conférencier et Enseignant Android
                                       Docteur en Mathématiques Fondamentales
                                Expert Technique de l'Agence Nationale de la Recherche
                                             Rédacteur sur Developpez.com
                            Blogs Android : Android2EE sur DVP et Android2ee sur BlogSpot
Doctorat Mathématiques
    Fondamentales                               Via CapGemini                       Via Sopra          Naissance Android2EE
              Siemens     Magnus        DGA          CNES       Airbus       Airbus        Airbus      STI         Android2EE
                VDO
      03           04        05           06          07           08               09          10       11             12
                                                                        Java J2EE
                                                                                                              Android
                                                    Manager   Manager
                                       Leader        Leader    Leader                     Leader     Directeur      Fondateur
            Développeur Développeur     IHM        Technique Technique      Manager      Technique   Technique     Android2EE
Master Informatique de                                                   Chez STI
    l’ENSEEIHT

                                                                                                                                8
9
Invasion de la mobilité via les
smartphones:
Le taux de pénétration des
smartphones est exceptionnel, tant
part sa valeur actuelle que par la
rapidité de sa progression.
•486M de smartphones vendus en
2011.
•27% du parc mondial.


Android, l’OS Winner !
En quatre ans, Android est devenu
leader     mondial     du   système
d’exploitation des smartphones, en
terme de stock et en terme de vente.




                                       10
GooglePlay (AndroidMarket) versus AppleStore,
                         la guerre du Market.


Le nombre d’applications sur GooglePlay est en hausse permanente.
    • + 17 391 % en 3 ans
    • + 320 % en 1 an




Le nombre d’applications téléchargées a pour unité le milliard.

    •+500% sur 1 an
    •10 000 000 000 de downloads !

Cette dynamique est la clef de réussite de la plateforme, le facteur
d’adoption.




                                                                       11
La guerre des brevets fait rage dans les grands comptes de l’IT. Depuis l’été 2011,
                               cette guerre fait des ravages dans le monde entier. Le système Android est attaqué
                               par le trio Microsoft-Apple-Oracle et se défend:

                               Apple versus Android : La guerre froide
                               Ces deux-là se mènent une guerre non frontale: Apple attaque les constructeurs et
                               Google rachète Motorola pour 8.6B$.

                               Apple versus HTC et Samsung: La guerre des tribunaux.
                               Interdiction du GalaxyTab en Australie, plainte en Europe et aux Etats Unis… (Depuis
                               peu demande un accord « amiable » entre 5 et 15$ par unité).

                               Microsoft versus Android: La guerre des gangs.
                               Microsoft a su imposer une redevance (5$) à Samsung et à HTC pour chaque unité
                               Android vendue.

                               Oracle Versus Android : l’open-guerre
                               Quand l’open source fait la guerre à l’open source…
                               Plainte déposée par Oracle en 2010 (le procès
                               s’ouvre cette semaine… à suivre).


Vidyanand Kamat/Forbes India




                                                                                                                      12
Aujourd’hui Android envahit la téléphonie mobile.
Demain, Android sera partout: téléphone, tablette, télévision, montres, chaine Hifi, voiture, électroménager, domotique ….
Partout, vous dis-je.




                                                                                                                             13
14
•Les règles
•Les acteurs du système : Activity, Service, ContentProvider et Intent
•La structure d’un projet :
   •Vision globale
   •Le fichier AndroidManifest.xml qui décrit votre application
   •Le fichier layoutmain.xml qui décrit l’IHM de votre activité
   •Le fichier resvaluesstring.xml qui décrit les chaines de caractère de votre application
   •L’activité
•Le test avec l’émulateur




                                                                                                15
Respecter ses données,
    Respecter sa confidentialité.



    Respecter le CPU,
    Respecter la batterie,
    Respecter la mémoire.


Respecter la charte graphique Android,
Respecter les bonnes pratiques du système.
…

                                              16
: Ce sont les programmes vu par l’utilisateur. Ils                           : Les services ont une durée de vie potentiellement infinie
possèdent une I.H.M.                                                           (contrairement aux activités et aux fournisseurs de données). Ce
                                                                               sont des processus qui tournent dans la même Thread que
                      : Ils offrent un niveau d’abstraction pour               l’application sans IHM.
l’accès à toutes les données stockées sur le terminal. Les                           : Ce sont des messages systèmes qui servent de support
données sont identifiées au moyen d’URI (Unified Ressources                    événementiel pour permettre le dialogue entre applications. On
Identifier).                                                                   répond et on envoie des intentions qui lancent ou communiquent
                                                                               avec les activités.


                                                    Listen                                                        Service
                                     Listen
                                                  BroadCastReceiver                     Bind
                                                                 Activity

                                                 StartActivity                          ContentResolver.action(URI,…)

                                                                              CRUD
                                                                            operation
                                                                             return
                                                                                                                  URI
                                                                      ContentProvider
                                                Send
                                       Intent                                                  Find ContentProvider


                                                                                                                                                     17
Un projet Android simple contient les dossiers:
    pour les sources Java
    pour les sources générées à partir du dossier res
   pour les dossiers de ressources:
               pour les images
           pour la définition des composants graphiques
           pour les chaînes de caractères

ainsi que le fichier                       qui est le centre névralgique de votre application. Il
décrit les besoins de votre application, en termes de SDK, de compatibilité matérielle, d’API
utilisées et d’utilisation de services du système. Il décrit ce qu’offre votre application au
système (Activity, ContentProvider, Service…), et les éléments auxquels votre application
réagit au moyen des IntentFilters et d’URI ainsi que les permissions nécessaire pour les
utiliser.




                                                                                                    18
Le fichier AndroidManifest.xml décrit votre application:          <?xml version=“1.0“ encoding=“utf-8“?>
     • son package,                                               <manifest xmlns:android=http://schemas.android.com/apk/res/android
     • son nom,                                                       package= “ com.android2ee.android.tuto.gui“
     • sa version,                                                     android:versionCode=“1“
     • son icône,
                                                                      android:versionName=“1.0“>
     • son label,
                                                                  <application android:icon=“@drawable/icon“
     • la liste des activités qu’elle possède et les intentions
                                                                        android:label=“@string/app_name“>
     auxquelles chacune répond (ici l’Intent démarrage),
                                                                  <activity android:name=“.RadioButtonTuto“
     • ainsi que la version minimale du système nécessaire à
                                                                        android:label=“@string/app_name“>
     la faire fonctionner.
                                                                  <intent-filter>
                                                                   <action android:name=“android.intent.action.MAIN“ />
Il peut aussi déclarer:
     • les services et les content provider qu’elle contient,      <category android:name=“android.intent.category.LAUNCHER“ />
     • les permissions dont elle a besoin et celles qu’elle       </intent-filter>
     procure.                                                     </activity>
                                                                  </application>
Enfin, il peut déclarer les éléments matériels dont elle a        <uses-sdk android:minSdkVersion=“8“ />
besoin.                                                           </manifest>




                                                                                                                                       19
Le fichier des Layouts : layoutmain.xml
Ce fichier décrit les composants graphiques de votre activité.       <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
Ils se placent dans un layout et définissent les propriétés              android:orientation=“vertical“
suivantes (en fonction du besoin):                                       android:layout_width=“fill_parent“
                                                                         android:layout_height=“fill_parent“ >
    • La     manière     dont     ils  remplissent  l’espace         <TextView android:layout_width=“fill_parent“
    (android:layout_width, android:layout_height)                          android:layout_height=“wrap_content“
    • Un identifiant pour pouvoir être récupéré dans le code              android:text=“@string/like“/>
    java (android:id)                                                <CheckBox android:id=“@+id/checkchocolate“
    • Le texte affiché (android:text)                                     android:layout_width=“wrap_content“
    • Le poids du composant (android:layout_weight)                       android:layout_height=“wrap_content“
                                                                          android:text=“@string/chocolate“ />
Ce fichier est interprété par l’activité pour construire son écran
                                                                     <Button android:id=“@+id/btnShow“
via la méthode :
                                                                           android:layout_width=“fill_parent“
setContentView(R.layout.main);
                                                                           android:layout_height=“wrap_content“
                                                                           android:text=“@string/show“/>
Un composant se récupère dans le code par la méthode:
                                                                     </LinearLayout>
btn=(Button)findViewById(R.id.btnShow);




                                                                                                                                              20
Le fichier des chaines de caractères: resvaluesstring.xml                                        valuesstring.xml
                                                                              <resources>
                                                                                <string name=“hello“>Hello World, CheckBoxTuto!</string>
Ce fichier décrit les chaines de caractères utilisables par votre activité.     <string name=“app_name“>CheckBoxTuto</string>
                                                                                <string name=“like“>Do you like :</string>
Chaque chaine est identifiable par un nom et possède une valeur.                <string name=“choice“>Your choice is :</string>
                                                                                <string name=“chocolate“>Chocolate</string>
                                                                               <string name=“nicotine“>Nicotine</string>
Pour lier cette chaine à un composant dans le fichier des layout:               <string name=“hug“>Hug</string>
android:text=“@string/like“                                                     <string name=“santaclaus“>Santa Claus</string>
                                                                              </resources>
Pour utiliser cette chaine dans le code Java:
String hello = getString(R.string.hello) ;                                                          values-frstring.xml
                                                                              <resources>
                                                                                <string name=“hello“>Bonjour, CheckBoxTuto!</string>
Mais surtout ces fichiers sont internationalisables de manière
                                                                                <string name=“app_name“>CheckBoxTuto</string>
transparente:                                                                   <string name=“like“>Aimez-vous:</string>
    • Le fichier valuesstring.xml contient les chaines de caractères à         <string name=“choice“>Votre choix est:</string>
    utiliser par défaut,                                                        <string name=“chocolate“>Chocolat</string>
                                                                                <string name=“television“>Télévision</string>
    • Le fichier values-frstring.xml contient les chaines de caractères        <string name=“internet“>Internet</string>
    à utiliser quand la locale de l’appareil est le français,                   <string name=“nicotine“>Nicotine</string>
    • Et ainsi de suite.                                                        <string name=“hug“>Câlins</string>
                                                                                <string name=“santaclaus“>Le père Noël</string>
                                                                              </resources>
Le code Java d’une activité ressemble à du code Java des plus naturels.   public class MainActivity extends Activity implements
Cela ressemble beaucoup à du Swing :                                      View.OnClickListener {
    • Les composants principaux sont naturels.                            /** * A button */
    • Ils possèdent les méthodes usuelles des composants (setText,        private Button btn;
    getText, setOnClickListener, hasFocus, isPressed, isSelected,         /** * A dummy counter */
    setBackground, setTextColor, ...)                                     private int count;
                                                                          /** Called when the activity is first created. */
Les différences notables sont:
                                                                          @Override
                                                                          public void onCreate(Bundle savedInstanceState) {
    • L’agencement des composants et leur définition se fait en XML.
                                                                            super.onCreate(savedInstanceState);
                                                                            //Récupère le fichier main.xml pour construire l’IHM
    • L’IHM de l’activité se construit par l’appel de la méthode
                                                                            setContentView(R.layout.main);
    setContentView(R.layout.main) où main est le nom de votre fichier
                                                                            //Instancie le bouton en récupérant son Id,
    reslayoutmain.xml.
                                                                            //on peut ensuite utiliser le bouton normalement.
    • Ils se récupèrent via la méthode findViewById en utilisant leur       btn=(Button)findViewById(R.id.button);
    identifiant.                                                            btn.setOnClickListener(this);
                                                                            btn.setText(“Hello“);
    • Votre activité étend la classe Activity.                            }
                                                                          public void onClick(View view) {
                                                                            count++; btn.setText(“Hello “+count);}
                                                                          }



                                                                                                                                   22
Le cycle de vie d’une activité est une notion fondamentale d’Android.
Le système, pour des raisons de priorisation d’activités (coup de
téléphone), peut tuer une activité quand il a besoin de ressources.




Une activité possède 4 états :

    • Active. L’activité est lancée par l’utilisateur, s’exécute au
    premier plan.

    • En Pause. L’activité est lancée par l’utilisateur, elle s’exécute
    et est visible mais elle n’est plus au premier plan. Une
    notification ou une autre activité lui a volé le focus et une partie
    du premier plan.

    • Stoppée. L’activité à été lancée par l’utilisateur mais n’est
    plus au premier plan et est invisible. L’activité ne peut interagir
    avec l’utilisateur qu’avec une notification.

    • Morte. L’activité n’est pas lancée.                                  http://developer.android.
                                                                           com/reference/android/
                                                                           app/Activity.html


                                                                                                       23
Et le projet se teste en utilisant l’émulateur fournit par Google qui s’intègre parfaitement avec l’IDE Eclipse:
Clic droit sur le projet->Run As-> Android Application




 Bien sûr, vous avez auparavant installé votre espace de travail et définit vos AVD (Android Virtual Device ).




                                                                                                                   24
25
•Les Intents

•Les traitements:
   •Handler versus AsyncTask
   •Handler
   •AsyncTask
   •Fuite mémoire

•Gestion des ressources:
   •Les chaines de caractères
   •Images, couleurs et thèmes

•L’arbre des caractéristiques possibles d’un appareil.

•La problématique du multi-screens et de la fragmentation.




                                                             26
Pour mettre en place cette communication entre activités, Android utilise le système des intentions. Une intention peut se traduire par
   “ je veux, toi système, que tu fasses … “. Et cela dépend de l’action demandée et du contexte. Celles-ci permettent d’envoyer des
   messages d’une activité vers une autre avec des données pour les activer.

Dans ce contexte, il faut se demander si l’activité mère quand elle lance une autre activité est dans une relation maître-esclave ou
   dans une relation de pair à pair. Dans le premier cas, l’activité mère attend que l’activité fille finisse et est informée de cette fin.
   Dans l’autre cas, l’activité fille est lancée, l’activité mère n’a plus de contact avec elle.

Une intention est ainsi une action associée à des données. Les actions sont des constantes : ACTION_VIEW, ACTION_EDIT,
  ACTION_PICK, les données sont des URI.

Les intentions peuvent se spécifier ; on peut leur rajouter des informations :
• Une catégorie : LAUNCHER (pour les activités présentes dans le lanceur Android), DEFAULT ou ALTERNATIVE.
• Un type MIME : indique le type de la ressource (comme pour les mails)
• Un composant : indique la classe d’activité censée recevoir l’intention. Cette méthode n’est pas la plus heureuse, car elle fige
    l’activité associée. Soit vous l’avez codée vous-même, dans ce cas, c’est naturel, sinon, l’utilisation des autres paramètres est
    préconisée.
• Des “ extras “ : un bundle d’informations permettant de transférer des données à l’activité cible.

Exemple de déclaration d’une écoute d’intention:         <intent-filter >
                                                              <action android:name="android.intent.action.MAIN" />
                                                              <category android:name="android.intent.category.LAUNCHER" />
                                                         </intent-filter>



                                                                                                                                              27
Pour utiliser les données renvoyées par l’activité appelée
Pour lancer une activité :                                                protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//To launch your own activity
                                                                          super.onActivityResult(requestCode, resultCode, data);
//First declare an intent
                                                                          if (requestCode == INTENT_CALL_ID) {
final Intent intent = new Intent().setClass(this, OtherActivity.class);
// Launch the activity                                                       if (resultCode == Activity.RESULT_OK) {
startActivity(intent);                                                                Uri contactData = data.getData();  …
 // Do the same for Geo*                                                   } else if (resultCode == Activity.RESULT_CANCELED) {…}
// Retrieve latitude and longitude                                        }}
String latitude = “43.565715431592736“;
String longitude = “1.398482322692871“;
// Format the associated uri                                              Pour renvoyer des informations à l’activité appelante, il faut utiliser
Uri uriGeo = Uri.parse(“geo:“ + latitude + “,“ + longitude);              la méthode setResult (n’importe où dans le code).
// Declare the associated Intent                                          JavaDoc:
final Intent intentGeo = new Intent(Intent.ACTION_VIEW, uriGeo);
// Launch the activity
                                                                          public final void setResult (int resultCode, Intent data)
startActivity(intent);
                                                                          Call this to set the result that your activity will return to its caller.
// Do the same for Contact waiting for result
                                                                          Parameters
// Format the associated uri
                                                                          resultCode The result code to propagate back to the originating activity, often
Uri uriContact = Uri.parse(“content://contacts/people“);
                                                                          RESULT_CANCELED or RESULT_OK
// Declare the intent:
                                                                          data The data to propagate back to the originating activity.
final Intent intentContactForResult = new Intent(Intent.ACTION_PICK,
                                                                          See Also:RESULT_CANCELED, RESULT_OK, RESULT_FIRST_USER,
uriContact);
                                                                          setResult(int).
// Launch the activity
startActivityForResult(intentContactForResult, INTENT_CALL_ID);

                                                                                                                                                            28
Si une activité ne réagit pas dans les 5 secondes, elle sera tuée par l’ActivityManager qui la considèrera comme morte.
Les IHMs de l’activité sont dans une Thread qui leur sont propres (comme en swing, l’EDT). Plusieurs façons d’interagir entre les
threads en arrière plan et la thread d’IHM sont possibles.



Pour résoudre ce problème il faut effectuer les traitements dans des threads indépendantes. Android met à votre disposition deux
    moyens pour parvenir à ce découpage:
•   Les Handlers
•   Les AsyncTask
Ces deux classes permettent de lancer un traitement à partir de la thread d’IHM qui puisse communiquer avec elle.

La question est de savoir laquelle choisir dans quelle circonstance:

    Si vous faites un traitement lourd, par lots, spécifique, qui n’a besoin que de donner son avancement et sa fin (typiquement
    charger des données), le mieux est l’utilisation de l’AsyncTask.

    Si vous avez besoin d’établir une communication avec l’IHM, asynchrone, il est plus pertinent d’utiliser un Handler (l’exemple de
    la communication Bluetooth entre deux appareils utilise ce pattern).

                                                Article DVP:
                                                Thread, Handler, AsyncTask et fuites mémoires



                                                                                                                                        29
Thread I.H.M                                             /** Called method when launching the activity */
                                                         Autre Thread     public void onStart() {
       Activity            Handler
                                                           Thread          super.onStart();
    sendMessage()      handleMessage()
                                                        sendMessage()      // initialize the progress bar
                                                                           bar.setProgress(0);
                     message
                                                                           // Thread definition, it could have been done in an external classes
                                                                           Thread background = new Thread(new Runnable() {
                                                                          /** The bundle exchanged within the message between the tread and the handler*/
Tout se passe dans la classe de votre activité:
                                                                          Bundle messageBundle=new Bundle();
   • Vous déclarez le Handler
   • Vous déclarez la thread                                              /*** The message exchanged between this thread and the handler*/
   • Vous communiquez par messages                                        Message myMessage;
                                                                          // Overriden Run method
                                                                          public void run() {
/*** The handler that manage the communication from external threads to
                                                                            try { // Sleep one second
Gui's thread */
Handler handler = new Handler() {                                            Thread.sleep(1000);
@Override                                                                    //create a message, the best way is to use that method:
public void handleMessage(Message msg) {                                      myMessage=handler.obtainMessage();
int progress=msg.getData().getInt(PROGRESS_BAR_INCREMENT);                     //then, if you want add data to your message (you could use arg0 and arg1 too)
// here, just increment the progress bar
                                                                             messageBundle.putInt(PROGRESS_BAR_INCREMENT, i);
bar.incrementProgressBy(progress);
// You can do quick stuff that update the Gui                                myMessage.setData(messageBundle);
}}; // Handler declaration end.                                               //then send the message
                                                                             handler.sendMessage(myMessage);}}
                                                                             catch (Throwable t) { // just end the background thread}}});
                                                                                                                                                                30
Pour mettre en place un AsynTask, il faut :
   Créer une sous-classe d’AsyncTask (elle peut être interne et privée à l’activité).
   Redéfinir une ou plusieurs de ces méthodes pour spécifier son travail.
   La lancer au moyen de sa méthode execute

La dérivation d’une classe AsyncTask n’est pas triviale, elle est générique et à paramètres variables:
public class MyAsyncTask extends AsyncTask<Params, Progress, Result>{
    protected Result doInBackground(Params... param) {}
    protected void onProgressUpdate(Progress... progress) {}
    protected void onPostExecute(Result result) {}}
Pour la généricité elle attend 3 paramètres :
    Params : Le type de l’information qui est nécessaire au traitement (dans l’exemple         )
    Progress : Le type de l’information qui est passé à sa tache pour indiquer sa progression (dans l’exemple   )
    Result: Le type de l’information qui est passé au code lorsque la tâche est finie (dans l’exemple    ).
                                               Thread I.H.M.                             Other Thread
                                                   Usual communication

                                  Activity     MyAsyncTask extends AsyncTask
                                                                                  doInBackground()
                                                       onProgressUpdate()          update
                                     update
                                                       OnPostExecute()




                                                                                                                     31
class MyAsyncTask extends AsyncTask<              , Integer, String> {                          public void onCreate(Bundle savedInstanceState) {
/** * A simple counter */                                                                       super.onCreate(savedInstanceState);
Integer count = 0;                                                                              setContentView(R.layout.main);
// override of the method doInBackground (the one which is running in a separate thread)        // Define the progress bar
@Override                                                                                       bar = (ProgressBar) findViewById(R.id.progress);
protected String doInBackground(           ... unused) {                                        bar.setMax(210);
try {                                                                                           // Launch the asynchTask
  while (count < 20) {                                                                          new MyAsyncTask().execute();
   count++;//increment the counter                                                              }
   Thread.sleep(1000);// Make a pause
   publishProgress(count);//talk to the onProgressUpdate method
}
} catch (InterruptedException t) {
   return (“The sleep operation failed“);// just end the background thread}
return (“return object when task is finished“);
}
// override of the onProgressUpdate method (runs in the GUI thread)
@Override
protected void onProgressUpdate(Integer... diff) {
  bar.incrementProgressBy(diff[0]);
}
// override of the onPostExecute method (runs in the GUI thread)
@Override
protected void onPostExecute(String message) {
  Toast.makeText(getApplicationContext(), message,Toast.LENGTH_SHORT).show();}}
}




                                                                                           32
Que se passe-t-il lorsque l’activité suit son cycle               Thread I.H.M                   Thread de traitement
de vie et est détruite puis recréée ?                  Activity              Handler
Typiquement une rotation de l’écran? Que                                                            sendMessage()
devient la Thread de traitement ?
                                                                            message
Dans la plupart des cas, le développeur ne fait
pas attention et l’ancienne Thread n’est pas
                                                                     OnDestroy()
détruite, une nouvelle Thread est mise en place.
                                                                     OnCreate()
Le traitement peut rester cohérent (ou pas).
                                                                                             Thread de traitement initiale
La même chose           se    produit   avec   les            Thread I.H.M                          sendMessage()
AsynchTask.

Alors quelle est la parade?                            Activity             Handler
                                                      fantôme               fantôme
    • Accorder le cycle de vie de la thread à
    celui de l’activité (la détruire dans                                                         Thread de traitement
    onDestroy).                                       Activity              Handler
                                                                                                     sendMessage()
    • Sauvegarder la Thread pour le prochain
    démarrage.
                                                                                   message
    • Associer la Thread à un service et non
    pas à une activité


                                                                                                                             33
protected void onCreate() {…
                   Thread I.H.M                                 Thread de traitement   backgroundThread = new Thread(new Runnable() {
          Activity             Handler                                                 /** * The message exchanged between this thread and the handler*/
                                                                   sendMessage()       Message myMessage;
                                                                                       public void run() {
                                                                                       while (isThreadRunnning.get()) {
                              message                                                          if (isThreadPausing.get()) {
                                                          OnDestroy()                                 // When pausing just sleep 2 seconds
                                                          OnCreate()                                    Thread.sleep(2000);
               Thread I.H.M                                                                    } else {// Do something
                                                                Thread de traitement
                                                                                                        Thread.sleep(100);
        Activity             Handler                                                                    myMessage = handler.obtainMessage();
                                                                  sendMessage()
                                                                                                        handler.sendMessage(myMessage);
                                                                                               }...
                                   message                                             // Initialize the thread Safe booleans
                                                                                           isThreadRunnning.set(true);
Avantages de la méthode:
                                                                                           //start the thread
•    Est la méthode la plus sécurisée contre les fuites mémoire.                           backgroundThread.start();}
Inconvénients de la méthode:
                                                                                       protected void onDestroy() {// kill the thread
•    Les données de la Thread doivent être sauvegardées puis restaurées.
                                                                                          isThreadRunnning.set(false);super.onDestroy();}
/**The atomic boolean to set the thread run*/                                          protected void onPause() {// stop the thread
private AtomicBoolean isThreadRunnning = new AtomicBoolean();                             isThreadPausing.set(true);super.onPause();}
/*** The atomic boolean to set the thread pause */                                     protected void onResume() {//relaunch the thread
private AtomicBoolean isThreadPausing = new AtomicBoolean();                            isThreadPausing.set(false);super.onResume();}

                                                                                                                                                           34
/** Called when the activity is first created. */    Avantages de la méthode:
@Override
                                                     •   Conserve la thread et son état
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);                  Inconvénients de la méthode:
…//Do something                                      •   Ne marche que pour lorsque l’activité va être recréée immédiatement
backgroundThread = (Thread)
                                                     •   Est deprecated depuis l’API level 11 (Fragment.setRetainInstance())
getLastNonConfigurationInstance();
…//Test if backgroundThread == null                               Thread I.H.M                                Thread de traitement
…//Do something again
                                                           Activity             Handler
}                                                                                                                   sendMessage()
@Override
public Object onRetainNonConfigurationInstance() {
//Save the thread                                                             message
return backgroundThread;
}                                                                                                   OnDestroy()
                                                                                                    OnCreate()
Lorsque votre activité est détruite pour être
immédiatement        recrée,     la     méthode                       Thread I.H.M
onRetainNonConfigurationInstance permet                                                                           Thread de traitement
                                                             Activity            Handler                            sendMessage()
d’envoyer un objet de l'instance de l’activité
mourante vers l'instance de la nouvelle activité.
                                                                                          message

 !!!Attention ne pas utiliser en l’état !!!
           !!! Fuite mémoire !!!
                                                                                                                                         35
La gestion des ressources vous permet de gérer les éléments suivants:
   • Les chaines de caractères et leur internationalisation,
   • Les images,
   • Les couleurs,
   • Les styles et thèmes.


La localisation des ressources et l’arbre des caractéristiques potentielles des appareils.


La problématique du multi-screens et de la fragmentation.




                                                                                             36
Les chaines de caractères de l’application doivent être Externalisées dans       L’utilisation de ces chaînes de caractères est la suivante.
un fichier xml et Internationalisées.                                            Remarquez que la chaîne renvoyée dépend de la locale de
Cela s’effectue en les plaçant au sein des dossiers resvalues-**:               l’utilisateur et des fichiers ressources définis.
resvalue-**string.xml correspond au fichier des chaines de caractères à        Dans le code Java:
utiliser quand l’appareil a pour locale ** (** peut-être fr, en, ru, es...).     //Retrieve String param_message with its parameters
resvaluesstring.xml stocke les chaines de caractères qui seront utilisées      Resources res = getResources();
par défaut (quand aucune locale de votre application ne correspond à la          String parameterString=
locale de l’utilisateur).                                                        String.format(res.getString(R.string.param_message),“peace“,“war“,2);
Ces fichiers stockent les chaines de caractères en xml. Vous pouvez              //Retrieve the array of strings
stocker une chaine simple, une chaine avec des paramètres, un tableau de         String[] iLikeItems = res.getStringArray(R.array.i_like_array);
chaines ou une chaine singulier ou pluriel.
                                                                                 //Retrieve a plural string
                             resvaluesstring.xml
                                                                                 int count = 2;
 <?xml version=“1.0“ encoding=“utf-8“?>
 <resources><!--String with parameters ($s for string, $d for decimal … )-->     String humans = res.getQuantityString(R.plurals.singleOrPlural, count);
 <string name=“param_message“>Hello, i love %1$s, i hate %2$s, i am %3$d years
 old</string>                                                                    Dans un fichier xml, seule la string simple est utilisable:
 <!--String array-->                                                             <TextView android:layout_width=“fill_parent“
 <string-array name=“i_like_array“>                                                 android:layout_height=“wrap_content“ android:text=“@string/hello“
  <item>chocolate</item> <item>television</item>                                 />
 </string-array>
 <!--Plurals String-->
 <plurals name=“singleOrPlural“>                                                 Dans un fichier xml, le tableau s’utilise avec les Spinners:
  <item quantity=“one“>I am alone on moon</item>                                 <Spinner      android:id=“@+id/spinner“
   <item quantity=“other“>I am 7 Billion on earth</item>                         android:layout_width=“fill_parent“ android:layout_height=“wrap_content“
 </plurals>                                                                       android:prompt=“@array/string_array“ />
 </resources>


                                                                                                                                                           37
Les images se placent dans resdrawable. Les formats acceptés sont PNG (best) et JPEG (ok). GIF n’est pas recommandé.

Il existe 9 types d’image qui s’adaptent à la situation (étirable Nine-patch, à état StateList, associé à un niveau...) et sont définis par
un fichier XML.

Exemple d’image dépendant de l’état du composant (StateListDrawable):
<?xml version=“1.0“ encoding=“UTF-8“?>
<selector xmlns:android=“http://schemas.android.com/apk/res/android“>
 <!-- when focused --> <item android:state_focused=“true“ android:drawable=“@drawable/sky“/>
 <!-- when pressed --> <item android:state_pressed=“true“ android:drawable=“@drawable/coffee“ />
   <!-- when normal --> <item android:drawable=“@drawable/icon“ />
</selector>


Certaines images permettent de définir une forme (fichier dans drawablecolor_border.xml) :
<shape xmlns:android=“http://schemas.android.com/apk/res/android“>
  <stroke android:width=“1dip“ android:color=“#FFFFFFFF“ /> <!-- Bordure-->
  <solid android:color=“#FF00FF00“ /> <!– Couleur du fond-->
  <corners android:radius=“20dp“ /> <!– angle des coins-->
</shape>

Utilisation pour obtenir un composant à bords arrondis:
// make a round button
shape = (GradientDrawable) getResources().getDrawable(R.drawable.color_border);
// set the shape to the component
onOff.setBackgroundDrawable(shape);
                                                                                                                                              38
Les couleurs se placent dans valuescolor.xml (par convention) qui associe un nom à une couleur. Le format est soit RVB en
hexadécimal (FFFFFF pour le blanc) soit ARVB où A n’est autre que le alpha (la transparence) ce qui donne FFFFFFFF (blanc
toujours)

<resources>                                                          <TextView
  <color name=“opaque_red“>#ff0000</color>                             android:layout_width=“fill_parent“
  <color name=“translucent_red“>#80ff0000</color>                      android:layout_height=“wrap_content“
</resources>                                                           android:textColor=“@color/translucent_red“
                                                                       android:text=“Hello“/>

Il est très important dans vos applications de déclarer les couleurs que vous utilisez au sein d’un seul fichier de manière à externaliser
      toute votre charte couleur et à pouvoir les réutiliser dans vos styles.

<resources>                                                          <TextView
  <color name=“backgound“>#f00f0000</color>                            android:layout_width=“fill_parent“
  <color name=“background_component“>#80ff0000</color>                 android:layout_height=“wrap_content“
  <color name=“backgound_component_second“>#f00f0900</color>           android:textColor=“@color/foreground_color“
  <color name=“background_component_third“>#80ff0740</color>           android:text=“Hello“/>
  <color name=“ foreground_color “>#f00f0008</color>
…
</resources>

Pourquoi? Maintenance, Evolution, Réutilisation de charte graphique entre application, Factorisation...


                                                                                                                                             39
Les thèmes se placent dans valuestheme.xml et définissent un ensemble de styles. Un style est associé à un nom et définit un
     ensemble de variables (couleur de fond, couleur, taille, font de police, marges ...).
       <?xml version=“1.0“ encoding=“utf-8“?>                          <TextView
       <resources>                                                       style=“@style/ ToDoTheme“
        <style name=“ToDoTheme“ parent=“@android:style/Theme.Black“>     android:text=“@string/hello“ />
         <item name=“android:textSize“>12sp</item>
        </style>
       </resources>

Un exemple concret avec dérivation:

        !--Style for TextView-->                                       <!--Style for EditText-->
        <!-- ************************-->                               <!-- ************************-->
        <style name=“mainTxv“>                                         <style name=“matchEDT“ parent=“mainTxv“>
        <item name=“android:textSize“>12sp</item>                      <item name=“android:background“> "@color/background_edt" </item>
        <item name=“android:textStyle“>bold</item>                     <item name=“android:minWidth“>14.5sp</item>
        <item name=“android:background“>"@color/background"</item>     <item name=“android:textColor“> "@color/foreground_edt" </item>
        <item name=“android:paddingLeft“>3dip</item>                   <item name=“android:textStyle“>normal</item>
        <item name=“android:paddingRight“>3dip</item>                  </style>
        <item name=“android:textColor“> "@color/foreground" </item>
        <item name=“android:layout_width“>wrap_content</item>
        <item name=“android:layout_height“>wrap_content</item>
        </style>



                                                                                                                                          40
Android fait bien les choses, voire trop bien.
Où comment Android décide quel est le fichier de ressources à utiliser (cela se comprend bien dans le cas de l’internationalisation mais ce
 concept est étendu à l’arbre des caractéristiques des devices Android). La liste des paramètres principaux pris en compte par Android
 est la suivante :
         Code réseau et code mobile du pays de la carte SIM dit code MCC (Mobile Country Code) et MNC (Mobile Network Code).
     http://en.wikipedia.org/wiki/Mobile_Network_Code
         Langue et région (internationalisation usuelle)
         Taille de l’écran (small, medium, large et xLarge)
         Rapport largeur/longueur (long ou not long) de l’écran
         Orientation de l’écran (port pour portrait, land pour landscape ou square pour carré)
         Densité de l’écran en pixel (ldpi pour low dpi, mdpi pour medium dpi, hdpi pour high dpi, xhdpi)
         Type d’écran tactile (notouch pour non sensitif, stylus pour le stylet et finger pour sensitif)
         Visibilité du clavier (keyexposed pour clavier physique apparent, keyshidden pour clavier physique caché ou keysoft pour un clavier logiciel)
         Type de clavier (nokeys, qwerty ou 12Key ???)
         Type de navigation (nonav pour pas de navigation, dpad pour le pad, trackball pour trackball et wheel pour la roue de la souris ???)
         Version du système (v1,…v15,…)

Ainsi pour définir la branche dans laquelle se trouve votre ressource, il faut spécifier son chemin :
         Il faut définir dans l’ordre des paramètres ci-dessus listés,
         On peut omettre des éléments,
                                                                                                                          http://developer.android.com/guide/topics
         Il faut un unique qualificateur par type de paramètre,                                                             /resources/providing-resources.html
         Il faut les séparer par un trait d’union.

Exemple : values-fr, drawable-hdpi, layout-large-port, values-v14,…



                                                                                                                                                                      41
MyLight et MyTorch
disponible sur GooglePlay
                            42
Merci pour votre attention.

                             Merci à DEVOXX France




                                     et Bravo !
                                                           Et rendez-vous à Brazzaville
                                                                  en septembre
                                 android2ee.com.
                                   #android2ee
   MyLight et MyTorch       mathias.seguy.it@gmail.com
disponible sur GooglePlay
                                                                                      43

Contenu connexe

En vedette

Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Mathias Seguy
 
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Mathias Seguy
 
Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Mathias Seguy
 
Android2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsAndroid2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsMathias Seguy
 
The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]Nilhcem
 
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015Mathias Seguy
 
Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)Mathias Seguy
 
Formation au Mobile Commerce (m-commerce)
Formation au Mobile Commerce (m-commerce)Formation au Mobile Commerce (m-commerce)
Formation au Mobile Commerce (m-commerce)SimaWay Simaway
 
Android Tutorials : Basic widgets
Android Tutorials : Basic widgetsAndroid Tutorials : Basic widgets
Android Tutorials : Basic widgetsPrajyot Mainkar
 
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
Présentation et bonnes pratiques du pattern MVVM - MIC BelgiquePrésentation et bonnes pratiques du pattern MVVM - MIC Belgique
Présentation et bonnes pratiques du pattern MVVM - MIC BelgiqueDenis Voituron
 
سيرتي الذاتية بالغة العربية
سيرتي الذاتية بالغة العربيةسيرتي الذاتية بالغة العربية
سيرتي الذاتية بالغة العربيةTaoufik Chaieb
 
Le Marketing Mobile face aux idées reçues
Le Marketing Mobile face aux idées reçuesLe Marketing Mobile face aux idées reçues
Le Marketing Mobile face aux idées reçuesLaFrenchMobile
 
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1Mathias Seguy
 
1er Baromètre du Marketing Mobile en France
1er Baromètre du Marketing Mobile en France1er Baromètre du Marketing Mobile en France
1er Baromètre du Marketing Mobile en Franceservicesmobiles.fr
 
Les 5 risques les plus critiques des applications Web selon l'OWASP
Les 5 risques les plus critiques des applications Web selon l'OWASPLes 5 risques les plus critiques des applications Web selon l'OWASP
Les 5 risques les plus critiques des applications Web selon l'OWASPyaboukir
 
In01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationIn01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationYann Caron
 

En vedette (19)

Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
 
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
 
Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.
 
Android2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsAndroid2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projects
 
Programmation sous Android
Programmation sous AndroidProgrammation sous Android
Programmation sous Android
 
Business Plan d’une application mobile
Business Plan d’une application mobileBusiness Plan d’une application mobile
Business Plan d’une application mobile
 
Java pour android
Java pour androidJava pour android
Java pour android
 
The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]
 
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015
Animate Me! if you don't do it for me, do it for Chet - DroidconLondon2015
 
Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)
 
Formation au Mobile Commerce (m-commerce)
Formation au Mobile Commerce (m-commerce)Formation au Mobile Commerce (m-commerce)
Formation au Mobile Commerce (m-commerce)
 
Android Tutorials : Basic widgets
Android Tutorials : Basic widgetsAndroid Tutorials : Basic widgets
Android Tutorials : Basic widgets
 
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
Présentation et bonnes pratiques du pattern MVVM - MIC BelgiquePrésentation et bonnes pratiques du pattern MVVM - MIC Belgique
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
 
سيرتي الذاتية بالغة العربية
سيرتي الذاتية بالغة العربيةسيرتي الذاتية بالغة العربية
سيرتي الذاتية بالغة العربية
 
Le Marketing Mobile face aux idées reçues
Le Marketing Mobile face aux idées reçuesLe Marketing Mobile face aux idées reçues
Le Marketing Mobile face aux idées reçues
 
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part1
 
1er Baromètre du Marketing Mobile en France
1er Baromètre du Marketing Mobile en France1er Baromètre du Marketing Mobile en France
1er Baromètre du Marketing Mobile en France
 
Les 5 risques les plus critiques des applications Web selon l'OWASP
Les 5 risques les plus critiques des applications Web selon l'OWASPLes 5 risques les plus critiques des applications Web selon l'OWASP
Les 5 risques les plus critiques des applications Web selon l'OWASP
 
In01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationIn01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publication
 

"Android A Quick Course (Fr) Part I" by Android2EE (Mathias Seguy) à la Devoxx France 2012

  • 1. vous présente : Spécialiste Android Java J2EE Auteur du livre disponible sur
  • 2. •Android et le monde de l’IT Android et le monde de l’IT 2
  • 3. •Android et le monde de l’IT •Mettre en place une activité oLes acteurs du système : Activity – ContentProvider – Service oLa structure d’un projet Android oLes IHM Mettre en place une Activité 3
  • 4. •Android et le monde de l’IT •Mettre en place une activité •Autour de l’activité : oLes Intents oLes traitements : Thread et AsyncTask oLa gestion des ressources Autour de l’activité Mettre en place une Activité 4
  • 5. •Android et le monde de l’IT •Mettre en place une activité •Autour de l’activité •Autres éléments d’une application: oApplication Autres éléments de l’application oPermissions oPersistance des données Autour de l’activité oService Mettre en place une Activité 5
  • 6. •Android et le monde de l’IT •Mettre en place une activité Communiquer avec le •Autour de l’activité système •Autres éléments d’une application •Communiquer avec le système: Autres éléments de l’application oInternet oCapteur Autour de l’activité Mettre en place une Activité 6
  • 7. •Android et le monde de l’IT Autour du projet •Mettre en place une activité Communiquer avec le •Autour de l’activité système •Autres éléments d’une application •Communiquer avec le système Android et le monde Autres éléments de •Autour du projet de l’IT l’application oSigner et Déployer Autour de l’activité oStratégies de tests Mettre en place une Activité 7
  • 8. Formateur Consultant Expert Android mathias.seguy.it@gmail.com (mail) @android2ee (twitter) Auteur d’EBooks sur la programmation Android (Android2ee.com) Conférencier et Enseignant Android Docteur en Mathématiques Fondamentales Expert Technique de l'Agence Nationale de la Recherche Rédacteur sur Developpez.com Blogs Android : Android2EE sur DVP et Android2ee sur BlogSpot Doctorat Mathématiques Fondamentales Via CapGemini Via Sopra Naissance Android2EE Siemens Magnus DGA CNES Airbus Airbus Airbus STI Android2EE VDO 03 04 05 06 07 08 09 10 11 12 Java J2EE Android Manager Manager Leader Leader Leader Leader Directeur Fondateur Développeur Développeur IHM Technique Technique Manager Technique Technique Android2EE Master Informatique de Chez STI l’ENSEEIHT 8
  • 9. 9
  • 10. Invasion de la mobilité via les smartphones: Le taux de pénétration des smartphones est exceptionnel, tant part sa valeur actuelle que par la rapidité de sa progression. •486M de smartphones vendus en 2011. •27% du parc mondial. Android, l’OS Winner ! En quatre ans, Android est devenu leader mondial du système d’exploitation des smartphones, en terme de stock et en terme de vente. 10
  • 11. GooglePlay (AndroidMarket) versus AppleStore, la guerre du Market. Le nombre d’applications sur GooglePlay est en hausse permanente. • + 17 391 % en 3 ans • + 320 % en 1 an Le nombre d’applications téléchargées a pour unité le milliard. •+500% sur 1 an •10 000 000 000 de downloads ! Cette dynamique est la clef de réussite de la plateforme, le facteur d’adoption. 11
  • 12. La guerre des brevets fait rage dans les grands comptes de l’IT. Depuis l’été 2011, cette guerre fait des ravages dans le monde entier. Le système Android est attaqué par le trio Microsoft-Apple-Oracle et se défend: Apple versus Android : La guerre froide Ces deux-là se mènent une guerre non frontale: Apple attaque les constructeurs et Google rachète Motorola pour 8.6B$. Apple versus HTC et Samsung: La guerre des tribunaux. Interdiction du GalaxyTab en Australie, plainte en Europe et aux Etats Unis… (Depuis peu demande un accord « amiable » entre 5 et 15$ par unité). Microsoft versus Android: La guerre des gangs. Microsoft a su imposer une redevance (5$) à Samsung et à HTC pour chaque unité Android vendue. Oracle Versus Android : l’open-guerre Quand l’open source fait la guerre à l’open source… Plainte déposée par Oracle en 2010 (le procès s’ouvre cette semaine… à suivre). Vidyanand Kamat/Forbes India 12
  • 13. Aujourd’hui Android envahit la téléphonie mobile. Demain, Android sera partout: téléphone, tablette, télévision, montres, chaine Hifi, voiture, électroménager, domotique …. Partout, vous dis-je. 13
  • 14. 14
  • 15. •Les règles •Les acteurs du système : Activity, Service, ContentProvider et Intent •La structure d’un projet : •Vision globale •Le fichier AndroidManifest.xml qui décrit votre application •Le fichier layoutmain.xml qui décrit l’IHM de votre activité •Le fichier resvaluesstring.xml qui décrit les chaines de caractère de votre application •L’activité •Le test avec l’émulateur 15
  • 16. Respecter ses données, Respecter sa confidentialité. Respecter le CPU, Respecter la batterie, Respecter la mémoire. Respecter la charte graphique Android, Respecter les bonnes pratiques du système. … 16
  • 17. : Ce sont les programmes vu par l’utilisateur. Ils : Les services ont une durée de vie potentiellement infinie possèdent une I.H.M. (contrairement aux activités et aux fournisseurs de données). Ce sont des processus qui tournent dans la même Thread que : Ils offrent un niveau d’abstraction pour l’application sans IHM. l’accès à toutes les données stockées sur le terminal. Les : Ce sont des messages systèmes qui servent de support données sont identifiées au moyen d’URI (Unified Ressources événementiel pour permettre le dialogue entre applications. On Identifier). répond et on envoie des intentions qui lancent ou communiquent avec les activités. Listen Service Listen BroadCastReceiver Bind Activity StartActivity ContentResolver.action(URI,…) CRUD operation return URI ContentProvider Send Intent Find ContentProvider 17
  • 18. Un projet Android simple contient les dossiers: pour les sources Java pour les sources générées à partir du dossier res pour les dossiers de ressources: pour les images pour la définition des composants graphiques pour les chaînes de caractères ainsi que le fichier qui est le centre névralgique de votre application. Il décrit les besoins de votre application, en termes de SDK, de compatibilité matérielle, d’API utilisées et d’utilisation de services du système. Il décrit ce qu’offre votre application au système (Activity, ContentProvider, Service…), et les éléments auxquels votre application réagit au moyen des IntentFilters et d’URI ainsi que les permissions nécessaire pour les utiliser. 18
  • 19. Le fichier AndroidManifest.xml décrit votre application: <?xml version=“1.0“ encoding=“utf-8“?> • son package, <manifest xmlns:android=http://schemas.android.com/apk/res/android • son nom, package= “ com.android2ee.android.tuto.gui“ • sa version, android:versionCode=“1“ • son icône, android:versionName=“1.0“> • son label, <application android:icon=“@drawable/icon“ • la liste des activités qu’elle possède et les intentions android:label=“@string/app_name“> auxquelles chacune répond (ici l’Intent démarrage), <activity android:name=“.RadioButtonTuto“ • ainsi que la version minimale du système nécessaire à android:label=“@string/app_name“> la faire fonctionner. <intent-filter> <action android:name=“android.intent.action.MAIN“ /> Il peut aussi déclarer: • les services et les content provider qu’elle contient, <category android:name=“android.intent.category.LAUNCHER“ /> • les permissions dont elle a besoin et celles qu’elle </intent-filter> procure. </activity> </application> Enfin, il peut déclarer les éléments matériels dont elle a <uses-sdk android:minSdkVersion=“8“ /> besoin. </manifest> 19
  • 20. Le fichier des Layouts : layoutmain.xml Ce fichier décrit les composants graphiques de votre activité. <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android Ils se placent dans un layout et définissent les propriétés android:orientation=“vertical“ suivantes (en fonction du besoin): android:layout_width=“fill_parent“ android:layout_height=“fill_parent“ > • La manière dont ils remplissent l’espace <TextView android:layout_width=“fill_parent“ (android:layout_width, android:layout_height) android:layout_height=“wrap_content“ • Un identifiant pour pouvoir être récupéré dans le code android:text=“@string/like“/> java (android:id) <CheckBox android:id=“@+id/checkchocolate“ • Le texte affiché (android:text) android:layout_width=“wrap_content“ • Le poids du composant (android:layout_weight) android:layout_height=“wrap_content“ android:text=“@string/chocolate“ /> Ce fichier est interprété par l’activité pour construire son écran <Button android:id=“@+id/btnShow“ via la méthode : android:layout_width=“fill_parent“ setContentView(R.layout.main); android:layout_height=“wrap_content“ android:text=“@string/show“/> Un composant se récupère dans le code par la méthode: </LinearLayout> btn=(Button)findViewById(R.id.btnShow); 20
  • 21. Le fichier des chaines de caractères: resvaluesstring.xml valuesstring.xml <resources> <string name=“hello“>Hello World, CheckBoxTuto!</string> Ce fichier décrit les chaines de caractères utilisables par votre activité. <string name=“app_name“>CheckBoxTuto</string> <string name=“like“>Do you like :</string> Chaque chaine est identifiable par un nom et possède une valeur. <string name=“choice“>Your choice is :</string> <string name=“chocolate“>Chocolate</string> <string name=“nicotine“>Nicotine</string> Pour lier cette chaine à un composant dans le fichier des layout: <string name=“hug“>Hug</string> android:text=“@string/like“ <string name=“santaclaus“>Santa Claus</string> </resources> Pour utiliser cette chaine dans le code Java: String hello = getString(R.string.hello) ; values-frstring.xml <resources> <string name=“hello“>Bonjour, CheckBoxTuto!</string> Mais surtout ces fichiers sont internationalisables de manière <string name=“app_name“>CheckBoxTuto</string> transparente: <string name=“like“>Aimez-vous:</string> • Le fichier valuesstring.xml contient les chaines de caractères à <string name=“choice“>Votre choix est:</string> utiliser par défaut, <string name=“chocolate“>Chocolat</string> <string name=“television“>Télévision</string> • Le fichier values-frstring.xml contient les chaines de caractères <string name=“internet“>Internet</string> à utiliser quand la locale de l’appareil est le français, <string name=“nicotine“>Nicotine</string> • Et ainsi de suite. <string name=“hug“>Câlins</string> <string name=“santaclaus“>Le père Noël</string> </resources>
  • 22. Le code Java d’une activité ressemble à du code Java des plus naturels. public class MainActivity extends Activity implements Cela ressemble beaucoup à du Swing : View.OnClickListener { • Les composants principaux sont naturels. /** * A button */ • Ils possèdent les méthodes usuelles des composants (setText, private Button btn; getText, setOnClickListener, hasFocus, isPressed, isSelected, /** * A dummy counter */ setBackground, setTextColor, ...) private int count; /** Called when the activity is first created. */ Les différences notables sont: @Override public void onCreate(Bundle savedInstanceState) { • L’agencement des composants et leur définition se fait en XML. super.onCreate(savedInstanceState); //Récupère le fichier main.xml pour construire l’IHM • L’IHM de l’activité se construit par l’appel de la méthode setContentView(R.layout.main); setContentView(R.layout.main) où main est le nom de votre fichier //Instancie le bouton en récupérant son Id, reslayoutmain.xml. //on peut ensuite utiliser le bouton normalement. • Ils se récupèrent via la méthode findViewById en utilisant leur btn=(Button)findViewById(R.id.button); identifiant. btn.setOnClickListener(this); btn.setText(“Hello“); • Votre activité étend la classe Activity. } public void onClick(View view) { count++; btn.setText(“Hello “+count);} } 22
  • 23. Le cycle de vie d’une activité est une notion fondamentale d’Android. Le système, pour des raisons de priorisation d’activités (coup de téléphone), peut tuer une activité quand il a besoin de ressources. Une activité possède 4 états : • Active. L’activité est lancée par l’utilisateur, s’exécute au premier plan. • En Pause. L’activité est lancée par l’utilisateur, elle s’exécute et est visible mais elle n’est plus au premier plan. Une notification ou une autre activité lui a volé le focus et une partie du premier plan. • Stoppée. L’activité à été lancée par l’utilisateur mais n’est plus au premier plan et est invisible. L’activité ne peut interagir avec l’utilisateur qu’avec une notification. • Morte. L’activité n’est pas lancée. http://developer.android. com/reference/android/ app/Activity.html 23
  • 24. Et le projet se teste en utilisant l’émulateur fournit par Google qui s’intègre parfaitement avec l’IDE Eclipse: Clic droit sur le projet->Run As-> Android Application Bien sûr, vous avez auparavant installé votre espace de travail et définit vos AVD (Android Virtual Device ). 24
  • 25. 25
  • 26. •Les Intents •Les traitements: •Handler versus AsyncTask •Handler •AsyncTask •Fuite mémoire •Gestion des ressources: •Les chaines de caractères •Images, couleurs et thèmes •L’arbre des caractéristiques possibles d’un appareil. •La problématique du multi-screens et de la fragmentation. 26
  • 27. Pour mettre en place cette communication entre activités, Android utilise le système des intentions. Une intention peut se traduire par “ je veux, toi système, que tu fasses … “. Et cela dépend de l’action demandée et du contexte. Celles-ci permettent d’envoyer des messages d’une activité vers une autre avec des données pour les activer. Dans ce contexte, il faut se demander si l’activité mère quand elle lance une autre activité est dans une relation maître-esclave ou dans une relation de pair à pair. Dans le premier cas, l’activité mère attend que l’activité fille finisse et est informée de cette fin. Dans l’autre cas, l’activité fille est lancée, l’activité mère n’a plus de contact avec elle. Une intention est ainsi une action associée à des données. Les actions sont des constantes : ACTION_VIEW, ACTION_EDIT, ACTION_PICK, les données sont des URI. Les intentions peuvent se spécifier ; on peut leur rajouter des informations : • Une catégorie : LAUNCHER (pour les activités présentes dans le lanceur Android), DEFAULT ou ALTERNATIVE. • Un type MIME : indique le type de la ressource (comme pour les mails) • Un composant : indique la classe d’activité censée recevoir l’intention. Cette méthode n’est pas la plus heureuse, car elle fige l’activité associée. Soit vous l’avez codée vous-même, dans ce cas, c’est naturel, sinon, l’utilisation des autres paramètres est préconisée. • Des “ extras “ : un bundle d’informations permettant de transférer des données à l’activité cible. Exemple de déclaration d’une écoute d’intention: <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> 27
  • 28. Pour utiliser les données renvoyées par l’activité appelée Pour lancer une activité : protected void onActivityResult(int requestCode, int resultCode, Intent data) { //To launch your own activity super.onActivityResult(requestCode, resultCode, data); //First declare an intent if (requestCode == INTENT_CALL_ID) { final Intent intent = new Intent().setClass(this, OtherActivity.class); // Launch the activity if (resultCode == Activity.RESULT_OK) { startActivity(intent); Uri contactData = data.getData(); … // Do the same for Geo* } else if (resultCode == Activity.RESULT_CANCELED) {…} // Retrieve latitude and longitude }} String latitude = “43.565715431592736“; String longitude = “1.398482322692871“; // Format the associated uri Pour renvoyer des informations à l’activité appelante, il faut utiliser Uri uriGeo = Uri.parse(“geo:“ + latitude + “,“ + longitude); la méthode setResult (n’importe où dans le code). // Declare the associated Intent JavaDoc: final Intent intentGeo = new Intent(Intent.ACTION_VIEW, uriGeo); // Launch the activity public final void setResult (int resultCode, Intent data) startActivity(intent); Call this to set the result that your activity will return to its caller. // Do the same for Contact waiting for result Parameters // Format the associated uri resultCode The result code to propagate back to the originating activity, often Uri uriContact = Uri.parse(“content://contacts/people“); RESULT_CANCELED or RESULT_OK // Declare the intent: data The data to propagate back to the originating activity. final Intent intentContactForResult = new Intent(Intent.ACTION_PICK, See Also:RESULT_CANCELED, RESULT_OK, RESULT_FIRST_USER, uriContact); setResult(int). // Launch the activity startActivityForResult(intentContactForResult, INTENT_CALL_ID); 28
  • 29. Si une activité ne réagit pas dans les 5 secondes, elle sera tuée par l’ActivityManager qui la considèrera comme morte. Les IHMs de l’activité sont dans une Thread qui leur sont propres (comme en swing, l’EDT). Plusieurs façons d’interagir entre les threads en arrière plan et la thread d’IHM sont possibles. Pour résoudre ce problème il faut effectuer les traitements dans des threads indépendantes. Android met à votre disposition deux moyens pour parvenir à ce découpage: • Les Handlers • Les AsyncTask Ces deux classes permettent de lancer un traitement à partir de la thread d’IHM qui puisse communiquer avec elle. La question est de savoir laquelle choisir dans quelle circonstance: Si vous faites un traitement lourd, par lots, spécifique, qui n’a besoin que de donner son avancement et sa fin (typiquement charger des données), le mieux est l’utilisation de l’AsyncTask. Si vous avez besoin d’établir une communication avec l’IHM, asynchrone, il est plus pertinent d’utiliser un Handler (l’exemple de la communication Bluetooth entre deux appareils utilise ce pattern). Article DVP: Thread, Handler, AsyncTask et fuites mémoires 29
  • 30. Thread I.H.M /** Called method when launching the activity */ Autre Thread public void onStart() { Activity Handler Thread super.onStart(); sendMessage() handleMessage() sendMessage() // initialize the progress bar bar.setProgress(0); message // Thread definition, it could have been done in an external classes Thread background = new Thread(new Runnable() { /** The bundle exchanged within the message between the tread and the handler*/ Tout se passe dans la classe de votre activité: Bundle messageBundle=new Bundle(); • Vous déclarez le Handler • Vous déclarez la thread /*** The message exchanged between this thread and the handler*/ • Vous communiquez par messages Message myMessage; // Overriden Run method public void run() { /*** The handler that manage the communication from external threads to try { // Sleep one second Gui's thread */ Handler handler = new Handler() { Thread.sleep(1000); @Override //create a message, the best way is to use that method: public void handleMessage(Message msg) { myMessage=handler.obtainMessage(); int progress=msg.getData().getInt(PROGRESS_BAR_INCREMENT); //then, if you want add data to your message (you could use arg0 and arg1 too) // here, just increment the progress bar messageBundle.putInt(PROGRESS_BAR_INCREMENT, i); bar.incrementProgressBy(progress); // You can do quick stuff that update the Gui myMessage.setData(messageBundle); }}; // Handler declaration end. //then send the message handler.sendMessage(myMessage);}} catch (Throwable t) { // just end the background thread}}}); 30
  • 31. Pour mettre en place un AsynTask, il faut : Créer une sous-classe d’AsyncTask (elle peut être interne et privée à l’activité). Redéfinir une ou plusieurs de ces méthodes pour spécifier son travail. La lancer au moyen de sa méthode execute La dérivation d’une classe AsyncTask n’est pas triviale, elle est générique et à paramètres variables: public class MyAsyncTask extends AsyncTask<Params, Progress, Result>{ protected Result doInBackground(Params... param) {} protected void onProgressUpdate(Progress... progress) {} protected void onPostExecute(Result result) {}} Pour la généricité elle attend 3 paramètres : Params : Le type de l’information qui est nécessaire au traitement (dans l’exemple ) Progress : Le type de l’information qui est passé à sa tache pour indiquer sa progression (dans l’exemple ) Result: Le type de l’information qui est passé au code lorsque la tâche est finie (dans l’exemple ). Thread I.H.M. Other Thread Usual communication Activity MyAsyncTask extends AsyncTask doInBackground() onProgressUpdate() update update OnPostExecute() 31
  • 32. class MyAsyncTask extends AsyncTask< , Integer, String> { public void onCreate(Bundle savedInstanceState) { /** * A simple counter */ super.onCreate(savedInstanceState); Integer count = 0; setContentView(R.layout.main); // override of the method doInBackground (the one which is running in a separate thread) // Define the progress bar @Override bar = (ProgressBar) findViewById(R.id.progress); protected String doInBackground( ... unused) { bar.setMax(210); try { // Launch the asynchTask while (count < 20) { new MyAsyncTask().execute(); count++;//increment the counter } Thread.sleep(1000);// Make a pause publishProgress(count);//talk to the onProgressUpdate method } } catch (InterruptedException t) { return (“The sleep operation failed“);// just end the background thread} return (“return object when task is finished“); } // override of the onProgressUpdate method (runs in the GUI thread) @Override protected void onProgressUpdate(Integer... diff) { bar.incrementProgressBy(diff[0]); } // override of the onPostExecute method (runs in the GUI thread) @Override protected void onPostExecute(String message) { Toast.makeText(getApplicationContext(), message,Toast.LENGTH_SHORT).show();}} } 32
  • 33. Que se passe-t-il lorsque l’activité suit son cycle Thread I.H.M Thread de traitement de vie et est détruite puis recréée ? Activity Handler Typiquement une rotation de l’écran? Que sendMessage() devient la Thread de traitement ? message Dans la plupart des cas, le développeur ne fait pas attention et l’ancienne Thread n’est pas OnDestroy() détruite, une nouvelle Thread est mise en place. OnCreate() Le traitement peut rester cohérent (ou pas). Thread de traitement initiale La même chose se produit avec les Thread I.H.M sendMessage() AsynchTask. Alors quelle est la parade? Activity Handler fantôme fantôme • Accorder le cycle de vie de la thread à celui de l’activité (la détruire dans Thread de traitement onDestroy). Activity Handler sendMessage() • Sauvegarder la Thread pour le prochain démarrage. message • Associer la Thread à un service et non pas à une activité 33
  • 34. protected void onCreate() {… Thread I.H.M Thread de traitement backgroundThread = new Thread(new Runnable() { Activity Handler /** * The message exchanged between this thread and the handler*/ sendMessage() Message myMessage; public void run() { while (isThreadRunnning.get()) { message if (isThreadPausing.get()) { OnDestroy() // When pausing just sleep 2 seconds OnCreate() Thread.sleep(2000); Thread I.H.M } else {// Do something Thread de traitement Thread.sleep(100); Activity Handler myMessage = handler.obtainMessage(); sendMessage() handler.sendMessage(myMessage); }... message // Initialize the thread Safe booleans isThreadRunnning.set(true); Avantages de la méthode: //start the thread • Est la méthode la plus sécurisée contre les fuites mémoire. backgroundThread.start();} Inconvénients de la méthode: protected void onDestroy() {// kill the thread • Les données de la Thread doivent être sauvegardées puis restaurées. isThreadRunnning.set(false);super.onDestroy();} /**The atomic boolean to set the thread run*/ protected void onPause() {// stop the thread private AtomicBoolean isThreadRunnning = new AtomicBoolean(); isThreadPausing.set(true);super.onPause();} /*** The atomic boolean to set the thread pause */ protected void onResume() {//relaunch the thread private AtomicBoolean isThreadPausing = new AtomicBoolean(); isThreadPausing.set(false);super.onResume();} 34
  • 35. /** Called when the activity is first created. */ Avantages de la méthode: @Override • Conserve la thread et son état public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Inconvénients de la méthode: …//Do something • Ne marche que pour lorsque l’activité va être recréée immédiatement backgroundThread = (Thread) • Est deprecated depuis l’API level 11 (Fragment.setRetainInstance()) getLastNonConfigurationInstance(); …//Test if backgroundThread == null Thread I.H.M Thread de traitement …//Do something again Activity Handler } sendMessage() @Override public Object onRetainNonConfigurationInstance() { //Save the thread message return backgroundThread; } OnDestroy() OnCreate() Lorsque votre activité est détruite pour être immédiatement recrée, la méthode Thread I.H.M onRetainNonConfigurationInstance permet Thread de traitement Activity Handler sendMessage() d’envoyer un objet de l'instance de l’activité mourante vers l'instance de la nouvelle activité. message !!!Attention ne pas utiliser en l’état !!! !!! Fuite mémoire !!! 35
  • 36. La gestion des ressources vous permet de gérer les éléments suivants: • Les chaines de caractères et leur internationalisation, • Les images, • Les couleurs, • Les styles et thèmes. La localisation des ressources et l’arbre des caractéristiques potentielles des appareils. La problématique du multi-screens et de la fragmentation. 36
  • 37. Les chaines de caractères de l’application doivent être Externalisées dans L’utilisation de ces chaînes de caractères est la suivante. un fichier xml et Internationalisées. Remarquez que la chaîne renvoyée dépend de la locale de Cela s’effectue en les plaçant au sein des dossiers resvalues-**: l’utilisateur et des fichiers ressources définis. resvalue-**string.xml correspond au fichier des chaines de caractères à Dans le code Java: utiliser quand l’appareil a pour locale ** (** peut-être fr, en, ru, es...). //Retrieve String param_message with its parameters resvaluesstring.xml stocke les chaines de caractères qui seront utilisées Resources res = getResources(); par défaut (quand aucune locale de votre application ne correspond à la String parameterString= locale de l’utilisateur). String.format(res.getString(R.string.param_message),“peace“,“war“,2); Ces fichiers stockent les chaines de caractères en xml. Vous pouvez //Retrieve the array of strings stocker une chaine simple, une chaine avec des paramètres, un tableau de String[] iLikeItems = res.getStringArray(R.array.i_like_array); chaines ou une chaine singulier ou pluriel. //Retrieve a plural string resvaluesstring.xml int count = 2; <?xml version=“1.0“ encoding=“utf-8“?> <resources><!--String with parameters ($s for string, $d for decimal … )--> String humans = res.getQuantityString(R.plurals.singleOrPlural, count); <string name=“param_message“>Hello, i love %1$s, i hate %2$s, i am %3$d years old</string> Dans un fichier xml, seule la string simple est utilisable: <!--String array--> <TextView android:layout_width=“fill_parent“ <string-array name=“i_like_array“> android:layout_height=“wrap_content“ android:text=“@string/hello“ <item>chocolate</item> <item>television</item> /> </string-array> <!--Plurals String--> <plurals name=“singleOrPlural“> Dans un fichier xml, le tableau s’utilise avec les Spinners: <item quantity=“one“>I am alone on moon</item> <Spinner android:id=“@+id/spinner“ <item quantity=“other“>I am 7 Billion on earth</item> android:layout_width=“fill_parent“ android:layout_height=“wrap_content“ </plurals> android:prompt=“@array/string_array“ /> </resources> 37
  • 38. Les images se placent dans resdrawable. Les formats acceptés sont PNG (best) et JPEG (ok). GIF n’est pas recommandé. Il existe 9 types d’image qui s’adaptent à la situation (étirable Nine-patch, à état StateList, associé à un niveau...) et sont définis par un fichier XML. Exemple d’image dépendant de l’état du composant (StateListDrawable): <?xml version=“1.0“ encoding=“UTF-8“?> <selector xmlns:android=“http://schemas.android.com/apk/res/android“> <!-- when focused --> <item android:state_focused=“true“ android:drawable=“@drawable/sky“/> <!-- when pressed --> <item android:state_pressed=“true“ android:drawable=“@drawable/coffee“ /> <!-- when normal --> <item android:drawable=“@drawable/icon“ /> </selector> Certaines images permettent de définir une forme (fichier dans drawablecolor_border.xml) : <shape xmlns:android=“http://schemas.android.com/apk/res/android“> <stroke android:width=“1dip“ android:color=“#FFFFFFFF“ /> <!-- Bordure--> <solid android:color=“#FF00FF00“ /> <!– Couleur du fond--> <corners android:radius=“20dp“ /> <!– angle des coins--> </shape> Utilisation pour obtenir un composant à bords arrondis: // make a round button shape = (GradientDrawable) getResources().getDrawable(R.drawable.color_border); // set the shape to the component onOff.setBackgroundDrawable(shape); 38
  • 39. Les couleurs se placent dans valuescolor.xml (par convention) qui associe un nom à une couleur. Le format est soit RVB en hexadécimal (FFFFFF pour le blanc) soit ARVB où A n’est autre que le alpha (la transparence) ce qui donne FFFFFFFF (blanc toujours) <resources> <TextView <color name=“opaque_red“>#ff0000</color> android:layout_width=“fill_parent“ <color name=“translucent_red“>#80ff0000</color> android:layout_height=“wrap_content“ </resources> android:textColor=“@color/translucent_red“ android:text=“Hello“/> Il est très important dans vos applications de déclarer les couleurs que vous utilisez au sein d’un seul fichier de manière à externaliser toute votre charte couleur et à pouvoir les réutiliser dans vos styles. <resources> <TextView <color name=“backgound“>#f00f0000</color> android:layout_width=“fill_parent“ <color name=“background_component“>#80ff0000</color> android:layout_height=“wrap_content“ <color name=“backgound_component_second“>#f00f0900</color> android:textColor=“@color/foreground_color“ <color name=“background_component_third“>#80ff0740</color> android:text=“Hello“/> <color name=“ foreground_color “>#f00f0008</color> … </resources> Pourquoi? Maintenance, Evolution, Réutilisation de charte graphique entre application, Factorisation... 39
  • 40. Les thèmes se placent dans valuestheme.xml et définissent un ensemble de styles. Un style est associé à un nom et définit un ensemble de variables (couleur de fond, couleur, taille, font de police, marges ...). <?xml version=“1.0“ encoding=“utf-8“?> <TextView <resources> style=“@style/ ToDoTheme“ <style name=“ToDoTheme“ parent=“@android:style/Theme.Black“> android:text=“@string/hello“ /> <item name=“android:textSize“>12sp</item> </style> </resources> Un exemple concret avec dérivation: !--Style for TextView--> <!--Style for EditText--> <!-- ************************--> <!-- ************************--> <style name=“mainTxv“> <style name=“matchEDT“ parent=“mainTxv“> <item name=“android:textSize“>12sp</item> <item name=“android:background“> "@color/background_edt" </item> <item name=“android:textStyle“>bold</item> <item name=“android:minWidth“>14.5sp</item> <item name=“android:background“>"@color/background"</item> <item name=“android:textColor“> "@color/foreground_edt" </item> <item name=“android:paddingLeft“>3dip</item> <item name=“android:textStyle“>normal</item> <item name=“android:paddingRight“>3dip</item> </style> <item name=“android:textColor“> "@color/foreground" </item> <item name=“android:layout_width“>wrap_content</item> <item name=“android:layout_height“>wrap_content</item> </style> 40
  • 41. Android fait bien les choses, voire trop bien. Où comment Android décide quel est le fichier de ressources à utiliser (cela se comprend bien dans le cas de l’internationalisation mais ce concept est étendu à l’arbre des caractéristiques des devices Android). La liste des paramètres principaux pris en compte par Android est la suivante :  Code réseau et code mobile du pays de la carte SIM dit code MCC (Mobile Country Code) et MNC (Mobile Network Code). http://en.wikipedia.org/wiki/Mobile_Network_Code  Langue et région (internationalisation usuelle)  Taille de l’écran (small, medium, large et xLarge)  Rapport largeur/longueur (long ou not long) de l’écran  Orientation de l’écran (port pour portrait, land pour landscape ou square pour carré)  Densité de l’écran en pixel (ldpi pour low dpi, mdpi pour medium dpi, hdpi pour high dpi, xhdpi)  Type d’écran tactile (notouch pour non sensitif, stylus pour le stylet et finger pour sensitif)  Visibilité du clavier (keyexposed pour clavier physique apparent, keyshidden pour clavier physique caché ou keysoft pour un clavier logiciel)  Type de clavier (nokeys, qwerty ou 12Key ???)  Type de navigation (nonav pour pas de navigation, dpad pour le pad, trackball pour trackball et wheel pour la roue de la souris ???)  Version du système (v1,…v15,…) Ainsi pour définir la branche dans laquelle se trouve votre ressource, il faut spécifier son chemin :  Il faut définir dans l’ordre des paramètres ci-dessus listés,  On peut omettre des éléments, http://developer.android.com/guide/topics  Il faut un unique qualificateur par type de paramètre, /resources/providing-resources.html  Il faut les séparer par un trait d’union. Exemple : values-fr, drawable-hdpi, layout-large-port, values-v14,… 41
  • 42. MyLight et MyTorch disponible sur GooglePlay 42
  • 43. Merci pour votre attention. Merci à DEVOXX France et Bravo ! Et rendez-vous à Brazzaville en septembre android2ee.com. #android2ee MyLight et MyTorch mathias.seguy.it@gmail.com disponible sur GooglePlay 43