Category Archives: Développement

How to fix the “NoClassDefFoundError” with ADT 17

So I updated my SDK and ADT to version 17 and once again I got a big problem :)

Every project I have which use JAR libraries could still be built without problems but as soon as they start on the phone, they crashed with the following error :

03-21 19:20:56.455: E/AndroidRuntime(24471): FATAL EXCEPTION: main
03-21 19:20:56.455: E/AndroidRuntime(24471): java.lang.NoClassDefFoundError: org.acra.ACRA
03-21 19:20:56.455: E/AndroidRuntime(24471): at com.foxykeep.myproject.HomeActivity.onCreate(MyProjectApplication.java:127)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3925)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.app.ActivityThread.access$1300(ActivityThread.java:122)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1184)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.os.Handler.dispatchMessage(Handler.java:99)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.os.Looper.loop(Looper.java:137)
03-21 19:20:56.455: E/AndroidRuntime(24471): at android.app.ActivityThread.main(ActivityThread.java:4340)
03-21 19:20:56.455: E/AndroidRuntime(24471): at java.lang.reflect.Method.invokeNative(Native Method)
03-21 19:20:56.455: E/AndroidRuntime(24471): at java.lang.reflect.Method.invoke(Method.java:511)
03-21 19:20:56.455: E/AndroidRuntime(24471): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-21 19:20:56.455: E/AndroidRuntime(24471): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-21 19:20:56.455: E/AndroidRuntime(24471): at dalvik.system.NativeStart.main(Native Method)

I asked Xavier Ducrohet and Tor Norbye (both working on the ADT plugin) on Google+ about the error and they linked to this page which explains how to solve the problem but is not ultra clear (at least for me).

So here is the same solution but explained with screenshots so we can see more easily what changed  :

From left to right, we have :

  • My project with ADT 16 (the small graphic changes are due to the fact the left image is from Eclipse Windows while the 2 on the right are from Eclipse Mac)
  • My project with ADT 17 before the fix
  • My project with ADT 17 after the fix
We can see :
  • In blue, the changes due to the patch (more info on this at the end of this post)
  • In red, the changes for the fix

What I did to fix the bug was :

  • Remove the libraries from the standard Java build path :
    • Right click on the project name > Properties > Java Build Path > tab Libraries > remove everything except the “Android X.X” (2.3.3 in my case) and the “Android Dependencies”
  • Rename the libraries folder from “lib” to “libs”
    • By doing that, all the libraries in the folder “libs” are found by the Android plugin and are added to the “Android Dependencies” item of the project
  • Clean the project (not exactly needed)
  • You are good to go !

This problem is due to the fact that libraries are not managed the same way with the new ADT build.
Instead of having 2 different managements of libraries (one for Android Library Projects, one for the standard jars), now both are merged into the Android Dependencies item.

Other info, the annotations.jar file is for the new lint Java annotations (more info here : http://tools.android.com/recent/ignoringlintwarnings)
Besides this small problem, the ADT version 17 looks really good and I love the new things added to the lint checks !!

[Update]

The DroidUX Team found another solution to fix the problem. I didn’t test it personally but it don’t see why it shouldn’t work : 

Hi,

Just to add to the solution:

If you have references to jars that are not in the ‘libs’ folder, for example if you use ‘classpath variable’, you can resolve the NoClassDefFoundError issue with the new ADT 17 by exporting the references.

To export the references: simply go to “Properties > Java Build Path > Order and Export”, and check all the references you want exported.

Cheers,

DroidUX Team

[/Update]

How to fix the “Conversion to Dalvik format failed with error 1″ with ADT 14

Today I updated my SDK and ADT to the 14 version and I had a big problem !!

Every project I had which used Android Library Project couldn’t be launched on a terminal and crashed during the APK generation with the following error :

UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/foxykeep/datadroid/config/LogConfig;
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processClass(Main.java:486)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.access$400(Main.java:67)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processOne(Main.java:418)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.run(Main.java:206)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at java.lang.reflect.Method.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.DexWrapper.run(DexWrapper.java:179)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.BuildHelper.executeDx(BuildHelper.java:729)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.build(PostCompilerBuilder.java:602)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:629)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:172)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:282)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:363)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project$1.run(Project.java:545)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project.internalBuild(Project.java:524)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project.build(Project.java:123)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.project.ProjectHelper.build(ProjectHelper.java:869)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate.launch(LaunchConfigDelegate.java:146)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:853)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:702)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:924)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.ui.DebugUIPlugin$8.run(DebugUIPlugin.java:1128)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
[2011-10-19 15:19:18 - MyProject] Dx
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lgreendroid/app/ActionBarActivity;
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processClass(Main.java:486)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.access$400(Main.java:67)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processOne(Main.java:418)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.dx.command.dexer.Main.run(Main.java:206)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at java.lang.reflect.Method.invoke(Unknown Source)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.DexWrapper.run(DexWrapper.java:179)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.BuildHelper.executeDx(BuildHelper.java:729)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.build(PostCompilerBuilder.java:602)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:629)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:172)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:282)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:363)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project$1.run(Project.java:545)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project.internalBuild(Project.java:524)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.resources.Project.build(Project.java:123)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.project.ProjectHelper.build(ProjectHelper.java:869)
[2011-10-19 15:19:18 - MyProject] Dx 	at com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate.launch(LaunchConfigDelegate.java:146)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:853)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:702)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:924)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.debug.internal.ui.DebugUIPlugin$8.run(DebugUIPlugin.java:1128)
[2011-10-19 15:19:18 - MyProject] Dx 	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
[2011-10-19 15:19:23 - MyProject] Dx warning: Ignoring InnerClasses attribute for an anonymous inner class
(org.ksoap2.transport.KeepAliveHttpsTransportSE$1) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced by a
compiler that did not target the modern .class file format. The recommended
solution is to recompile the class from source, using an up-to-date compiler
and without specifying any "-target" type options. The consequence of ignoring
this warning is that reflective operations on this class will incorrectly
indicate that it is *not* an inner class.
[2011-10-19 15:19:23 - MyProject] Dx 2 errors; aborting
[2011-10-19 15:19:23 - MyProject] Conversion to Dalvik format failed with error 1

After searching the web and finding this existing bug in the Android bugtracker, I found the reason of this crash . Below you can see my project hierarchy before and after the update from ADT 12 to ADT 14 :

There is only 3 visible differences : “Library Projects” and a “bin” folder and the “default.properties” has been rename to “project.properties”.

The problem here is that the Library Projects elements contains for each Android Library Projects a jar file with the source code. At the same time we still have the GreenDroid_src and DataDroid_src elements which also contains the source code of the libraries. So we have duplicated code in our projects as mentioned in the error.

I think the update should have removed the useless X_src elements but it’s not the case. So we will have to do it manually :

  1. For each X_src element,right click on it and then Build Path > Remove from build path.
  2. A popup will open. Make sure that “Also unlink the folder from the project” is checked and then accept it.
Your project should changed from the left image to the right one :

Now you can launch your project and it should work !

Human Interface Guidelines pour Android

Un des points forts d’iPhone reste la cohérence des applications d’un point de vue ergonomique et graphique, principalement grâce à la présence des Human Interface Guidelines d’Apple qui décrivent de façon précise comment architecturer d’un point de vue UI (interface utilisateur) et UX (expérience utilisateur) une application.

Du côté d’Android, on a la chance d’avoir la liberté de faire son application comme on veut, mais c’est aussi un défaut … En effet à avoir trop de libertés, cela part un peu dans tous les sens ce qui est dommage. Le site officiel Android Developers présente un certain nombre d’informations sur les bonnes pratiques d’UI et d’UX mais ces informations ne sont pas aussi faciles à trouver qu’il le faudrait et pas totalement complètes.

Les équipes de Mutual Mobile viennent donc de sortir leurs Android Design Guidelines (en PDF) qui ne sont pas exhaustives mais qui sont déjà un très bon début. Voila leur présentation par Mutual Mobile :

Android is crushingly programmer heavy. In my opinion, they have not given enough consideration to asset creation or creative direction. With apple, the moment you start designing an app, you know how they want you to build it. Their design plans are so complete that you can immediately access it. I often dream that my house is an iPhone app; it has become comfortable. With Android, there is a false sense of freedom to do whatever you want. Unfortunately, when you start taking all the various screen sizes and resolutions into account, it doesn’t realistically pan out that way.

As a disclaimer, I am a designer, and while my knowledge of programming has increased a fraction while creating a document, it should be known that Android makes it difficult for anyone who is not a programming to decipher their rules. So with that in mind, understand that while my research has been abundant, this document should be considered a designer’s translation of Android and therefore subject to error.

While it certainly is not my place to set a standard for Google, in this document I intend to at least create a guideline for us to follow.

Après les avoir lu, je trouve qu’elles sont un must-read pour tout développeur, designer ou ergonome voulant travailler sur la plateforme Android.

 

En passant un site très intéressant qui présente les différents patterns utilisables dans les applications Android : http://www.androidpatterns.com/

 

Preview d’Android 3.0 (infos et SDK)

Après avoir vu des vidéos présentant l’interface durant le CES, Android vient de lâcher une nouvelle bombe en présentant une preview de la version 3.0, Honeycomb.

Au programme, des informations sur les nouvelles fonctionnalités/possibilités de cette version ainsi qu’un SDK non final.

Nouvelles fonctionnalités

Refonte de l’UI

On l’avait déjà vu dans la vidéo de présentation, mais une refonte de l’UI a été effectuée afin de fournir une expérience utilisateur la plus nickel possible sur tablettes. A l’heure actuelle, on a toujours aucune information sur le fait que cette version d’Android est uniquement destinée aux tablettes ou qu’on retrouvera une refonte semblable côté smartphones

Ajout des Fragments

Cette version ajoute un nouveau élément dans la logique de création d’une application : le Fragment. Il sera possible de découper une Activity en Fragments. Un Fragment pourra être ajouté, enlevé, remplacé ou animé au sein d’une Activity de façon dynamique ce qui permettra d’avoir des possibilités encore plus larges au niveau intéraction utilisateur. Un Fragment sera modulaire et pourra donc être utilisé entre plusieurs Activities. Cela permettra également de faire des interfaces gérant différemment ces fragments entre une tablette et un smartphone.

Refonte du design des widgets

Cette version apporte également un nouveau jeu de widgets qui permettront de montrer différemment le contenu disponible dans un widget. Par exemple :

  • Une pile 3D de Views (avec ajout de la gestion de scroll/fling sur le widget)
  • Une boite de recherche
  • Un picker de date/heure
  • Un picker de chiffres (qui a l’air d’être une tuerie d’apres Roman Nurik)
  • Un calendrier
  • Un menu s’ouvrant en popup

Action Bar persistante et meilleure gestion de la multisélection

Chaque application pourra désormais avoir une Action Bar persistante lui permettant d’afficher des informations et par exemple de changer d’état lors d’une multisélection.

Graphismes 2D et 3D haute performance

Un des points qui manquaient à Android était de pouvoir proposer une interface ayant des transitions sympas entre les écrans (et cela de manière facile d’un point de vue développement). C’est maintenant chose faite avec une nouvelle version du framework d’animations qui va permettre d’ajouter facilement des fondus ou toute autre sorte d’animation

Une autre grande nouvelle est l’ajout d’une accélération matérielle sur les graphismes 2D. Cela va permettre d’atteindre des performances encore jamais atteintes lors de l’utilisation de classes telles que Canvas, Paint, Xfermode, ColorFilter, Shader, ou Camera. De plus il sera possible de choisir le niveau d’accélération de son application, soit globalement soit pour une action spécifique.

Enfin alors qu’il avait fait son apparition avec le Nexus One et son fond d’écran animé, il va enfin être possible de développer en utilisant le moteur de rendu 3D Renderscript. Il va donc être possible de créer des animations 3D ayant de très bonnes performances pour créer des carousels ou des fond d’écrans animés !

Support des architectures multicoeurs

Cette version va supporter les architectures multicoeurs et donc pouvoir répartir les taches sur les différents coeurs du terminal de façon automatique. Par exemple si le passage d’un Garbage Collector est nécessaire, il pourra s’effectuer sur le 2e coeur pendant que le 1er continu a exécuté l’application.

Rich media et connectivité

Support du HTTP Live Streaming

Première nouveauté et une de taille : le support du HTTP Live Streaming. Cette technologie créée par Apple a pour but de remplacer le RTSP pour transmettre des flux vidéos que ca soit des flux différés ou même des flux live. De plus elle permet de gérer des qualités différentes automatiquement afin de choisir le meilleur qualité en fonction du débit du terminal.

Ce support est une grande nouvelle et va pousser les éditeurs qui vendaient un player spécifique supportant cette technologie (Nextreaming est le plus connu dans ce domaine)  à trouver un autre marché !

Gestion des DRM

Il sera désormais possible de gérer facilement les contenus protégés par DRM en utilisant une API unique qui va gérer de façon transparente les différentes méthodes de DRM utilisées

Support du Media/Picture Transfer Protocol (MTP/PTP) via USB

Ce protocole permet de transférer des media ou des images de façon automatique entre des appareils sans avoir à monter le disque en tant que disque amovible. Il sera possible aux développeurs de créer des applications pour utiliser ce protocole

Ajout de nouvelles connectivités

Android 3.0 supportera les protocoles suivants : Bluetooth A2DP et les profils HSP. J’avoue que je ne m’y connais pas trop en Bluetooth et donc je ne vois pas trop ce que ça apporte …

Amélioration pour les entreprises

Les applications administratives peuvent désormais supporter de nouvelles polices de sécurités comme par exemple stockage de données encryptés, expiration de mots de passe, historique de mots de passe, nécessité d’avoir des caractères compliqués dans son mot de passe.

Installation et utilisation du SDK preview

Maintenant qu’on a vu un aperçu des nouvelles fonctionnalités de cette version, voila les informations si vous voulez tester ce SDK. Tout d’abord voila les informations à savoir :

  • Il ne s’agit pas de la version final du SDK. Une version finale du SDK sera fourni un peu avant la mise à disposition de ce SDK.
  • Il n’est pas possible de publier une application qui a été développée avec le SDK de preview. On peut seulement la tester avec l’émulateur prévu à cet effet.
  • La documentation de cette preview 3.0 n’est pas disponible en ligne. Il faut donc récupérer cette documentation et l’utiliser en version locale.

Cette preview se compose des éléments suivants :

  • Une image système (non terminée) d’Android 3.0 à utiliser dans l’émulateur
  • Une librarie Android 3.0 avec des APIs non finales
  • Un nouveau skin d’émulateur WXGA pour un AVD (Android Virtual Device) extra large
  • La documentation 3.0, contenant la référence complète de l’API, de nouveaux guides de développement, et un rapport des différences d’API entre 2.3 et 3.0.

Actuellement l’émulateur est très lent car il doit émuler l’architecture ARM et l’écran WXGA est beaucoup plus grand que les autres terminaux habituellement émulés. Les ingénieurs Android sont en train de se focaliser sur ce point afin d’avoir une performance sur émulateur acceptable. Bien entendu, les performances sur terminal n’auront rien à voir avec les performances actuelles de l’émulateur !

Enfin pour récupérer cette nouvelle version, il suffit de la télécharger depuis le Android SDK and AVD Manager comme pour les autres versions d’Android. Si vous débutez en développement Android, allez voir ici

Si vous voulez plus d’informations sur l’utilisation de ce SDK, je vous conseille d’aller voir ici

Source

Tutorial : utilisation des projets Android library

Ce tutoriel suppose que vous utilisiez Eclipse en version 3.5.2 (la version 3.6 est déconseillé pour le plugin Android), le SDK en révision 7 et le plugin ADT pour Eclipse en version 0.9.8

Cet article a pour objectif d’expliquer ce que sont et comment utiliser les Android library dans vos projets Android.

Présentation

Cette fonctionnalité relativement récente (intégré au SDK en mai 2010 avec la révision 6) permet de factoriser du code commun à plusieurs applications et donc de profiter d’une réutilisabilité plus forte de vos développements.

Elle est compatible avec les versions d’Android suivantes : 1.5, 1.6, 2.1 et 2.2.

La grande différence par rapport à l’utilisation d’un JAR contenant son code source est que les projets library Android permettent également de factoriser les ressources (layout, drawable, …) et donc de pouvoir réutiliser également des Activities ou des Providers !

Par exemple dans le cas d’une application disponible en version gratuite et payante, toute la partie commune peut être mise dans un projet library. Les 2 versions, payante et gratuite, vont inclure cette library et vont seulement ajouter le mécanisme spécifique de leur version : des pubs dans la version gratuite et le mécanisme de vérification d’achat réel de l’application dans la version payante par exemple.

Le code est du coup beaucoup plus simple à maintenir plutôt que de devoir continuellement copier/coller du code entre les 2 applications à chaque modification de la partie commune.

Au niveau architecture, un projet library Android ne se différencie pas, ou très peu, d’un projet standard Android. Il contient également un fichier manifest, des dossiers src/ et res/. Il est possible d’inclure des layout ou de stocker des images via le dossier standard drawable. Le code source peut utiliser ces ressources via la classe R standard.

Un projet library Android n’est par contre pas compilable en l’état en un fichier .apk. De la même façon, il n’est pas possible d’exporter ce projet sous la forme d’un JAR. A la place, il faut le référencer dans un projet standard Android qui va, lui, générer l’application complète. Il est par contre totalement possible d’intégrer une library JAR dans un projet library et même de référencer un projet library dans une projet library (mais on y reviendra plus tard dans l’article)

Cette génération va fusionner les sources provenant du projet principal et celle venant du projet library. Les ressources (contenu dans le dossier res/) seront également fusionnées. Si une ressource a la même ID dans le projet principal et le projet library, c’est celle du projet principal qui aura la priorité. Cela va permettre entre autres de surcharger des ressources.

Un projet peut référencer sans problème plusieurs projets library. Cela va permettre de segmenter son projet encore mieux. Comme on le verra tout à l’heure, il va être possible de prioriser un projet library par rapport à une autre (cela est principalement utile pour les ressources).

Les ressources du projet final ayant la priorité, si vous ne voulez pas que quelqu’un qui inclut votre librairie écrase une de vos ressources par erreur en en ajoutant une avec le même nom dans son projet, penser à utiliser des noms spéciaux ou encore mieux à préfixer toutes vos ressources par un identifiant spécifique à votre projet.

Création d’un projet library

La création d’un projet library est en tout point identique à la création d’un projet standard Android. Une fois ce projet créé (nommé dans le cas de ce tutoriel AndroLibFirst), nous allons changer un paramètre afin de transformer ce projet standard en projet library:

  1. Dans l’onglet Package Explorer , faire un clic droit sur le projet et choisir Properties.
  2. Dans la fenêtre qui s’ouvre, choisir la section “Android”. On remarque alors la présence d’une section Library en bas de la fenêtre
  3. Cocher la case “Is Library” et cliquer sur Apply.
  4. Valider les changements en cliquant sur le bouton OK.

Le projet est maintenant devenu un projet library ! Il est maintenant possible de le référencer dans un projet principal.

Gestion du fichier manifest d’un projet library

De la même façon que pour un projet standard, le fichier manifest doit définir les composants partagés de la librairie : les Activities, les Providers, …

Référencer un projet library dans le projet principal

Dans l’interface qu’on vient d’utiliser pour transformer notre projet standard en projet library, on remarque qu’il y a 4 boutons : Add, Remove, Up et Down. Ils vont permettre d’ajouter ou de retirer une référence vers un projet library et d’ordonner les références aux projets library entre elles. Il faut savoir que la librairie la plus haute dans la liste est prioritaire sur celles qui la suivent et que les ressources sont donc choisies en fonction de ces priorités.

Pour ajouter un référence vers notre projet AndroLibFirst depuis notre projet principal AndroLibMain, les actions sont les suivantes :

  1. Dans l’onglet Package Explorer , faire un clic droit sur le projet et choisir Properties.
  2. Dans la fenêtre qui s’ouvre, cliquer sur le bouton Add. Une popup s’ouvre alors montrant la liste des projets library disponibles dans le workspace.
  3. Choisir le projet AndroLibFirst que l’on veut référencer et cliquer sur le bouton OK.
  4. Validez les changements en cliquant sur le bouton OK.

La référence est alors mise en place par Eclipse et le code et les ressources du projet library(encadrés en bleu ci-dessous) sont maintenant accessibles dans le projet principal comme on peut le voir dans ce screenshot :

Gestion spéciale des composants library dans le fichier manifest du projet standard

Les composants du projet library que l’on veut rendre accessible dans l’APK final doivent être redéfini dans le manifest afin qu’ils soient pris en compte lors de la création de l’APK.

Cela concerne les balises <activity>, <service>, <receiver>, <provider> ainsi que les <permission> et <uses-library> entre autres. Les déclarations doivent utiliser les noms complets avec les packages afin qu’ADT puisse savoir exactement où chercher les éléments.

Fonctionnement spécial : l’imbrication des projets library

On va commencer ici à s’amuser un peu en s’amusant à enchaîner les projets library.

Exemple : un projet principal qui référence un projet library (jusque là c’est standard), qui lui-même référence un projet library qui peut lui aussi référencer un projet library, etc, etc, etc … (Toute ressemblance avec Inception n’est que pur coïncidence. On pourrait parler d’Androidception !)

Avant de voir comment faire cela, une chose à savoir ! Cela ne fonctionne que depuis la toute récente (hier soir) mise à jour du SDK et du plugin ADT. Il faut donc avoir le SDK révision 7 et le plugin ADT en version 0.9.8. Mettez à jour votre environnement avant de tester cette nouvelle fonctionnalité donc

Prenons un exemple bidon : un projet principal AndroLibMain qui inclut un projet library AndroLibFirst qui lui-même inclut un projet library AndroLibSecond. Le projet AndroLibMain contient une classe LibMain qui étend la classe LibFirst du projet AndroLibFirst qui elle-même étend la classe LibSecond du projet AndroLibSecond. Totalement inutile comme fonctionnement mais cela ira très bien comme exemple. Voyons maintenant comment réaliser cela :

  1. Pour commencer, on va créer nos 3 projets sans se soucier de savoir si ce sont des projets library ou non
  2. Une fois cela fait, on commence par transformer le projet AndroLibSecond en projet library. Pour ceux qui ont oublié comment faire, remonter un peu dans l’article pour trouver la marche à suivre
  3. On attaque ensuite la nouveauté ! A savoir transformer le projet AndroLibFirst en projet library et référencer dans celui-ci le projet AndroLibSecond.
    1. Pour la partie, transformer le projet en projet library, on fonctionne comme précédemment.
    2. Pour ajouter le projet library AndroLibSecond, on remarque que la zone d’ajout d’un projet library n’est pas grisé (ce qui était le cas avant la mise à jour du SDK r7 et du plugin ADT en version 0.9.8). Il nous suffit d’ajouter le projet library comme expliqué précédemment.
    3. On valide le tout. On a donc désormais un projet library AndroLibFirst référençant le projet AndroLibSecond
  4. Pour finir, il nous faut référencer ce projet AndroLibFirst dans le projet principal. On ajoute donc cette référence comme précédemment.
  5. Et la surprise ! Le projet principal AndroLibMain contient désormais une référence vers le projet AndroLibFirst ce qui est logique mais aussi vers le projet AndroLibSecond. Le plugin ADT s’est chargé de reporter le référence entre le projet AndroLibFirst et AndroLibSecond afin que lors de la création de l’apk du projet principal toutes les librairies nécessaires soient présentes !

Le résultat est donc le suivant :

On voit donc dans le projet AndroLibFirst les éléments entourés en bleu du référence du projet AndroLibSecond


Dans le projet principal, on a en vert les éléments du référencement direct du projet AndroLibFirst et en rouge les éléments indirectement référencés du projet AndroLibSecond

Migration des projets library de ADT 0.9.7 à 0.9.8

Afin de pouvoir gérer l’imbrication des projets library, le fonctionnement des projets library a été revu entre la version 0.9.7 et 0.9.8 du plugin ADT. La conséquence de cette modification est que si vous ouvrez un workspace ayant un projet library après avoir mis à jour le plugin ADT, vous allez tomber sur ce problème :

La référence MyLibrary est celle d’ADT 0.9.7 tandis que MyLibrary_src est celle d’ADT 0.9.8. Il faut donc déréférencer l’ancienne. Pour cela, les étapes à effectuer sont les suivantes :

  1. Faire un clic-droite sur MyLibrary et choisir Build Path puis Remove from Build Path
  2. Ensuite valider la pop-up qui s’ouvre en vérifiant que le choix “Also unlink the folder from the project” est bien coché

Le temps que Eclipse rebuild le projet et ca devrait être nickel !

Conclusion

Voila ! c’est la fin de ce tutoriel sur les projets library Android. Si vous avez encore des interrogations, n’hésitez pas à poser vos questions dans les commentaires, je ferais de mon mieux pour y répondre et sinon je vous conseille l’article plus complet disponible sur le site officiel Android (en anglais par contre) : A lire ici

Page optimized by WP Minify WordPress Plugin