SlideShare una empresa de Scribd logo
1 de 71
vous présente :




Spécialiste Android Java J2EE

        Auteur du livre

disponible sur




                                   1
Formateur Consultant Expert Android
                                           mathias.seguy.it@gmail.com (mail)
                                                 @android2ee (twitter)
                                Fondateur Android2EE – Formation Expertise Android
                            Auteur d’EBooks sur la programmation Android (Android2ee.com)
                                       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

                                                                                                                                2
• Pourquoi de l’architecture ?

• Architecture d’applications Stand Alone (Swing)

• Android Application Design

• Android ProTips

• MutliVersionning & Resources are your
best friends

• Automatiser les tests !




                                                    3
4
Ex: L'activité utilise un service Rest pour mettre à jour des informations de manière cyclique.



                      Thread I.H.M                                   Thread de traitement
              Activity               Handler
                                                     sendMessage()                           REST Call

                                     message


                          OnDestroy()
                          OnCreate()

                                                               Thread de traitement initiale

                      Thread I.H.M
                                                      sendMessage()                           REST Call

               Activity          Handler
              fantôme            fantôme

                                                                      Thread de traitement
              Activity           Handler
                                                       sendMessage()                           REST Call

                                           message

                                                                                                           5
6
Le modèle N-Tiers et ses dépendances.
Chaque couche possède une interface.

Chaque couche possède un cahier des charges très précis.

Les dépendances entres les packages sont extrêmement importantes.



                                                                                              Internet
                                                                              Façade
                                                                                       COM
                                                                               COM



                                  Façade                                                      DataBase
                    IHM                       Service
                                  Service                            Façade
                                                                               DAO
                                                                      DAO

                                                                                             FileSystem
Use or not
                                                        Transverse

 Use


                                                                                                          7
Les fondations de l’application.

La couche transverse est connue de tous mais ne connait personne.




 Objet      Service Utilitaire Transverse    Service des Exceptions
 métiers

  PojoA         Log        HttpUtil             ExceptionManager

  PojoB       Tracker      DateUtil            ExceptionManaged

  DtoA                    StringUtil




                                                                      8
Le cerveau de l’application.

La couche service contient les services métiers.




                  LoginSrv                                      SimulationSrv                                     MainStreamSrv




                                                                                            MainStreamSrvIntf
                                 SimulationSrvIntf
  LoginSrvIntf




                 LoginSrvImpl                                                                                   MainStreamSrvImpl

                                                     SimulationSrvImpl
                  LoginUtil                                                                                       MSDisplaySrv

                  LoginCore                                                                                       MsUpdateSrv




                                                                                                                                    9
La mémoire de l’application.
                                                     La couche DAO : Data Access Object.

Elle n’expose ses services qu’au travers d’interfaces.

Utiliser les factory.

Expose les méthodes CRUD (Create, Read, Update, Delete) et autres méthodes spécifiques.




                                                           Human                   SqlUtil

                                                      HumanDaoFactory              SqlUtil
                                      HumanDaoIntf




                                                       HumanDaoHb8

                                                       HumanDaoJdbc

                                                        HumanDaoFS



                                                                                             10
La bouche et les oreilles de l’application.

La couche COM (communication) prend en charge l’accès aux données et services déportés sur un serveur (web ou autre).


On ne doit pas spécifier le type de communication mais le service rendu.




                                         ForecastCom
                                                                                           HttpComUtil
                                       ForecastComIntf
                                                                  use
                                                                                          HttpComUtilIntf

                                       ForecastComImpl
                                                                                          HttpComUtilImpl




                                                                                                                        11
Hiérarchie des packages de vues.


La couche IHM contient l’ensemble des écrans et se scinde en plusieurs sous-packages.


Une application hiérarchise ses vues, cette hiérarchie doit se retrouver dans vos packages.




                                                   Cohérence




                                                                                              12
Le modèle Model – (Vue Controller).

Le deuxième concept fort est la séparation entre l’affichage des objets et leur gestion.
                                                              La view affiche
                                                        le model gère les données.
Le model se charge de la gestion des objets affichés et la communication avec les services.




                                         1      1
                         FamilyView                  FamilyModel                              FamilySrvIntf
                             0                           0
                                                                             use
                             n                           n
                                         1      1
                         HumanView                   HumanModel                               HumanSrvIntf
                             0                           0

                             n                           n                   use
                                         1      1
                         AdressView                  AdressModel                              AdressSrvIntf




                                                                                                              13
14
Houston, we’ve got a problem.



Avec Android le problème est « Comment mettre en place ce Design en respect du cycle de vie des activités? ».




            Certaines application Swing ont un temps de boot de 30 secondes, et ce n’est pas possible sur Android.




                                                                                                                     15
Les contraintes sont:

Il faut que notre Design réussisse quatre challenges:

•On ne doit instancier un élément qu’à la demande;

•Quand un élément est instancié, il faut qu’il le reste;

•On ne doit pas détruire les éléments instanciés quand l’activité est
déconstruite pour être immédiatement reconstruite;

•On doit pouvoir laisser les traitements se terminer (au sens use case) tout en
étant capable de leur signaler que l’application est terminée...




                                                                                  16
L’enfer de la fragmentation



                                   Notre Design doit être capable de :

• Lancer l’application en mode Post-HoneyComb/ICS/JB ou en mode pre HoneyComb / ICS / JB,

•Instancier des composants en fonction de la version du système




                                                                                            17
Le Pattern Parrallel Activity étendu :



Instancier l’implémentation d’un service / d'une brique applicative en fonction de la
version du système.                                                                                        Human

                                                                                                       AServiceFactory




                                                                                        AServiceIntf
                                                                                                       AServiceV6Impl

                                                                                                       AServiceV11Imp

                                                                                                       AServiceV13Imp




                                                                                                                         18
19
Parrallel Activity Pattern and fragments :

Les activités sont devenues des coquilles vides qui écoutent les Intents, imposent le cycle de vie et re-routent les évènements vers les
fragments qui les composent. C’est la nouvelle philosophie générale.

Votre application lancera une première activité qui aura comme unique objectif de lancer soit l’activité dans son mode pré-HoneyComb soit
dans son mode post HC.

                  Ces deux activités utiliseront les mêmes classes de type Fragment (grâce à la support-librairy).

                                             Il faut décliner chaque Intent en post et pré HC.




                                                         ActivityLegacy     0


                                                                                1
                                         LauncherActivity                           Fragment
                                                                                1


                                                            ActivityHC      0


                                                                                                                                            20
Les fragment et les support.v4.app.Fragment ne sont pas compatibles:

                                          Ils ne possèdent pas d’interface commune.

                           Duplication du code de vos fragments (seules différences leurs imports).




                                 0    1
               ActivityLegacy              FragmentLeg



LauncherActivity


                                 0    1
                   ActivityHC               FragmentHC




                                                                                                      21
Les fragments (post-HC et pre-HC) partagent le même modèle.

Les fragments sont purement du code dupliqué. Les modèles sont indépendants de la version du système.

Chaque Fragment est associé à son modèle. Chaque activité se décline en deux types : pré et post HC.




                                           0     1
                          ActivityLegacy             FragmentLegacy
                                                         1

                                                         1                  use
          LauncherActivity                           FragmentModel                           AServiceSrvIntf
                                                         1

                                           0     1       1
                             ActivityHC               FragmentHC


                                                                                                               22
Le modèle MVC Android.

Le modèle MVC Android se décline en trois types :
                                                                                                                    0     1
None : Les données à afficher sont en read-only, peu de traitement au                              ActivityLegacy             FragmentLegacy

niveau des données.                                                             LauncherActivity
                                                                                                                    0     1
                                                                                                     ActivityHC                  FragmentHC
Simple : Chaque fragment gère ses données au moyen de son modèle.

Full : L’activité et les fragments ont des données corrélées qu’il faut
synchroniser au niveau des modèles.



                                        0     1                                                                     0    1
                     ActivityLegacy               FragmentLegacy                                   ActivityLegacy             FragmentLegacy
                                                       1                                                      1                    1
                                                                                   use                              ParentIntf
                                                       1                                                                           1
    LauncherActivity                                                                                      1
                                                  FragmentModel           LauncherActivity                                    FragmentModel
                                                       1
                                                                                                        ActivityModel
                                                                                                          1                        1

                                        0     1        1                                                      1                    1
                                                                                                                    0    1
                       ActivityHC                  FragmentHC                                       ActivityHC                   FragmentHC


                                                                                                                                               23
Votre package UI doit alors ressembler à
                         Attention à la duplication du code
                                                                           quelque chose comme le schéma ci-contre:




  Les activités/fragments Legacy, HC, ICS, JB possèdent le même modèle.




Il reste les problématiques :
•de la démultiplication des activités qui est plus fatigante en termes :
    • de code,
    •de maintenabilité
•et la duplication de code des fragments.




                                                                                                                      24
25
Base class for those who need to maintain global application state.
La classe application va nous permettre de répondre aux problématiques suivantes :
                                                 instancier un élément qu’à la demande;
                                                 un élément est instancié doit le rester;
    On ne doit pas détruire les éléments instanciés ne doivent pas être détruit quand l’activité est déconstruite/reconstruite;
                                           On doit pouvoir laisser les traitements se terminer


   L’objet application est créé dès que l’un des composants de votre application est instanciée et est détruite quand le dernier
                                                     composant est détruit.



      public class DesignApplication extends Application {                             Déclaration dans le AndroidManifest.xml
      HumanDaoIntf humanDao;
      /** * @return the humanDao */                                             <application
      public final synchronized HumanDaoIntf getHumanDao() {                      android:icon="@drawable/ic_launcher"
           if(humanDao==null) {                                                   android:label="@string/app_name" android:name=".MyApplication">
                humanDao=new HumanDaoCPImpl();
           }
           return humanDao;
      }
      }

                                                                                                                                                    26
Application, où es-tu?
                                   Utilisez le pattern du singleton.



public class DesignApplication extends              Déclaration dans le AndroidManifest.xml
Application {
@Override                                    <application
public void onCreate() {                       android:icon="@drawable/ic_launcher"
super.onCreate();                              android:label="@string/app_name" android:name=".MyApplication">
//First record the Application object
AppSingleton.INSTANCE.setApp(this);
…
}                                          Le code pour récupérer l’Application quand vous êtes ni dans
                                           une Activity ni dans un service :
public enum AppSingleton {
                                           //Retrouver l’application
INSTANCE;
                                           AppSingleton.INSTANCE.getApp();
private DesignApplication application;
/** * @return */
public DesignApplication getApp() {
return application;                        Le code pour récupérer l’Application quand vous êtes dans
}                                          une Activity ou dans un service :
/** * @param app */                        //Retrieve the application
public void setApp(Application app) {      (DesignApplication )getApplication();
application=app;
}
}

                                                                                                                 27
Les services métiers doivent :




                                                              finir leur traitement,
                                                         être instancié à la demande,
                                                         persister leur instanciation,
                                  ne pas suivre le cycle de vie de l'activité mais celui de l'application.




Pour résoudre ce problème vous avez deux choix :
   •Soit votre service métier est un service Android.
   •Soit ce n’est pas un service Android et il faut le faire à la main.


Le second cas est complexe est n’est pas recommandé.

                                                                                                             28
Les services Android sont les services métiers de l'application.




                                                                                          Net
                                                                           Façade
                                                                                    COM
                                                                            COM


                                          Service
             Couche             Façade                                                    DB
                                          Métier
              IHM               Service
                                          Android                 Façade
                                                                            DAO
                                                                   DAO
                                                                                           FS
Use or not
                                          Transverse

  Use




                                                                                                29
Le ServiceLoader
Le service Loader a pour objectif :
•de lancer les services de l'application,
•de se lier à eux en mode bind (et ainsi conserver un pointeur vers eux),
•de se délier à eux quand l'application s'arrête (et ainsi de les arreter).

                                                  LazyLoading
                                                                                                                     Pour cela,
                                                                                       DaughterService2
                                                                           1-1                                       •C'est un singleton (une
                                                                                                                     énumération)
                                                   ServiceLoader                                  DaughterService1   •Il connait ses services via une
                                                                                 1-1                                 liste de ServiceConnection
                                                                                                ServiceLoader
                                                                                                                     •Possède une méthode d'arrêt.
  Caption                                                       BIND
                                         1
                   LazyLoading                                                                                        Et il faut l'écrire à la main.
 WorkFlow                            getService                                                                       N'appartient pas au SDK.
                                                                                   MService
                                                     2

                                                     callBack
 Contains



 Extends         DaughterActivity
                                                         service.doSomething()

                                                                 3




                                                                                                                                                       30
Le serviceLoader : Mise en place du LazyLoading
private void launchServiceAsync() {                       Activity             /** * The method to be called by the activities                     ServiceLoader
// load your service...                                                        @return the dService (could be null if not started yet) */
ServiceLoader.instance.getdService(new OnServiceCallBack() {                   public void getdService(OnServiceCallBack onServiceCallBack) {
      public void onServiceCallBack(MService service) {                             startDummySrv(); // insure the service is started
      // so just call the method you want of your service                           // then if the service is null add the callBack to the list of elements waiting for the service
            ((DummyService) service).doSomethingAsynch(getActivityId());            to be instantiated
      }});}                                                                         if (dService == null) {// add to the callback list
                                                                                          onDServiceCallBack.add(onServiceCallBack);
/** * The service you want to expose to activities */          ServiceLoader        } else {// else, service is not null, just use directly the callback
private DummyService dService = null;
                                                                                          onServiceCallBack.onServiceCallBack(dService);
/** * The list of the callback of the service instantiation */
                                                                                    }}
private List<OnServiceCallBack> onDServiceCallBack;
/** * Method to start the DummyService service */                              /** * The object to handle the connection of this with the service. So this will keep a pointer on
private void startDummySrv() {// insure the list is not null                   the service not loosing it in the memory. */                             ServiceLoader
     if (onDServiceCallBack == null) {onDServiceCallBack = new                 private ServiceConnection dummySrvConn = new ServiceConnection() {
     ArrayList<OnServiceCallBack>();}                                          // as usual deconnexion
     // if the service is null, launch it using the Bind process               @Override
     if (dService == null) {                                                   public void onServiceDisconnected(ComponentName name) {dService = null;}
            Intent service = new                                               // as usual connection
            Intent(MAppInstance.ins.getApplication(), DummyService.class)      @Override
            ;                                                                  public void onServiceConnected(ComponentName name, IBinder service) {
            MAppInstance.ins.getApplication().bindService(service, dummySrv          // use the IBinder
            Conn,Service.START_STICKY);}                                             dService = (DummyService) ((MService.LocalBinder) service).getService();
      // add it to the list of bound services (if not in yet):                        // notify callback the service is awake
     if(!boundServices.contains(dummySrvConn))                                       for (OnServiceCallBack callBack : onDServiceCallBack) {
     {boundServices.add(dummySrvConn);}                                                    callBack.onServiceCallBack(dService);
}                                                                                    }// and clear the callback list
                                                                                     onDServiceCallBack.clear(); onDServiceCallBack = null;}};                                  31
Persister les services : l'objet Application instancie le ServiceLoader

                                   Persitence des services                                                     public class MApplication extends
                                                                                                               Application {
                                                                                 DaughterService2              /** * Just keep a reference on it to
                              Persistence                            1-1
                                                                                                               avoid unusefull
                                   1-0                                                                         destruction/recreation of services */
 Caption      Application                    ServiceLoader                                  DaughterService1   private ServiceLoader sLoader;
                                                                           1-1
                                                                                                               @Override
                                                                                                                    public void onCreate() {
WorkFlow                                                  BIND
                                                                                                                    ...
                                    1
            LazyLoading                                                                                             // keep the ref
                                getService                                                                          sLoader =
Contains                                                                     MService
                                              2                                                                     ServiceLoader.instance;
                                               callBack                                                        }
Extends                                                                                                        /**
                                                                                                                * This method has to be called when
           DaughterActivity                                                                                    the application died. It kill all the
                                                   service.doSomething()                                       services So find the activity that quit
                                                           3                                                   the application and add that method
                                                                                                               */
                                                                                                               public void onBackPressed() {
                                                                                                                    // Call the application object and
                                                                                                                    release the services
                                                                                                                    sLoader.unbindAndDie();
                                                                                                               }
                                                                                                               }
                                                                                                                                                    32
Communication
                                                                                                                    Service-Activity
                                                                          1
                        DaughterActivity                                                                         DaughterService1
                                                       service.doSomething(String ActivityId)
         4
 onServiceCallBack                                                                                                                 2
(int serviceMethodId,
                            MActivity                                                                               callBack(methodID, activityID, result);
     Object result)
                                                                           3
                                 1-1
                                               Build And Launch Intent to the Activity using its ActivityId

                        BroadCastReceiver                                                                     ServiceHelper


                                            Caption      WorkFlow              Contains           Extends




                                                                                                                                                              33
Objectif pour le développeur final : peu de code.
public abstract class MyActivity extends MActivity {...                  Activity       /** Retrieving results from business services calls *******/              Activity
private void launchServiceAsync() {                                                     /** The method to implement to root your service call with the method that handle
// find your service...(lazy loading part)                                              the return. It's called back via intent through MActivity. So you just need to check
ServiceLoader.instance.getdService(new OnServiceCallBack() {                            your method id and do something with your result */
public void onServiceCallBack(MService service) {
                                                                                    4   protected void onServiceCallBack(int serviceMethodId, Object result) {
// so just call the method you want of your service
((DummyService) service).doSomethingAsynch(getActivityId());}});}               1
                                                                                        switch (serviceMethodId) {
                                                                                        case DummyService.doSomethingID:
public class DummyService extends MService {                                                 // call your result method doSomethingResult(result)
                                                                  Service                    onServiceResult((ConstantData) result); 5
/**
 * The id of the method doSomething                                                     break;
                                                                 Activity
 * It has to be unique for your whole application and for each service'method           default:
of it.                                                                                  break;}
 */                                                                                     }
public static final int doSomethingID = 10000101;                                       private void onServiceResult(ConstantData message) { 6
/** * A dummy method with the return sent to the calling activity                       // You can also display a indeterminate progress bar
 * * @param activityId The unique id of the calling activity */                         simpleServiceCall--;
public void doSomething(String activityId) { 2                                          if(simpleServiceCall==0) {
// do your treatment                                                                         prbResultSimple.setVisibility(View.GONE);}
ConstantData data = new ConstantData("SomeResuls", 11021974, true);                     txvResultSimple.setText(message.message);}
// And the important part is here
// When your treatment is over, just use the serviceHelper to contact the calling
Activity and to send the method return to that activity
ServiceHelper.instance.callBack(doSomethingID, activityId, data); 3
}


                                                                                                                                                                               34
L'activité mère
public abstract class MActivity extends Activity {                                            1) Mise en place de l'écoute transparente des Intents via une
/** * @return a unique identifier of the activity to be attached to intents that have to be      activité mère.
calledBack by the activity */                                                                 2) Enregistrement en tant qu'écouteur d'intents qui ont pour
public String getActivityId() {// so use the canonical name it should be enough
                                                                                                 action le getActivityId
return getClass().getCanonicalName();}
                                                                                              3) Parcing du retour dans le BroadcastReceiver et appel de
protected abstract void onServiceCallBack(int serviceMethodId, Object result);                   la méthode onServiceCallBack

private BroadcastReceiver serviceCallBackReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MActivity", "serviceCallBackReceiver:onReceive, called: " + intent.getAction());
// first be sure to listen for the right intent
if (intent.getAction() == getActivityId()) {
// retrieve the type of the result object
String resType = intent.getStringExtra(ServiceHelper.SRV_MTH_RES_TYPE);
// using that type, retrieve the result object
// there will be a lot of case, should be the same case than the number of
                                                                                          @Override
// intent.get**Extra method
                                                                                          protected void onResume() {
if (resType.equals(ServiceHelper.Parcelable)) {
                                                                                          super.onResume();
       onServiceCallBack(intent.getIntExtra(ServiceHelper.SRV_MTH_ID, -1),
                                                                                           registerReceiver(serviceCallBackReceiver, new IntentFilter(getActivityId()));}
       intent.getParcelableExtra(ServiceHelper.SRV_MTH_RES));
                                                                                          @Override
} else if (resType.equals(ServiceHelper.String)) {
                                                                                          protected void onPause() {
// other case
                                                                                          super.onPause();
       onServiceCallBack(intent.getIntExtra(ServiceHelper.SRV_MTH_ID, -1),
                                                                                          unregisterReceiver(serviceCallBackReceiver);}
       intent.getStringExtra(ServiceHelper.SRV_MTH_RES));
                                                                                          }
}// and so on}}};
                                                                                                                                                                        35
Le service mère
       1) Mise en place du Binding automatique des services avec le
          service locator



public class MService extends Service {
/** The binder process ***********/
/** * The Binder */
private final Binder binder = new LocalBinder();
/** *This class aims to be a local Binder that keep and share a pointer on the instance of this
*/
public class LocalBinder extends Binder {
     // as usual
     public MService getService() {// return the instance of the service
           return MService.this;}
     }
@Override
public IBinder onBind(Intent intent) {
     return binder;
}
@Override
public void onDestroy() {
     super.onDestroy();
}
}


                                                                                                  36
Les services filles
1) Déclare les identifiants de méthode du service
2) Mets en place les méthodes du services
3) Et renvoie toujours le résultat via:
   ServiceHelper.instance.callBack(doSomethingID, activityId, data);


 public class DummyService extends MService {
 /**
  * The id of the method doSomething
  * It has to be unique for your whole application and for each service'method of it.
  */
 public static final int doSomethingID = 10000101;
 /** * A dummy method with the return sent to the calling activity
  * * @param activityId The unique id of the calling activity */
 public void doSomething(String activityId) {
 // do your treatment
 ConstantData data = new ConstantData("SomeResuls", 11021974, true);
 // And the important part is here
 // When your treatment is over, just use the serviceHelper to contact the calling Activity
 // and to send the method return to that activity
 ServiceHelper.instance.callBack(doSomethingID, activityId, data);
 }




                                                                                              37
Le ServiceHelper
1) Construit et envoie les Intents dans le système pour être automatiquement récupérés par les activités appelantes.



public enum ServiceHelper {                                             /** CallBack ******/
instance;                                                               /** * This method just create an Intent and launched it
/** Constants ***/                                                       * @param serviceMethodId : The method that ask for sending the result to the activity
/** The constant to be used by intent to carry the service's method's    * @param activityId : The activity that calls the method, the intent will be received by it
id */                                                                    * @param result: The object to carry (the result object of the method) */
public static final String SRV_MTH_ID =                                 public void callBack(int serviceMethodId, String activityId, Object result) {
"com.android2ee.service.method.id";                                     //create the Intent
/** * The constant to be used by intent to carry the service's          Intent callBack = new Intent(activityId);
method's result */                                                      //add the service method id
public static final String SRV_MTH_RES =                                callBack.putExtra(SRV_MTH_ID, serviceMethodId);
"com.android2ee.service.method.result";                                 //your object should implements Parcelable
/** * The constant to be used by intent to carry the service's          //add the type of the result object (to unparse)
method's result */                                                      if (result instanceof Parcelable) {
public static final String SRV_MTH_RES_TYPE =                                 callBack.putExtra(SRV_MTH_RES, (Parcelable) result);
com.android2ee.service.method.result.type";                                   callBack.putExtra(SRV_MTH_RES_TYPE,Parcelable);
                                                                        }else if( result instanceof String) {
                                                                              callBack.putExtra(SRV_MTH_RES, (String) result);
                                                                              callBack.putExtra(SRV_MTH_RES_TYPE,String);
                                                                        }//and so on
                                                                        //Then send the Intent
                                                                        MAppInstance.ins.get().sendBroadcast(callBack);
                                                                        }
                                                                        }
                                                                                                                                                                       38
ServiceHelper et ServiceLoader full pattern
                                                                                                            DaughterService2
                                             Persistence                                        1-1

 Caption                                          1-0
                              Application                        ServiceLoader                                           DaughterService1
                                                                                                      1-1
WorkFlow
                                                                                  BIND
                                                   1
Contains                    LazyLoading
                                               getService
                                                                                                         MService
                                                                     2
Extends
                                                                     callBack

                                                                                                                                                       Communication
                          DaughterActivity                                                                                                             Service-Activity
           6                                                               service.doSomething()

   onServiceCallBack                                                                3                                                   4
  (int serviceMethodId,
                              MActivity                                                                                           callBack(methodID, activityID, result);
       Object result)
                                                                                   5
                                   1-1
                                                       Build And Launch Intent to the Activity using its ActivityId

                          BroadCastReceiver                                                                           ServiceHelper




                                                                                                                                                                            39
Le projet MythicServiceHelper imlplémente ce pattern (version alpha draft)
                      Tout le code est disponible :
   https://github.com/MathiasSeguy-Android2EE/MythicServiceHelper




                                                                             40
Les services métiers sont des services Android.



                           Application                                   Service                                                      Net
                                                                                                        Façade
                                                                         Métier                                   COM
                                                                                                         COM
                                                                         Android
                              Couche
                               IHM                        Façade
                                                          Service    ServiceLoader                                                     DB

                              MActivity                              ServiceHelper             Façade
     start                                                                                               DAO
                                                                       MService                 DAO
                                                                                                                                        FS
   Use or not


                                                                    Transverse
     Use




                                                          Préserver les interfaces
Il est important de pouvoir changer la manière dont fonctionne un service sans avoir à modifier le reste de l‘application. Il doit pouvoir
conserver son interface tout en changeant son implémentation sans pour autant impacter le reste de l’application.



                                                                                                                                             41
La couche BroadCast est une couche à part entière


                       BroadCast
                        Receiver                                                          Net
                                                                           Façade
                                                                                    COM
                                                                            COM




                                             Service                                      DB
             Couche                Façade
                                             Métier
              IHM                  Service
                                             Android
  start
                                                                  Façade
                                                                            DAO
                                                                   DAO
                                                                                           FS

Use or not
                                             Transverse



  Use



                                                                                                42
Où se trouve le ContentProvider ?
La couche DAO pose le problème de « où mettre les ContentProvider ? ».
Pour rappel:

  “You don't need to develop your own provider if you don't intend to share your data with other applications. However, you do need your
   own provider to provide custom search suggestions in your own application. You also need your own provider if you want to copy and
                    paste complex data or files from your application to other applications.” dixit developer.android.com

                                                   les ContentProviders sont vos DAO publiques

Ainsi vos DAO contiennent bien vos ContentProvider et le Design est celui-ci :

                                                                   Cela ne veut pas dire que toutes vos DAO doivent posséder un
                                                                   ContentProvider, mais que si elles en contiennent un elles le mettent à la
                                    Human                          même hauteur que son interface. En effet, il n’y a qu’une implémentation
                                                                   pour un ContentProvider.
                 HumanContentProvider   HumanDBOpenHelper
  HumanDaoIntf




                   HumanDaoSQLite                                  Se posera à vous la question de la redondance des méthodes. Pour cela
                                                                   vous pouvez re-router les méthodes de votre ContentProvider vers votre
                   HumanDaoOrlite           HumanDaoFactory        interface de DAO, ce qui est le plus propre.
                     HumanDaoFS



                                                                                                                                                43
Pas de changement avec l'architecture n-tiers usuelle d'applications stand-alones.
                                     NDK.




                                                                                     44
J’attire votre attention sur la nécessité de mettre en place un gestionnaire d’exception qui vous permettent de les logger/persister en
base/afficher à l’utilisateur.
                                                         Service des Exceptions


                                                            ExceptionManager

                                                           ExceptionManaged




                                                                                                                                          45
BroadCast
                          Receiver                                                              Net
                                               Application
                                                                                 Façade
                                                                                          COM
                                                                                  COM

              Couche                           Service Métier Android
               IHM
                                                 ServiceLoader                                  DB
                                     Façade
                                     Service
             MActivity                            ServiceHelper
  start
                                                                        Façade
                                                                                  DAO
                                                    MService             DAO
                                                                                                 FS


Use or not


                                                 Transverse


  Use



                                                                                                      46
La solution au problème des Threads de traitements.




                       Thread I.H.M                                 Thread de traitement
                Service
OnDestroy()                                         sendMessage()                          REST Call
OnCreate()


                                      Handler
              BIND

                                      message


                 Activity




                                                                                                       47
48
From Google I/O And Devoxx

Ce chapitre est un extrait des « meilleurs » proTips donnés par les équipes Google lors des GoogleI/O, notamment :


•Android ProTips, Reto Meier, Google I/O 2011

•Making Good Apps Great , Reto Meier, Google I/O 2012

•Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010



Merci à eux pour ces présentations.




                                                                                                                     49
Use ViewStub

  La ViewStub permet le lazy loading de layouts.
   <ViewStub
   android:id="@+id/stub_import"
   android:inflatedId="@+id/panel_import"
   android:layout="@layout/progress_overlay"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:layout_gravity="bottom" />




                                                                                                         id/panel_import



                                           findViewById(R.id.stub_import).setVisibility(View.VISIBLE);
                                           // or
                                           View importPanel = ((ViewStub)
             id/stub_import                findViewById(R.id.stub_import)).inflate();



From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
                                                                                                                           50
Use merge et include
                                                                                            Without merge   With merge
  Le merge permet d’inclure les layouts les uns dans les
  autres sans redondance. Cela permet aussi la
  décomposition et la réutilisation des layout.

   <!-- The merge tag must be the root tag -->
   <merge
   xmlns:android="http://schemas.android.com/apk/res/android">
   <!-- Content -->
   </merge>

   <!– The include tag is the one to use-->
   <LinearLayout …>
     <include layout="@layout/subLayout" />
     <LinearLayout> .. </LinearLayout>
   </LinearLayout>




From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
                                                                                                                         51
ListView and ArrayAdpater : Use ViewHolder and convertView




   public View getView(int position, View convertView, ViewGroup parent) {                  static class ViewHolder {
    ViewHolder holder;                                                                       TextView text;
   if (convertView == null) {                                                                ImageView icon;
         convertView = mInflater.inflate(R.layout.list_item_icon_text, parent, false);       }
         holder = new ViewHolder();
         holder.text = (TextView) convertView.findViewById(R.id.text);
         holder.icon = (ImageView) convertView.findViewById(R.id.icon);
         convertView.setTag(holder);
    } else {
         holder = (ViewHolder) convertView.getTag();
    }

    holder.text.setText(DATA[position]);
    holder.icon.setImageBitmap((position & 1) ==? mIcon1 : mIcon2);

    return convertView;
    }



From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
                                                                                                                        52
Know your Network and Battery context


                                      <receiver android:name="DeviceStateReceiever" >
                                             <action android:name="android.intent.action.ACTION_DOCK_EVENT" />
                                             <action android:name="android.intent.action.ACTION_BATTERY_LOW" />
                                             <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                                             <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
                                             <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                                             <action android:name="android.intent.action.BOOT_COMPLETED" />
                                             <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                                             <action android:name="android.net.wifi.STATE_CHANGE" />
                                          </receiver>
                                      ConnectivityManager cm = (ConnectivityManager)
                                      context.getSystemService(Context.CONNECTIVITY_SERVICE);

                                      NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
                                      boolean isConnected = activeNetwork.isConnectedOrConnecting();
                                      boolean isMobile = activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE;




Android ProTips, Reto Meier, Google I/O 2011
                                                                                                                         53
KeyBoard and EditText : Customize KeyBoard and set Action
  Quand vous définissez un champ de type EditText vous devez définir :
         • Son type de clavier
         • L’action IME
         • (et le Hint)
  <EditText                                               EditText.OnEditorActionListener myActionListener = new
      android:id="@+id/editEmailInput"                    EditText.OnEditorActionListener() {
      android:layout_width="match_parent"                 @Override
      android:layout_height="wrap_content"                public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
      android:hint="@string/compose_email_hint"               if (actionId == EditorInfo.IME_ACTION_DONE) {
      android:imeOptions="actionSend|flagNoEnterAction"            // do here your stuff f
      android:inputType="textShortMessage|                         return true;
              textAutoCorrect|                                }
              textCapSentences" />                                 return false;
                                                              }
                                                          };




Android ProTips, Reto Meier, Google I/O 2011
                                                                                                                                      54
Always be asynchronous
                                           Rendez tout asynchrone en utilisant:
                                           •le ServiceHelper;
                                           •les Handler, Asynctask;
                                           •IntentService (le système des Intents quoi);
                                           •AsyncQueryHandler (le GetContentResolver en un sens);
                                           •Loader (abstractClass) and CursorLoader (HoneyComb only).




Android ProTips, Reto Meier, Google I/O 2011
                                                                                                        55
Use the big cookies strategy when possible

  Préférez transférer un gros paquet de données au travers d’internet quand c’est possible plutôt que plein de petits paquets.

                                  int prefetchCacheSize = DEFAULT_PREFETCH_CACHE;
                                       switch (activeNetwork.getType()) {
                                            case ConnectivityManager.TYPE_WIFI:
                                                prefetchCacheSize = MAX_PREFETCH_CACHE;
                                                break;
                                            case ConnectivityManager.TYPE_MOBILE): {
                                                switch (telephonyManager.getNetworkType()) {
                                                     case TelephonyManager.NETWORK_TYPE_LTE:
                                                     case TelephonyManager.NETWORK_TYPE_HSPAP:
                                                         prefetchCacheSize *= 4; break;
                                                     case TelephonyManager.NETWORK_TYPE_EDGE:
                                                     case TelephonyManager.NETWORK_TYPE_GPRS:
                                                         prefetchCacheSize /= 2; break;
                                                     default: break;
                                            } break;
                                       }
                                       default: break;
                                   }


Making Good Apps Great, Reto Meier, Google I/O 2012
                                                                                                                                 56
57
From Google I/O 2012

Ce chapitre est un extrait de la conférence des Google I/O 2012 :


•Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012




Qui est exceptionnel sur la lutte contre la fragmentation, un très grand moment, merci à eux.




                                                                                                58
Be Lazy

  Utiliser une classe abstraite qui sera instanciée par une factory et renverra l’implémentation correspondant à le version du système.

                                                                                                                   Activity
     public abstract class VersionedLoremIpsum {
                                                                                                       VersionedLoremIpsum li;
     public abstract String doLorem();
                                                                                                       li=VLIFactory.get()
     public abstract int doIpsum();
     }

     public class EclairLoremIpsum               public class FroyoLoremIpsum                                       VLIFactory
     extends VersionedLoremIpsum {               extends EclairLoremIpsum {                  public static VersionedLoremIpsum get(
     public String doLorem() {                   public String doLorem() {                       int sdk = Build.VERSION.SDK_INT;
     // do lorem, Eclair-style                   String l = super.doLorem();                     if (sdk <= Build.VERSION_CODES.ECLAIR) {
     }                                           // additional processing                        li = new EclairLoremIpsum();
     public abstract int doIpsum() {             return l;                                       } else if (sdk <=
     // deliver ipsum, a là Eclair               }                                               Build.VERSION_CODES.FROYO) {
     }                                           public abstract int doIpsum() {                 li = new FroyoLoremIpsum();
     }                                           ...                                             } else {
                                                                                                 li = new GingerbreadLoremIpsum();
                                                                                                 }
                                                                                             )



Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                                            59
Resources are your best friend, use them.

  Utilisez des booléens pour savoir quelle est la version du système. Ils s’utilisent dans le code et dans le Manifest.xml.

                                           Resvalues-v14bools.xml                             Resvaluesbools.xml
                                    <?xml version="1.0" encoding="utf-8"?>             <?xml version="1.0" encoding="utf-8"?>
                                    <resources>                                        <resources>
                                    <bool name="postICS">true</bool>                   <bool name="postICS">false</bool>
                                    <bool name="preICS">false</bool>                   <bool name="preICS">true</bool>
                                    </resources>                                       </resources>



                                      SomeWhere in java                                                    Manifest
                      Resources res = getResources();                                  <receiver android:name="MyPreICSAppWidget"
                      boolean postICS =                                                android:enabled="@bool/preICS">
                      res.getBoolean(R.bool.postICS);                                  ...
                      if (postICS) {                                                   </receiver>
                      // do something cool and cutting-edge                            <receiver android:name="MyPostICSAppWidget"
                      } else {                                                         android:enabled="@bool/postICS">
                      // do something old-school but elegant!                          ...
                      }                                                                </receiver>



Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                                     60
Hériter du thème de la version.

  Restez cohérent avec le thème du SDK de l’appareil cible, conservez une application cohérente avec l’appareil.




                                resvalues-v11theme.xml                                                            MyTheme
       <style name="MyAppThemeBase" parent="@android:style/Theme.Holo" />
       <style name="MyButtonStyle" parent="@android:style/Widget.Holo.Button">
                                                                                                               MyBaseTheme
                             resvaluestheme.xml
       <style name="MyAppThemeBase" parent="@android:style/Theme" />
       <style name="MyAppTheme" parent="MyAppThemeBase">
       <style name="MyButtonStyle" parent="@android:style/Widget.Button">

                                                                                                            Theme         Theme.Holo




Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                                       61
Utiliser les Fragments et l’ActionBar sur toutes vos versions.

  Ayez une application identique quelque soit la version du système et utilisez le même fichier de layout.

               public class BaseActivityHC extends Activity{...}

               public class BaseActivityLegacy extends android.support.v4.app.FragmentActivity {...}
                                                        android.support.v4.app.ActionBarActivity


               public class SpeakerDetailFragmentHC extends Fragment {

               public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  View view = inflater.inflate(R.layout.speaker_detail, container, false);
                  return view;
               }

               public class SpeakerDetailFragment extends android.support.v4.app.Fragment {

               public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  View view = inflater.inflate(R.layout.speaker_detail, container, false);
                  return view;
               }


Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                     62
Utiliser les notifications PreJB, PostJB.

  Utilisez les notifications sur toutes les versions avec le NotificationCompat.Builder.
  Les notifications sont une des grandes évolutions de JellyBean.
  Le NotificationBuilder a été délivré pour HC, mais si vous voulez profitez des évolutions sur toutes les versions, il faut utiliser le
  NotificationCompat.Builder.
                                                                if version >= JellyBean
                                                                     use Notification.Builder
                                                                else
                                                                     use NotificationCompat.Builder
                           private void pushInboxNotifications() {
                           Notification notification = new Notification.Builder(this)
                                .setContentTitle("10 New emails for me")
                                .setContentText("subject")
                                .setSmallIcon(android.R.drawable.ic_menu_agenda)
                                .setStyle(Notification.InboxStyle)
                                .addLine("Line 1, i can add more if i want")
                                .addAction(R.drawable.icon,R.string.notification_message,new PendingIntent(....))
                                .setSound(aSound)
                                .build();
                           NotificationManager
                           notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
                           notificationManager.notify(0, notification);
                           }
Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                                           63
L’ordre des boutons a changé depuis ICS.

  Avant ICS le bouton OK est à gauche, le bouton non ou cancel à droite.
  Après ICS le bouton OK est à droite, le bouton non ou cancel à gauche.




Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                           64
Min, max et target SDK importe.

  Définissez toujours votre targetSdk comme le plus haut possible pour profiter des nouveautés du système.
  En d’autres termes, toujours tester votre application avec la plus haute version du système et si elle fonctionne, définissez votre
  targetSDK comme étant celui-là.



                                                           <uses-sdk
                                                               android:maxSdkVersion="16"
                                                               android:minSdkVersion="8"
                                                               android:targetSdkVersion="16" />




  ps: le maxSDK s'utilise uniquement pour proposer différents apk en fonction de la version du système au niveau de GooglePlay.


Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
                                                                                                                                        65
66
Ne pas oublier le projet de Tests.

L’architecte a à charge la conception de l’application mais aussi la conception de l’application
                                             de test.

                                             Ne l'oubliez pas.




                                  Pour aller plus loin, vous pouvez acheter :
                                  Android An Entreprise Edition Vision
                                                                                                   67
Ces outils sont :


    • Le SDK de Test fourni par Android,


    • JUnit 3 (intégré au SDK d’Android),


    • Maven pour construire l’application,


    • Jenkins pour lancer Maven et passer les tests sur différents émulateurs




                                                                                68
Communauté Google+ Android projects on Github
                     Github open source projects
https://plus.google.com/u/0/communities/100609058582053363304




                                                                69
Cette conférence utilise les références suivantes :
Les EBooks et tutoriels d’Android2ee : http://www.android2ee.com
Les sites de référence Android:
                    • http://developer.android.com/index.html
                    • http://android-developers.blogspot.fr/
                    • http://www.google.com/events/io/2011/sessions.html
                    • https://developers.google.com/events/io/sessions

Sur Android2ee, vous trouverez les tutoriels libres suivants pour approfondir les notions présentées:
                  • Les capteurs
                  • Les thread de traitement (Handler et fuite mémoire)
                  • Les AppWidgets
                  • Construction dynamique d’IHM
                  • Service REST
                  • Lecteur de flux RSS
                  • Le fichier POM pour mavéniser vos projets
                  • Comment préparer ses livraisons sur GooglePlay

Sur developpez.com vous trouverez les articles du conférencier :
                  • Déployer son application Android et obtenir sa clef MapView.
                  • Construire dynamiquement ses IHM Android
                  • Les capteurs Android
                  • Thread, Handler, AsyncTask et fuites mémoires
                  • Investir l'écran d'accueil Android avec les AppWidgets
                  • Android, Livrer son projet sur GooglePlay
                                                                                                        70
Merci pour votre attention.




                                       android2ee.com.
                                         #android2ee             Jcertif Mobile
                                                                sur GooglePlay
MySensors, MyLight et MyTorch   mathias.seguy@android2ee.com
  disponible sur GooglePlay
                                                                                  71

Más contenido relacionado

La actualidad más candente

CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)Mathias Seguy
 
Cours android
Cours androidCours android
Cours androidAd Hafsa
 
FelixDroid: Application de gestion du framework Felix pour Android
FelixDroid: Application de gestion du framework Felix pour AndroidFelixDroid: Application de gestion du framework Felix pour Android
FelixDroid: Application de gestion du framework Felix pour AndroidOSGi User Group France
 
DES205 - Ne ratez pas le METRO
DES205 - Ne ratez pas le METRODES205 - Ne ratez pas le METRO
DES205 - Ne ratez pas le METROAudreyPetitPro
 
Design : Ne ratez pas le METRO
Design : Ne ratez pas le METRODesign : Ne ratez pas le METRO
Design : Ne ratez pas le METROMicrosoft
 
Framework Hibernate
Framework HibernateFramework Hibernate
Framework HibernateInes Ouaz
 
Techdays 2012 - Tout sur Microsoft Speech
Techdays 2012 - Tout sur Microsoft SpeechTechdays 2012 - Tout sur Microsoft Speech
Techdays 2012 - Tout sur Microsoft Speechsputier
 
Les ateliers android_1_vers2015
Les ateliers android_1_vers2015Les ateliers android_1_vers2015
Les ateliers android_1_vers2015Sabeur LAJILI
 
Java 110605092007-phpapp02
Java 110605092007-phpapp02Java 110605092007-phpapp02
Java 110605092007-phpapp02Eric Bourdet
 
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...La dure lutte du développeur : 10 trucs pratiques pour une application mobile...
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...Microsoft
 
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...Microsoft
 
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileNouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileIppon
 
Environnement java
Environnement javaEnvironnement java
Environnement javaInes Ouaz
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EEInes Ouaz
 
Restlet et le multi-plateforme
Restlet et le multi-plateformeRestlet et le multi-plateforme
Restlet et le multi-plateformeJerome Louvel
 

La actualidad más candente (19)

CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)
 
Cours android
Cours androidCours android
Cours android
 
FelixDroid: Application de gestion du framework Felix pour Android
FelixDroid: Application de gestion du framework Felix pour AndroidFelixDroid: Application de gestion du framework Felix pour Android
FelixDroid: Application de gestion du framework Felix pour Android
 
DES205 - Ne ratez pas le METRO
DES205 - Ne ratez pas le METRODES205 - Ne ratez pas le METRO
DES205 - Ne ratez pas le METRO
 
Design : Ne ratez pas le METRO
Design : Ne ratez pas le METRODesign : Ne ratez pas le METRO
Design : Ne ratez pas le METRO
 
Framework Hibernate
Framework HibernateFramework Hibernate
Framework Hibernate
 
Support POO Java Deuxième Partie
Support POO Java Deuxième PartieSupport POO Java Deuxième Partie
Support POO Java Deuxième Partie
 
Techdays 2012 - Tout sur Microsoft Speech
Techdays 2012 - Tout sur Microsoft SpeechTechdays 2012 - Tout sur Microsoft Speech
Techdays 2012 - Tout sur Microsoft Speech
 
Les ateliers android_1_vers2015
Les ateliers android_1_vers2015Les ateliers android_1_vers2015
Les ateliers android_1_vers2015
 
Java 110605092007-phpapp02
Java 110605092007-phpapp02Java 110605092007-phpapp02
Java 110605092007-phpapp02
 
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...La dure lutte du développeur : 10 trucs pratiques pour une application mobile...
La dure lutte du développeur : 10 trucs pratiques pour une application mobile...
 
Chap 02 poo en java
Chap 02 poo en javaChap 02 poo en java
Chap 02 poo en java
 
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...
Applications métiers et/ou d'entreprise sur Windows Phone 7 - bonnes pratique...
 
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileNouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
 
Environnement java
Environnement javaEnvironnement java
Environnement java
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EE
 
Introduction a Android
Introduction a AndroidIntroduction a Android
Introduction a Android
 
Restlet et le multi-plateforme
Restlet et le multi-plateformeRestlet et le multi-plateforme
Restlet et le multi-plateforme
 
Cours de Génie Logiciel / ESIEA 2013-2014
Cours de Génie Logiciel / ESIEA 2013-2014 Cours de Génie Logiciel / ESIEA 2013-2014
Cours de Génie Logiciel / ESIEA 2013-2014
 

Destacado

Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Loïc Knuchel
 
Développement Android
Développement AndroidDéveloppement Android
Développement AndroidFranck SIMON
 
01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)TECOS
 
Traitement numérique des images - Projet Android "Virtual Pong" - Présentation
Traitement numérique des images - Projet Android "Virtual Pong" - PrésentationTraitement numérique des images - Projet Android "Virtual Pong" - Présentation
Traitement numérique des images - Projet Android "Virtual Pong" - PrésentationValentin Thirion
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chatLoïc Knuchel
 
Algea - 04 - conclusion
Algea - 04 - conclusionAlgea - 04 - conclusion
Algea - 04 - conclusionYann Caron
 
Angular 4 - ngfor -- Français
Angular 4  - ngfor -- FrançaisAngular 4  - ngfor -- Français
Angular 4 - ngfor -- FrançaisVERTIKA
 
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...Grégoire Arnould
 
1cours virologie généralités (1)
1cours virologie généralités (1)1cours virologie généralités (1)
1cours virologie généralités (1)imlen gan
 
Android Studio, premier contact
Android Studio, premier contactAndroid Studio, premier contact
Android Studio, premier contactJasmine Conseil
 
04 programmation mobile - android - (db, receivers, services...)
04 programmation mobile - android - (db, receivers, services...)04 programmation mobile - android - (db, receivers, services...)
04 programmation mobile - android - (db, receivers, services...)TECOS
 
Andcx formation-android-avance-creation-d-applications-complexes
Andcx formation-android-avance-creation-d-applications-complexesAndcx formation-android-avance-creation-d-applications-complexes
Andcx formation-android-avance-creation-d-applications-complexesCERTyou Formation
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Loïc Knuchel
 

Destacado (20)

Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015
 
Développement Android
Développement AndroidDéveloppement Android
Développement Android
 
Codes malveillants
Codes malveillantsCodes malveillants
Codes malveillants
 
Android 6 marshmallow
Android 6 marshmallowAndroid 6 marshmallow
Android 6 marshmallow
 
01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)
 
Traitement numérique des images - Projet Android "Virtual Pong" - Présentation
Traitement numérique des images - Projet Android "Virtual Pong" - PrésentationTraitement numérique des images - Projet Android "Virtual Pong" - Présentation
Traitement numérique des images - Projet Android "Virtual Pong" - Présentation
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chat
 
Initiation aux echecs
Initiation aux echecsInitiation aux echecs
Initiation aux echecs
 
Les virus
Les virusLes virus
Les virus
 
Mta
MtaMta
Mta
 
Algea - 04 - conclusion
Algea - 04 - conclusionAlgea - 04 - conclusion
Algea - 04 - conclusion
 
Montage video
Montage videoMontage video
Montage video
 
Angular 4 - ngfor -- Français
Angular 4  - ngfor -- FrançaisAngular 4  - ngfor -- Français
Angular 4 - ngfor -- Français
 
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...
La Veille en E-Réputation et Community Management [2/3] : Outils, méthodologi...
 
1cours virologie généralités (1)
1cours virologie généralités (1)1cours virologie généralités (1)
1cours virologie généralités (1)
 
Android Studio, premier contact
Android Studio, premier contactAndroid Studio, premier contact
Android Studio, premier contact
 
04 programmation mobile - android - (db, receivers, services...)
04 programmation mobile - android - (db, receivers, services...)04 programmation mobile - android - (db, receivers, services...)
04 programmation mobile - android - (db, receivers, services...)
 
Android à domicile
Android à domicileAndroid à domicile
Android à domicile
 
Andcx formation-android-avance-creation-d-applications-complexes
Andcx formation-android-avance-creation-d-applications-complexesAndcx formation-android-avance-creation-d-applications-complexes
Andcx formation-android-avance-creation-d-applications-complexes
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
 

Similar a Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur d'Android2EE spécialiste de la formation Android.

Développement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EEDéveloppement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EESabri Bouchlema
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Eric Bourdet
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Eric Bourdet
 
Témoignage client ProxiAD
Témoignage client ProxiADTémoignage client ProxiAD
Témoignage client ProxiADEclipseDayParis
 
At2008 Grenoble Hugonnet Sanlaville Public
At2008 Grenoble Hugonnet Sanlaville PublicAt2008 Grenoble Hugonnet Sanlaville Public
At2008 Grenoble Hugonnet Sanlaville PublicEmmanuel Hugonnet
 
Réutilisation de code entre Windows 8 et Windows Phone 8.
Réutilisation de code entre Windows 8 et Windows Phone 8.Réutilisation de code entre Windows 8 et Windows Phone 8.
Réutilisation de code entre Windows 8 et Windows Phone 8.Microsoft
 
Bluesmvc solutionlinux 2012 eric german
Bluesmvc solutionlinux 2012 eric german Bluesmvc solutionlinux 2012 eric german
Bluesmvc solutionlinux 2012 eric german eric German
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiENSET, Université Hassan II Casablanca
 
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...ENSET, Université Hassan II Casablanca
 
Comment intégrer une application ASP.NET dans Windows Azure
Comment intégrer une application ASP.NET dans Windows AzureComment intégrer une application ASP.NET dans Windows Azure
Comment intégrer une application ASP.NET dans Windows AzureMicrosoft Technet France
 
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8Microsoft
 
Design applicatif avec symfony2
Design applicatif avec symfony2Design applicatif avec symfony2
Design applicatif avec symfony2RomainKuzniak
 
ToulouseJUG - REX Flex, Spring & Agilité
ToulouseJUG - REX Flex, Spring & AgilitéToulouseJUG - REX Flex, Spring & Agilité
ToulouseJUG - REX Flex, Spring & AgilitéNicolas Deverge
 
Présentation Eranea à Open Source Now 2012
Présentation Eranea à Open Source Now 2012Présentation Eranea à Open Source Now 2012
Présentation Eranea à Open Source Now 2012Didier Durand
 

Similar a Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur d'Android2EE spécialiste de la formation Android. (20)

Développement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EEDéveloppement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EE
 
Google App Engine
Google App EngineGoogle App Engine
Google App Engine
 
Support JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVCSupport JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVC
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01
 
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
Supportdecoursejb3versioncompletemryoussfi 140317162653-phpapp01 (1)
 
Témoignage client ProxiAD
Témoignage client ProxiADTémoignage client ProxiAD
Témoignage client ProxiAD
 
Mysql
MysqlMysql
Mysql
 
At2008 Grenoble Hugonnet Sanlaville Public
At2008 Grenoble Hugonnet Sanlaville PublicAt2008 Grenoble Hugonnet Sanlaville Public
At2008 Grenoble Hugonnet Sanlaville Public
 
Support de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfiSupport de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfi
 
Réutilisation de code entre Windows 8 et Windows Phone 8.
Réutilisation de code entre Windows 8 et Windows Phone 8.Réutilisation de code entre Windows 8 et Windows Phone 8.
Réutilisation de code entre Windows 8 et Windows Phone 8.
 
Bluesmvc solutionlinux 2012 eric german
Bluesmvc solutionlinux 2012 eric german Bluesmvc solutionlinux 2012 eric german
Bluesmvc solutionlinux 2012 eric german
 
Support de cours Spring M.youssfi
Support de cours Spring  M.youssfiSupport de cours Spring  M.youssfi
Support de cours Spring M.youssfi
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
 
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
 
Comment intégrer une application ASP.NET dans Windows Azure
Comment intégrer une application ASP.NET dans Windows AzureComment intégrer une application ASP.NET dans Windows Azure
Comment intégrer une application ASP.NET dans Windows Azure
 
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8
Créer des applications métier (LOB) pour Windows 8 et Windows Phone 8
 
Design applicatif avec symfony2
Design applicatif avec symfony2Design applicatif avec symfony2
Design applicatif avec symfony2
 
Architecture .net
Architecture  .netArchitecture  .net
Architecture .net
 
ToulouseJUG - REX Flex, Spring & Agilité
ToulouseJUG - REX Flex, Spring & AgilitéToulouseJUG - REX Flex, Spring & Agilité
ToulouseJUG - REX Flex, Spring & Agilité
 
Présentation Eranea à Open Source Now 2012
Présentation Eranea à Open Source Now 2012Présentation Eranea à Open Source Now 2012
Présentation Eranea à Open Source Now 2012
 

Más de Mathias Seguy

Treatment, Architecture and Threads
Treatment, Architecture and ThreadsTreatment, Architecture and Threads
Treatment, Architecture and ThreadsMathias Seguy
 
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
 
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
 
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
 
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
 
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
 
Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mathias Seguy
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleMathias Seguy
 
ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013Mathias Seguy
 
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...Mathias Seguy
 

Más de Mathias Seguy (11)

Treatment, Architecture and Threads
Treatment, Architecture and ThreadsTreatment, Architecture and Threads
Treatment, Architecture and Threads
 
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
 
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)
 
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 :)
 
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
 
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.
 
Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification Google
 
ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013
 
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...
Eclispe daytoulouse combining the power of eclipse with android_fr_1024_768_s...
 

Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur d'Android2EE spécialiste de la formation Android.

  • 1. vous présente : Spécialiste Android Java J2EE Auteur du livre disponible sur 1
  • 2. Formateur Consultant Expert Android mathias.seguy.it@gmail.com (mail) @android2ee (twitter) Fondateur Android2EE – Formation Expertise Android Auteur d’EBooks sur la programmation Android (Android2ee.com) 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 2
  • 3. • Pourquoi de l’architecture ? • Architecture d’applications Stand Alone (Swing) • Android Application Design • Android ProTips • MutliVersionning & Resources are your best friends • Automatiser les tests ! 3
  • 4. 4
  • 5. Ex: L'activité utilise un service Rest pour mettre à jour des informations de manière cyclique. Thread I.H.M Thread de traitement Activity Handler sendMessage() REST Call message OnDestroy() OnCreate() Thread de traitement initiale Thread I.H.M sendMessage() REST Call Activity Handler fantôme fantôme Thread de traitement Activity Handler sendMessage() REST Call message 5
  • 6. 6
  • 7. Le modèle N-Tiers et ses dépendances. Chaque couche possède une interface. Chaque couche possède un cahier des charges très précis. Les dépendances entres les packages sont extrêmement importantes. Internet Façade COM COM Façade DataBase IHM Service Service Façade DAO DAO FileSystem Use or not Transverse Use 7
  • 8. Les fondations de l’application. La couche transverse est connue de tous mais ne connait personne. Objet Service Utilitaire Transverse Service des Exceptions métiers PojoA Log HttpUtil ExceptionManager PojoB Tracker DateUtil ExceptionManaged DtoA StringUtil 8
  • 9. Le cerveau de l’application. La couche service contient les services métiers. LoginSrv SimulationSrv MainStreamSrv MainStreamSrvIntf SimulationSrvIntf LoginSrvIntf LoginSrvImpl MainStreamSrvImpl SimulationSrvImpl LoginUtil MSDisplaySrv LoginCore MsUpdateSrv 9
  • 10. La mémoire de l’application. La couche DAO : Data Access Object. Elle n’expose ses services qu’au travers d’interfaces. Utiliser les factory. Expose les méthodes CRUD (Create, Read, Update, Delete) et autres méthodes spécifiques. Human SqlUtil HumanDaoFactory SqlUtil HumanDaoIntf HumanDaoHb8 HumanDaoJdbc HumanDaoFS 10
  • 11. La bouche et les oreilles de l’application. La couche COM (communication) prend en charge l’accès aux données et services déportés sur un serveur (web ou autre). On ne doit pas spécifier le type de communication mais le service rendu. ForecastCom HttpComUtil ForecastComIntf use HttpComUtilIntf ForecastComImpl HttpComUtilImpl 11
  • 12. Hiérarchie des packages de vues. La couche IHM contient l’ensemble des écrans et se scinde en plusieurs sous-packages. Une application hiérarchise ses vues, cette hiérarchie doit se retrouver dans vos packages. Cohérence 12
  • 13. Le modèle Model – (Vue Controller). Le deuxième concept fort est la séparation entre l’affichage des objets et leur gestion. La view affiche le model gère les données. Le model se charge de la gestion des objets affichés et la communication avec les services. 1 1 FamilyView FamilyModel FamilySrvIntf 0 0 use n n 1 1 HumanView HumanModel HumanSrvIntf 0 0 n n use 1 1 AdressView AdressModel AdressSrvIntf 13
  • 14. 14
  • 15. Houston, we’ve got a problem. Avec Android le problème est « Comment mettre en place ce Design en respect du cycle de vie des activités? ». Certaines application Swing ont un temps de boot de 30 secondes, et ce n’est pas possible sur Android. 15
  • 16. Les contraintes sont: Il faut que notre Design réussisse quatre challenges: •On ne doit instancier un élément qu’à la demande; •Quand un élément est instancié, il faut qu’il le reste; •On ne doit pas détruire les éléments instanciés quand l’activité est déconstruite pour être immédiatement reconstruite; •On doit pouvoir laisser les traitements se terminer (au sens use case) tout en étant capable de leur signaler que l’application est terminée... 16
  • 17. L’enfer de la fragmentation Notre Design doit être capable de : • Lancer l’application en mode Post-HoneyComb/ICS/JB ou en mode pre HoneyComb / ICS / JB, •Instancier des composants en fonction de la version du système 17
  • 18. Le Pattern Parrallel Activity étendu : Instancier l’implémentation d’un service / d'une brique applicative en fonction de la version du système. Human AServiceFactory AServiceIntf AServiceV6Impl AServiceV11Imp AServiceV13Imp 18
  • 19. 19
  • 20. Parrallel Activity Pattern and fragments : Les activités sont devenues des coquilles vides qui écoutent les Intents, imposent le cycle de vie et re-routent les évènements vers les fragments qui les composent. C’est la nouvelle philosophie générale. Votre application lancera une première activité qui aura comme unique objectif de lancer soit l’activité dans son mode pré-HoneyComb soit dans son mode post HC. Ces deux activités utiliseront les mêmes classes de type Fragment (grâce à la support-librairy). Il faut décliner chaque Intent en post et pré HC. ActivityLegacy 0 1 LauncherActivity Fragment 1 ActivityHC 0 20
  • 21. Les fragment et les support.v4.app.Fragment ne sont pas compatibles: Ils ne possèdent pas d’interface commune. Duplication du code de vos fragments (seules différences leurs imports). 0 1 ActivityLegacy FragmentLeg LauncherActivity 0 1 ActivityHC FragmentHC 21
  • 22. Les fragments (post-HC et pre-HC) partagent le même modèle. Les fragments sont purement du code dupliqué. Les modèles sont indépendants de la version du système. Chaque Fragment est associé à son modèle. Chaque activité se décline en deux types : pré et post HC. 0 1 ActivityLegacy FragmentLegacy 1 1 use LauncherActivity FragmentModel AServiceSrvIntf 1 0 1 1 ActivityHC FragmentHC 22
  • 23. Le modèle MVC Android. Le modèle MVC Android se décline en trois types : 0 1 None : Les données à afficher sont en read-only, peu de traitement au ActivityLegacy FragmentLegacy niveau des données. LauncherActivity 0 1 ActivityHC FragmentHC Simple : Chaque fragment gère ses données au moyen de son modèle. Full : L’activité et les fragments ont des données corrélées qu’il faut synchroniser au niveau des modèles. 0 1 0 1 ActivityLegacy FragmentLegacy ActivityLegacy FragmentLegacy 1 1 1 use ParentIntf 1 1 LauncherActivity 1 FragmentModel LauncherActivity FragmentModel 1 ActivityModel 1 1 0 1 1 1 1 0 1 ActivityHC FragmentHC ActivityHC FragmentHC 23
  • 24. Votre package UI doit alors ressembler à Attention à la duplication du code quelque chose comme le schéma ci-contre: Les activités/fragments Legacy, HC, ICS, JB possèdent le même modèle. Il reste les problématiques : •de la démultiplication des activités qui est plus fatigante en termes : • de code, •de maintenabilité •et la duplication de code des fragments. 24
  • 25. 25
  • 26. Base class for those who need to maintain global application state. La classe application va nous permettre de répondre aux problématiques suivantes : instancier un élément qu’à la demande; un élément est instancié doit le rester; On ne doit pas détruire les éléments instanciés ne doivent pas être détruit quand l’activité est déconstruite/reconstruite; On doit pouvoir laisser les traitements se terminer L’objet application est créé dès que l’un des composants de votre application est instanciée et est détruite quand le dernier composant est détruit. public class DesignApplication extends Application { Déclaration dans le AndroidManifest.xml HumanDaoIntf humanDao; /** * @return the humanDao */ <application public final synchronized HumanDaoIntf getHumanDao() { android:icon="@drawable/ic_launcher" if(humanDao==null) { android:label="@string/app_name" android:name=".MyApplication"> humanDao=new HumanDaoCPImpl(); } return humanDao; } } 26
  • 27. Application, où es-tu? Utilisez le pattern du singleton. public class DesignApplication extends Déclaration dans le AndroidManifest.xml Application { @Override <application public void onCreate() { android:icon="@drawable/ic_launcher" super.onCreate(); android:label="@string/app_name" android:name=".MyApplication"> //First record the Application object AppSingleton.INSTANCE.setApp(this); … } Le code pour récupérer l’Application quand vous êtes ni dans une Activity ni dans un service : public enum AppSingleton { //Retrouver l’application INSTANCE; AppSingleton.INSTANCE.getApp(); private DesignApplication application; /** * @return */ public DesignApplication getApp() { return application; Le code pour récupérer l’Application quand vous êtes dans } une Activity ou dans un service : /** * @param app */ //Retrieve the application public void setApp(Application app) { (DesignApplication )getApplication(); application=app; } } 27
  • 28. Les services métiers doivent : finir leur traitement, être instancié à la demande, persister leur instanciation, ne pas suivre le cycle de vie de l'activité mais celui de l'application. Pour résoudre ce problème vous avez deux choix : •Soit votre service métier est un service Android. •Soit ce n’est pas un service Android et il faut le faire à la main. Le second cas est complexe est n’est pas recommandé. 28
  • 29. Les services Android sont les services métiers de l'application. Net Façade COM COM Service Couche Façade DB Métier IHM Service Android Façade DAO DAO FS Use or not Transverse Use 29
  • 30. Le ServiceLoader Le service Loader a pour objectif : •de lancer les services de l'application, •de se lier à eux en mode bind (et ainsi conserver un pointeur vers eux), •de se délier à eux quand l'application s'arrête (et ainsi de les arreter). LazyLoading Pour cela, DaughterService2 1-1 •C'est un singleton (une énumération) ServiceLoader DaughterService1 •Il connait ses services via une 1-1 liste de ServiceConnection ServiceLoader •Possède une méthode d'arrêt. Caption BIND 1 LazyLoading Et il faut l'écrire à la main. WorkFlow getService N'appartient pas au SDK. MService 2 callBack Contains Extends DaughterActivity service.doSomething() 3 30
  • 31. Le serviceLoader : Mise en place du LazyLoading private void launchServiceAsync() { Activity /** * The method to be called by the activities ServiceLoader // load your service... @return the dService (could be null if not started yet) */ ServiceLoader.instance.getdService(new OnServiceCallBack() { public void getdService(OnServiceCallBack onServiceCallBack) { public void onServiceCallBack(MService service) { startDummySrv(); // insure the service is started // so just call the method you want of your service // then if the service is null add the callBack to the list of elements waiting for the service ((DummyService) service).doSomethingAsynch(getActivityId()); to be instantiated }});} if (dService == null) {// add to the callback list onDServiceCallBack.add(onServiceCallBack); /** * The service you want to expose to activities */ ServiceLoader } else {// else, service is not null, just use directly the callback private DummyService dService = null; onServiceCallBack.onServiceCallBack(dService); /** * The list of the callback of the service instantiation */ }} private List<OnServiceCallBack> onDServiceCallBack; /** * Method to start the DummyService service */ /** * The object to handle the connection of this with the service. So this will keep a pointer on private void startDummySrv() {// insure the list is not null the service not loosing it in the memory. */ ServiceLoader if (onDServiceCallBack == null) {onDServiceCallBack = new private ServiceConnection dummySrvConn = new ServiceConnection() { ArrayList<OnServiceCallBack>();} // as usual deconnexion // if the service is null, launch it using the Bind process @Override if (dService == null) { public void onServiceDisconnected(ComponentName name) {dService = null;} Intent service = new // as usual connection Intent(MAppInstance.ins.getApplication(), DummyService.class) @Override ; public void onServiceConnected(ComponentName name, IBinder service) { MAppInstance.ins.getApplication().bindService(service, dummySrv // use the IBinder Conn,Service.START_STICKY);} dService = (DummyService) ((MService.LocalBinder) service).getService(); // add it to the list of bound services (if not in yet): // notify callback the service is awake if(!boundServices.contains(dummySrvConn)) for (OnServiceCallBack callBack : onDServiceCallBack) { {boundServices.add(dummySrvConn);} callBack.onServiceCallBack(dService); } }// and clear the callback list onDServiceCallBack.clear(); onDServiceCallBack = null;}}; 31
  • 32. Persister les services : l'objet Application instancie le ServiceLoader Persitence des services public class MApplication extends Application { DaughterService2 /** * Just keep a reference on it to Persistence 1-1 avoid unusefull 1-0 destruction/recreation of services */ Caption Application ServiceLoader DaughterService1 private ServiceLoader sLoader; 1-1 @Override public void onCreate() { WorkFlow BIND ... 1 LazyLoading // keep the ref getService sLoader = Contains MService 2 ServiceLoader.instance; callBack } Extends /** * This method has to be called when DaughterActivity the application died. It kill all the service.doSomething() services So find the activity that quit 3 the application and add that method */ public void onBackPressed() { // Call the application object and release the services sLoader.unbindAndDie(); } } 32
  • 33. Communication Service-Activity 1 DaughterActivity DaughterService1 service.doSomething(String ActivityId) 4 onServiceCallBack 2 (int serviceMethodId, MActivity callBack(methodID, activityID, result); Object result) 3 1-1 Build And Launch Intent to the Activity using its ActivityId BroadCastReceiver ServiceHelper Caption WorkFlow Contains Extends 33
  • 34. Objectif pour le développeur final : peu de code. public abstract class MyActivity extends MActivity {... Activity /** Retrieving results from business services calls *******/ Activity private void launchServiceAsync() { /** The method to implement to root your service call with the method that handle // find your service...(lazy loading part) the return. It's called back via intent through MActivity. So you just need to check ServiceLoader.instance.getdService(new OnServiceCallBack() { your method id and do something with your result */ public void onServiceCallBack(MService service) { 4 protected void onServiceCallBack(int serviceMethodId, Object result) { // so just call the method you want of your service ((DummyService) service).doSomethingAsynch(getActivityId());}});} 1 switch (serviceMethodId) { case DummyService.doSomethingID: public class DummyService extends MService { // call your result method doSomethingResult(result) Service onServiceResult((ConstantData) result); 5 /** * The id of the method doSomething break; Activity * It has to be unique for your whole application and for each service'method default: of it. break;} */ } public static final int doSomethingID = 10000101; private void onServiceResult(ConstantData message) { 6 /** * A dummy method with the return sent to the calling activity // You can also display a indeterminate progress bar * * @param activityId The unique id of the calling activity */ simpleServiceCall--; public void doSomething(String activityId) { 2 if(simpleServiceCall==0) { // do your treatment prbResultSimple.setVisibility(View.GONE);} ConstantData data = new ConstantData("SomeResuls", 11021974, true); txvResultSimple.setText(message.message);} // And the important part is here // When your treatment is over, just use the serviceHelper to contact the calling Activity and to send the method return to that activity ServiceHelper.instance.callBack(doSomethingID, activityId, data); 3 } 34
  • 35. L'activité mère public abstract class MActivity extends Activity { 1) Mise en place de l'écoute transparente des Intents via une /** * @return a unique identifier of the activity to be attached to intents that have to be activité mère. calledBack by the activity */ 2) Enregistrement en tant qu'écouteur d'intents qui ont pour public String getActivityId() {// so use the canonical name it should be enough action le getActivityId return getClass().getCanonicalName();} 3) Parcing du retour dans le BroadcastReceiver et appel de protected abstract void onServiceCallBack(int serviceMethodId, Object result); la méthode onServiceCallBack private BroadcastReceiver serviceCallBackReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d("MActivity", "serviceCallBackReceiver:onReceive, called: " + intent.getAction()); // first be sure to listen for the right intent if (intent.getAction() == getActivityId()) { // retrieve the type of the result object String resType = intent.getStringExtra(ServiceHelper.SRV_MTH_RES_TYPE); // using that type, retrieve the result object // there will be a lot of case, should be the same case than the number of @Override // intent.get**Extra method protected void onResume() { if (resType.equals(ServiceHelper.Parcelable)) { super.onResume(); onServiceCallBack(intent.getIntExtra(ServiceHelper.SRV_MTH_ID, -1), registerReceiver(serviceCallBackReceiver, new IntentFilter(getActivityId()));} intent.getParcelableExtra(ServiceHelper.SRV_MTH_RES)); @Override } else if (resType.equals(ServiceHelper.String)) { protected void onPause() { // other case super.onPause(); onServiceCallBack(intent.getIntExtra(ServiceHelper.SRV_MTH_ID, -1), unregisterReceiver(serviceCallBackReceiver);} intent.getStringExtra(ServiceHelper.SRV_MTH_RES)); } }// and so on}}}; 35
  • 36. Le service mère 1) Mise en place du Binding automatique des services avec le service locator public class MService extends Service { /** The binder process ***********/ /** * The Binder */ private final Binder binder = new LocalBinder(); /** *This class aims to be a local Binder that keep and share a pointer on the instance of this */ public class LocalBinder extends Binder { // as usual public MService getService() {// return the instance of the service return MService.this;} } @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onDestroy() { super.onDestroy(); } } 36
  • 37. Les services filles 1) Déclare les identifiants de méthode du service 2) Mets en place les méthodes du services 3) Et renvoie toujours le résultat via: ServiceHelper.instance.callBack(doSomethingID, activityId, data); public class DummyService extends MService { /** * The id of the method doSomething * It has to be unique for your whole application and for each service'method of it. */ public static final int doSomethingID = 10000101; /** * A dummy method with the return sent to the calling activity * * @param activityId The unique id of the calling activity */ public void doSomething(String activityId) { // do your treatment ConstantData data = new ConstantData("SomeResuls", 11021974, true); // And the important part is here // When your treatment is over, just use the serviceHelper to contact the calling Activity // and to send the method return to that activity ServiceHelper.instance.callBack(doSomethingID, activityId, data); } 37
  • 38. Le ServiceHelper 1) Construit et envoie les Intents dans le système pour être automatiquement récupérés par les activités appelantes. public enum ServiceHelper { /** CallBack ******/ instance; /** * This method just create an Intent and launched it /** Constants ***/ * @param serviceMethodId : The method that ask for sending the result to the activity /** The constant to be used by intent to carry the service's method's * @param activityId : The activity that calls the method, the intent will be received by it id */ * @param result: The object to carry (the result object of the method) */ public static final String SRV_MTH_ID = public void callBack(int serviceMethodId, String activityId, Object result) { "com.android2ee.service.method.id"; //create the Intent /** * The constant to be used by intent to carry the service's Intent callBack = new Intent(activityId); method's result */ //add the service method id public static final String SRV_MTH_RES = callBack.putExtra(SRV_MTH_ID, serviceMethodId); "com.android2ee.service.method.result"; //your object should implements Parcelable /** * The constant to be used by intent to carry the service's //add the type of the result object (to unparse) method's result */ if (result instanceof Parcelable) { public static final String SRV_MTH_RES_TYPE = callBack.putExtra(SRV_MTH_RES, (Parcelable) result); com.android2ee.service.method.result.type"; callBack.putExtra(SRV_MTH_RES_TYPE,Parcelable); }else if( result instanceof String) { callBack.putExtra(SRV_MTH_RES, (String) result); callBack.putExtra(SRV_MTH_RES_TYPE,String); }//and so on //Then send the Intent MAppInstance.ins.get().sendBroadcast(callBack); } } 38
  • 39. ServiceHelper et ServiceLoader full pattern DaughterService2 Persistence 1-1 Caption 1-0 Application ServiceLoader DaughterService1 1-1 WorkFlow BIND 1 Contains LazyLoading getService MService 2 Extends callBack Communication DaughterActivity Service-Activity 6 service.doSomething() onServiceCallBack 3 4 (int serviceMethodId, MActivity callBack(methodID, activityID, result); Object result) 5 1-1 Build And Launch Intent to the Activity using its ActivityId BroadCastReceiver ServiceHelper 39
  • 40. Le projet MythicServiceHelper imlplémente ce pattern (version alpha draft) Tout le code est disponible : https://github.com/MathiasSeguy-Android2EE/MythicServiceHelper 40
  • 41. Les services métiers sont des services Android. Application Service Net Façade Métier COM COM Android Couche IHM Façade Service ServiceLoader DB MActivity ServiceHelper Façade start DAO MService DAO FS Use or not Transverse Use Préserver les interfaces Il est important de pouvoir changer la manière dont fonctionne un service sans avoir à modifier le reste de l‘application. Il doit pouvoir conserver son interface tout en changeant son implémentation sans pour autant impacter le reste de l’application. 41
  • 42. La couche BroadCast est une couche à part entière BroadCast Receiver Net Façade COM COM Service DB Couche Façade Métier IHM Service Android start Façade DAO DAO FS Use or not Transverse Use 42
  • 43. Où se trouve le ContentProvider ? La couche DAO pose le problème de « où mettre les ContentProvider ? ». Pour rappel: “You don't need to develop your own provider if you don't intend to share your data with other applications. However, you do need your own provider to provide custom search suggestions in your own application. You also need your own provider if you want to copy and paste complex data or files from your application to other applications.” dixit developer.android.com les ContentProviders sont vos DAO publiques Ainsi vos DAO contiennent bien vos ContentProvider et le Design est celui-ci : Cela ne veut pas dire que toutes vos DAO doivent posséder un ContentProvider, mais que si elles en contiennent un elles le mettent à la Human même hauteur que son interface. En effet, il n’y a qu’une implémentation pour un ContentProvider. HumanContentProvider HumanDBOpenHelper HumanDaoIntf HumanDaoSQLite Se posera à vous la question de la redondance des méthodes. Pour cela vous pouvez re-router les méthodes de votre ContentProvider vers votre HumanDaoOrlite HumanDaoFactory interface de DAO, ce qui est le plus propre. HumanDaoFS 43
  • 44. Pas de changement avec l'architecture n-tiers usuelle d'applications stand-alones. NDK. 44
  • 45. J’attire votre attention sur la nécessité de mettre en place un gestionnaire d’exception qui vous permettent de les logger/persister en base/afficher à l’utilisateur. Service des Exceptions ExceptionManager ExceptionManaged 45
  • 46. BroadCast Receiver Net Application Façade COM COM Couche Service Métier Android IHM ServiceLoader DB Façade Service MActivity ServiceHelper start Façade DAO MService DAO FS Use or not Transverse Use 46
  • 47. La solution au problème des Threads de traitements. Thread I.H.M Thread de traitement Service OnDestroy() sendMessage() REST Call OnCreate() Handler BIND message Activity 47
  • 48. 48
  • 49. From Google I/O And Devoxx Ce chapitre est un extrait des « meilleurs » proTips donnés par les équipes Google lors des GoogleI/O, notamment : •Android ProTips, Reto Meier, Google I/O 2011 •Making Good Apps Great , Reto Meier, Google I/O 2012 •Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010 Merci à eux pour ces présentations. 49
  • 50. Use ViewStub La ViewStub permet le lazy loading de layouts. <ViewStub android:id="@+id/stub_import" android:inflatedId="@+id/panel_import" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" /> id/panel_import findViewById(R.id.stub_import).setVisibility(View.VISIBLE); // or View importPanel = ((ViewStub) id/stub_import findViewById(R.id.stub_import)).inflate(); From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010 50
  • 51. Use merge et include Without merge With merge Le merge permet d’inclure les layouts les uns dans les autres sans redondance. Cela permet aussi la décomposition et la réutilisation des layout. <!-- The merge tag must be the root tag --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Content --> </merge> <!– The include tag is the one to use--> <LinearLayout …> <include layout="@layout/subLayout" /> <LinearLayout> .. </LinearLayout> </LinearLayout> From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010 51
  • 52. ListView and ArrayAdpater : Use ViewHolder and convertView public View getView(int position, View convertView, ViewGroup parent) { static class ViewHolder { ViewHolder holder; TextView text; if (convertView == null) { ImageView icon; convertView = mInflater.inflate(R.layout.list_item_icon_text, parent, false); } holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); holder.icon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.text.setText(DATA[position]); holder.icon.setImageBitmap((position & 1) ==? mIcon1 : mIcon2); return convertView; } From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010 52
  • 53. Know your Network and Battery context <receiver android:name="DeviceStateReceiever" > <action android:name="android.intent.action.ACTION_DOCK_EVENT" /> <action android:name="android.intent.action.ACTION_BATTERY_LOW" /> <action android:name="android.intent.action.ACTION_POWER_CONNECTED" /> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.net.wifi.STATE_CHANGE" /> </receiver> ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork.isConnectedOrConnecting(); boolean isMobile = activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE; Android ProTips, Reto Meier, Google I/O 2011 53
  • 54. KeyBoard and EditText : Customize KeyBoard and set Action Quand vous définissez un champ de type EditText vous devez définir : • Son type de clavier • L’action IME • (et le Hint) <EditText EditText.OnEditorActionListener myActionListener = new android:id="@+id/editEmailInput" EditText.OnEditorActionListener() { android:layout_width="match_parent" @Override android:layout_height="wrap_content" public boolean onEditorAction(EditText v, int actionId, KeyEvent event) { android:hint="@string/compose_email_hint" if (actionId == EditorInfo.IME_ACTION_DONE) { android:imeOptions="actionSend|flagNoEnterAction" // do here your stuff f android:inputType="textShortMessage| return true; textAutoCorrect| } textCapSentences" /> return false; } }; Android ProTips, Reto Meier, Google I/O 2011 54
  • 55. Always be asynchronous Rendez tout asynchrone en utilisant: •le ServiceHelper; •les Handler, Asynctask; •IntentService (le système des Intents quoi); •AsyncQueryHandler (le GetContentResolver en un sens); •Loader (abstractClass) and CursorLoader (HoneyComb only). Android ProTips, Reto Meier, Google I/O 2011 55
  • 56. Use the big cookies strategy when possible Préférez transférer un gros paquet de données au travers d’internet quand c’est possible plutôt que plein de petits paquets. int prefetchCacheSize = DEFAULT_PREFETCH_CACHE; switch (activeNetwork.getType()) { case ConnectivityManager.TYPE_WIFI: prefetchCacheSize = MAX_PREFETCH_CACHE; break; case ConnectivityManager.TYPE_MOBILE): { switch (telephonyManager.getNetworkType()) { case TelephonyManager.NETWORK_TYPE_LTE: case TelephonyManager.NETWORK_TYPE_HSPAP: prefetchCacheSize *= 4; break; case TelephonyManager.NETWORK_TYPE_EDGE: case TelephonyManager.NETWORK_TYPE_GPRS: prefetchCacheSize /= 2; break; default: break; } break; } default: break; } Making Good Apps Great, Reto Meier, Google I/O 2012 56
  • 57. 57
  • 58. From Google I/O 2012 Ce chapitre est un extrait de la conférence des Google I/O 2012 : •Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 Qui est exceptionnel sur la lutte contre la fragmentation, un très grand moment, merci à eux. 58
  • 59. Be Lazy Utiliser une classe abstraite qui sera instanciée par une factory et renverra l’implémentation correspondant à le version du système. Activity public abstract class VersionedLoremIpsum { VersionedLoremIpsum li; public abstract String doLorem(); li=VLIFactory.get() public abstract int doIpsum(); } public class EclairLoremIpsum public class FroyoLoremIpsum VLIFactory extends VersionedLoremIpsum { extends EclairLoremIpsum { public static VersionedLoremIpsum get( public String doLorem() { public String doLorem() { int sdk = Build.VERSION.SDK_INT; // do lorem, Eclair-style String l = super.doLorem(); if (sdk <= Build.VERSION_CODES.ECLAIR) { } // additional processing li = new EclairLoremIpsum(); public abstract int doIpsum() { return l; } else if (sdk <= // deliver ipsum, a là Eclair } Build.VERSION_CODES.FROYO) { } public abstract int doIpsum() { li = new FroyoLoremIpsum(); } ... } else { li = new GingerbreadLoremIpsum(); } ) Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 59
  • 60. Resources are your best friend, use them. Utilisez des booléens pour savoir quelle est la version du système. Ils s’utilisent dans le code et dans le Manifest.xml. Resvalues-v14bools.xml Resvaluesbools.xml <?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?> <resources> <resources> <bool name="postICS">true</bool> <bool name="postICS">false</bool> <bool name="preICS">false</bool> <bool name="preICS">true</bool> </resources> </resources> SomeWhere in java Manifest Resources res = getResources(); <receiver android:name="MyPreICSAppWidget" boolean postICS = android:enabled="@bool/preICS"> res.getBoolean(R.bool.postICS); ... if (postICS) { </receiver> // do something cool and cutting-edge <receiver android:name="MyPostICSAppWidget" } else { android:enabled="@bool/postICS"> // do something old-school but elegant! ... } </receiver> Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 60
  • 61. Hériter du thème de la version. Restez cohérent avec le thème du SDK de l’appareil cible, conservez une application cohérente avec l’appareil. resvalues-v11theme.xml MyTheme <style name="MyAppThemeBase" parent="@android:style/Theme.Holo" /> <style name="MyButtonStyle" parent="@android:style/Widget.Holo.Button"> MyBaseTheme resvaluestheme.xml <style name="MyAppThemeBase" parent="@android:style/Theme" /> <style name="MyAppTheme" parent="MyAppThemeBase"> <style name="MyButtonStyle" parent="@android:style/Widget.Button"> Theme Theme.Holo Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 61
  • 62. Utiliser les Fragments et l’ActionBar sur toutes vos versions. Ayez une application identique quelque soit la version du système et utilisez le même fichier de layout. public class BaseActivityHC extends Activity{...} public class BaseActivityLegacy extends android.support.v4.app.FragmentActivity {...} android.support.v4.app.ActionBarActivity public class SpeakerDetailFragmentHC extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.speaker_detail, container, false); return view; } public class SpeakerDetailFragment extends android.support.v4.app.Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.speaker_detail, container, false); return view; } Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 62
  • 63. Utiliser les notifications PreJB, PostJB. Utilisez les notifications sur toutes les versions avec le NotificationCompat.Builder. Les notifications sont une des grandes évolutions de JellyBean. Le NotificationBuilder a été délivré pour HC, mais si vous voulez profitez des évolutions sur toutes les versions, il faut utiliser le NotificationCompat.Builder. if version >= JellyBean use Notification.Builder else use NotificationCompat.Builder private void pushInboxNotifications() { Notification notification = new Notification.Builder(this) .setContentTitle("10 New emails for me") .setContentText("subject") .setSmallIcon(android.R.drawable.ic_menu_agenda) .setStyle(Notification.InboxStyle) .addLine("Line 1, i can add more if i want") .addAction(R.drawable.icon,R.string.notification_message,new PendingIntent(....)) .setSound(aSound) .build(); NotificationManager notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notification); } Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 63
  • 64. L’ordre des boutons a changé depuis ICS. Avant ICS le bouton OK est à gauche, le bouton non ou cancel à droite. Après ICS le bouton OK est à droite, le bouton non ou cancel à gauche. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 64
  • 65. Min, max et target SDK importe. Définissez toujours votre targetSdk comme le plus haut possible pour profiter des nouveautés du système. En d’autres termes, toujours tester votre application avec la plus haute version du système et si elle fonctionne, définissez votre targetSDK comme étant celui-là. <uses-sdk android:maxSdkVersion="16" android:minSdkVersion="8" android:targetSdkVersion="16" /> ps: le maxSDK s'utilise uniquement pour proposer différents apk en fonction de la version du système au niveau de GooglePlay. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 65
  • 66. 66
  • 67. Ne pas oublier le projet de Tests. L’architecte a à charge la conception de l’application mais aussi la conception de l’application de test. Ne l'oubliez pas. Pour aller plus loin, vous pouvez acheter : Android An Entreprise Edition Vision 67
  • 68. Ces outils sont : • Le SDK de Test fourni par Android, • JUnit 3 (intégré au SDK d’Android), • Maven pour construire l’application, • Jenkins pour lancer Maven et passer les tests sur différents émulateurs 68
  • 69. Communauté Google+ Android projects on Github Github open source projects https://plus.google.com/u/0/communities/100609058582053363304 69
  • 70. Cette conférence utilise les références suivantes : Les EBooks et tutoriels d’Android2ee : http://www.android2ee.com Les sites de référence Android: • http://developer.android.com/index.html • http://android-developers.blogspot.fr/ • http://www.google.com/events/io/2011/sessions.html • https://developers.google.com/events/io/sessions Sur Android2ee, vous trouverez les tutoriels libres suivants pour approfondir les notions présentées: • Les capteurs • Les thread de traitement (Handler et fuite mémoire) • Les AppWidgets • Construction dynamique d’IHM • Service REST • Lecteur de flux RSS • Le fichier POM pour mavéniser vos projets • Comment préparer ses livraisons sur GooglePlay Sur developpez.com vous trouverez les articles du conférencier : • Déployer son application Android et obtenir sa clef MapView. • Construire dynamiquement ses IHM Android • Les capteurs Android • Thread, Handler, AsyncTask et fuites mémoires • Investir l'écran d'accueil Android avec les AppWidgets • Android, Livrer son projet sur GooglePlay 70
  • 71. Merci pour votre attention. android2ee.com. #android2ee Jcertif Mobile sur GooglePlay MySensors, MyLight et MyTorch mathias.seguy@android2ee.com disponible sur GooglePlay 71