Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
vous présente :




Spécialiste Android Java J2EE

        Auteur du livre

disponible sur




                           ...
Formateur Consultant Expert Android
                                           mathias.seguy.it@gmail.com (mail)
         ...
• Pourquoi de l’architecture ?

• Architecture d’applications Stand Alone (Swing)

• Android Application Design

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



                      T...
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...
Les fondations de l’application.

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




 Objet      Servic...
Le cerveau de l’application.

La couche service contient les services métiers.




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

Ell...
La bouche et les oreilles de l’application.

La couche COM (communication) prend en charge l’accès aux données et services...
Hiérarchie des packages de vues.


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

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

Le deuxième concept fort est la séparation entre l’affichage des objets et leur gesti...
14
Houston, we’ve got a problem.



Avec Android le problème est « Comment mettre en place ce Design en respect du cycle de v...
Les contraintes sont:

Il faut que notre Design réussisse quatre challenges:

•On ne doit instancier un élément qu’à la de...
L’enfer de la fragmentation



                                   Notre Design doit être capable de :

• Lancer l’applicat...
Le Pattern Parrallel Activity étendu :



Instancier l’implémentation d’un service / d'une brique applicative en fonction ...
19
Parrallel Activity Pattern and fragments :

Les activités sont devenues des coquilles vides qui écoutent les Intents, impo...
Les fragment et les support.v4.app.Fragment ne sont pas compatibles:

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

Les fragments sont purement du code dupliqué. Les modèles son...
Le modèle MVC Android.

Le modèle MVC Android se décline en trois types :
                                                ...
Votre package UI doit alors ressembler à
                         Attention à la duplication du code
                     ...
25
Base class for those who need to maintain global application state.
La classe application va nous permettre de répondre au...
Application, où es-tu?
                                   Utilisez le pattern du singleton.



public class DesignApplicat...
Les services métiers doivent :




                                                              finir leur traitement,
  ...
Les services Android sont les services métiers de l'application.




                                                     ...
Le ServiceLoader
Le service Loader a pour objectif :
•de lancer les services de l'application,
•de se lier à eux en mode b...
Le serviceLoader : Mise en place du LazyLoading
private void launchServiceAsync() {                       Activity        ...
Persister les services : l'objet Application instancie le ServiceLoader

                                   Persitence des...
Communication
                                                                                                            ...
Objectif pour le développeur final : peu de code.
public abstract class MyActivity extends MActivity {...                 ...
L'activité mère
public abstract class MActivity extends Activity {                                            1) Mise en p...
Le service mère
       1) Mise en place du Binding automatique des services avec le
          service locator



public cl...
Les services filles
1) Déclare les identifiants de méthode du service
2) Mets en place les méthodes du services
3) Et renv...
Le ServiceHelper
1) Construit et envoie les Intents dans le système pour être automatiquement récupérés par les activités ...
ServiceHelper et ServiceLoader full pattern
                                                                              ...
Le projet MythicServiceHelper imlplémente ce pattern (version alpha draft)
                      Tout le code est disponib...
Les services métiers sont des services Android.



                           Application                                 ...
La couche BroadCast est une couche à part entière


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

  “...
Pas de changement avec l'architecture n-tiers usuelle d'applications stand-alones.
                                     ND...
J’attire votre attention sur la nécessité de mettre en place un gestionnaire d’exception qui vous permettent de les logger...
BroadCast
                          Receiver                                                              Net
            ...
La solution au problème des Threads de traitements.




                       Thread I.H.M                               ...
48
From Google I/O And Devoxx

Ce chapitre est un extrait des « meilleurs » proTips donnés par les équipes Google lors des Go...
Use ViewStub

  La ViewStub permet le lazy loading de layouts.
   <ViewStub
   android:id="@+id/stub_import"
   android:in...
Use merge et include
                                                                                            Without m...
ListView and ArrayAdpater : Use ViewHolder and convertView




   public View getView(int position, View convertView, View...
Know your Network and Battery context


                                      <receiver android:name="DeviceStateReceiever...
KeyBoard and EditText : Customize KeyBoard and set Action
  Quand vous définissez un champ de type EditText vous devez déf...
Always be asynchronous
                                           Rendez tout asynchrone en utilisant:
                   ...
Use the big cookies strategy when possible

  Préférez transférer un gros paquet de données au travers d’internet quand c’...
57
From Google I/O 2012

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


•Multiversioning Android, Bruno ...
Be Lazy

  Utiliser une classe abstraite qui sera instanciée par une factory et renverra l’implémentation correspondant à ...
Resources are your best friend, use them.

  Utilisez des booléens pour savoir quelle est la version du système. Ils s’uti...
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...
Utiliser les Fragments et l’ActionBar sur toutes vos versions.

  Ayez une application identique quelque soit la version d...
Utiliser les notifications PreJB, PostJB.

  Utilisez les notifications sur toutes les versions avec le NotificationCompat...
L’ordre des boutons a changé depuis ICS.

  Avant ICS le bouton OK est à gauche, le bouton non ou cancel à droite.
  Après...
Min, max et target SDK importe.

  Définissez toujours votre targetSdk comme le plus haut possible pour profiter des nouve...
66
Ne pas oublier le projet de Tests.

L’architecte a à charge la conception de l’application mais aussi la conception de l’a...
Ces outils sont :


    • Le SDK de Test fourni par Android,


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


    • Maven pou...
Communauté Google+ Android projects on Github
                     Github open source projects
https://plus.google.com/u/0...
Cette conférence utilise les références suivantes :
Les EBooks et tutoriels d’Android2ee : http://www.android2ee.com
Les s...
Merci pour votre attention.




                                       android2ee.com.
                                   ...
Upcoming SlideShare
Loading in …5
×
Upcoming SlideShare
Meet up paris 13 of jun 2017
Next

6

Share

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

La conférence « Architecture Android » de Mathias Seguy (Android2EE).
Si l’architecture d’applications Android vous questionne, vous intéresse, vous mystifie cette conférence est faîte pour vous.
Elle s’attachera à décrire les design patterns, contraintes et bonnes pratiques Android. Cela nous permettra de concevoir une architecture propre aux applications Android.
La conférence se conclura en donner les pro-tips Android provenant des GoogleIO et Devoxx qu’il faut connaitre pour concevoir des applications pertinentes sous Android.

Cette conférence a eu lieu le mardi 19 Mars 2013, à 19h.
Si vous êtes un JUG ou un AUG et que cette conférence vous interesse, n'hésitez pas à me contacter.

Si vous souhaitez apprendre la technologie Android, contacter moi: mathias.seguy@android2ee.com, je suis formateur Android et les formations Android que je dispense sont exceptionnelles.

Speaker:Mathias est le fondateur de la société Android2ee spécialisée dans la technologie Android.
Il est :
• formateur Android,
• expert logiciel Android,
• speaker Android sur de grandes conférences Java : Devoxx France, Eclipse Day Toulouse, JCertif Africa, Toulouse JUG, CocoAhead,…
• Rédacteur Android sur Developpez.com ;
• Programmateur Android : MyLight, MyTorch, MySensors, JCertifMobile disponibles sur GooglePlay ;
• Docteur en Mathématiques Fondamentales et Ingénieur de l’ENSEEIHT ;
• Expert technique de l’agence nationale de la recherche française ;
Il présentera au cours de cette conférence sa vision sur la mise en place d’une architecture d’une application Android pertinente et partagera les meilleurs pro-tips (astuces de pro) de sa connaissance. A ne pas manquez.

Mathias Séguy
mathias.seguy@android2ee.com
Fondateur Android2EE
Formation – Expertise – Consulting Android.
Ebooks pour apprendre la programmation sous Android.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

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

  1. 1. vous présente : Spécialiste Android Java J2EE Auteur du livre disponible sur 1
  2. 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. 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. 4
  5. 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. 6
  7. 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. 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. 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. 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. 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. 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. 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. 14
  15. 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. 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. 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. 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. 19
  20. 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. 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. 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. 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. 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. 25
  26. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 40. Le projet MythicServiceHelper imlplémente ce pattern (version alpha draft) Tout le code est disponible : https://github.com/MathiasSeguy-Android2EE/MythicServiceHelper 40
  41. 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. 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. 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. 44. Pas de changement avec l'architecture n-tiers usuelle d'applications stand-alones. NDK. 44
  45. 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. 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. 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. 48
  49. 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. 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. 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. 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. 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. 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. 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. 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. 57
  58. 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. 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. 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. 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. 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. 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. 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. 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. 66
  67. 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. 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. 69. Communauté Google+ Android projects on Github Github open source projects https://plus.google.com/u/0/communities/100609058582053363304 69
  70. 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. 71. Merci pour votre attention. android2ee.com. #android2ee Jcertif Mobile sur GooglePlay MySensors, MyLight et MyTorch mathias.seguy@android2ee.com disponible sur GooglePlay 71
  • amaniadli

    Mar. 20, 2019
  • bahmedabdelamjid

    Mar. 5, 2015
  • Android2EE

    Sep. 29, 2014
  • ovesmi

    May. 30, 2014
  • zeineb26

    Apr. 11, 2014
  • LinaAga

    Jul. 19, 2013

La conférence « Architecture Android » de Mathias Seguy (Android2EE). Si l’architecture d’applications Android vous questionne, vous intéresse, vous mystifie cette conférence est faîte pour vous. Elle s’attachera à décrire les design patterns, contraintes et bonnes pratiques Android. Cela nous permettra de concevoir une architecture propre aux applications Android. La conférence se conclura en donner les pro-tips Android provenant des GoogleIO et Devoxx qu’il faut connaitre pour concevoir des applications pertinentes sous Android. Cette conférence a eu lieu le mardi 19 Mars 2013, à 19h. Si vous êtes un JUG ou un AUG et que cette conférence vous interesse, n'hésitez pas à me contacter. Si vous souhaitez apprendre la technologie Android, contacter moi: mathias.seguy@android2ee.com, je suis formateur Android et les formations Android que je dispense sont exceptionnelles. Speaker:Mathias est le fondateur de la société Android2ee spécialisée dans la technologie Android. Il est : • formateur Android, • expert logiciel Android, • speaker Android sur de grandes conférences Java : Devoxx France, Eclipse Day Toulouse, JCertif Africa, Toulouse JUG, CocoAhead,… • Rédacteur Android sur Developpez.com ; • Programmateur Android : MyLight, MyTorch, MySensors, JCertifMobile disponibles sur GooglePlay ; • Docteur en Mathématiques Fondamentales et Ingénieur de l’ENSEEIHT ; • Expert technique de l’agence nationale de la recherche française ; Il présentera au cours de cette conférence sa vision sur la mise en place d’une architecture d’une application Android pertinente et partagera les meilleurs pro-tips (astuces de pro) de sa connaissance. A ne pas manquez. Mathias Séguy mathias.seguy@android2ee.com Fondateur Android2EE Formation – Expertise – Consulting Android. Ebooks pour apprendre la programmation sous Android.

Views

Total views

5,685

On Slideshare

0

From embeds

0

Number of embeds

271

Actions

Downloads

9

Shares

0

Comments

0

Likes

6

×