Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Android : Wiko, Samsung et appcompat-v7 v21

8 février 2015

Depuis octobre 2014, Google nous offre la version 21 de la bibliothèque de support appcompat. Cette bibliothèque permet aux développeurs d’appliquer à l’actionBar de leurs applications le style Material Design.

Malheureusement, si vous êtes développeur vous vous êtes très certainement rendu compte que votre application ne démarrait plus sur les téléphones Wiko sous Android 4.2.2 ainsi que sur certains téléphones Samsung sous la même version d’Android.

Dans ce billet, nous allons voir comment contourner le problème.

Le problème

Si vous utilisez la bibliothèque de support appcompat dans sa version 21 et que vous exécutez votre application sur un téléphone Wiko sous Android 4.2.2, vous devriez voir votre application planter et le message d’erreur suivant s’afficher dans le logcat :

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
at android.support.v7.app.ActionBarActivityDelegateBase.initializePanelMenu(ActionBarActivityDelegateBase.java:914)
at android.support.v7.app.ActionBarActivityDelegateBase.preparePanel(ActionBarActivityDelegateBase.java:964)
at android.support.v7.app.ActionBarActivityDelegateBase.doInvalidatePanelMenu(ActionBarActivityDelegateBase.java:1182)
at android.support.v7.app.ActionBarActivityDelegateBase.access$100(ActionBarActivityDelegateBase.java:79)
at android.support.v7.app.ActionBarActivityDelegateBase$1.run(ActionBarActivityDelegateBase.java:118)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5391)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)

Comme vous pouvez le constater, la classe MenuBuilder n’est pas trouvée par le téléphone.

La solution

La solution ne prend que quelques lignes et consiste à utiliser Proguard et écrire quelques règles spécifiques. Aussi, dans le fichier proguard-rules.pro de votre projet (si ce fichier n’existe pas créez le), écrivez les lignes suivantes :

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

-dontobfuscate
-dontoptimize

-keep class !android.support.v7.internal.view.menu.**, ** { *; }

Rendez-vous ensuite dans votre fichier build.gradle et plus précisément dans la section buildTypes pour activer l’utilisation du fichier au moment de la compilation de votre projet :

buildTypes 
{
  release 
  {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  }
  debug 
  {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  }
}

Si vous utilisez des bibliothèques externes comme par exemple Jackson, il n’est pas impossible que vous ayez des warnings à la compilation. Vous pouvez les ignorer en ajoutant des règles spécifiques dans le fichier proguard-rules.pro. Par exemple, piur ignorer les warnings liés à Jackson, vous pouvez ajouter la règle suivante :

-dontwarn com.fasterxml.**

Aussi, votre fichier proguard-rules.pro devrait alors ressembler à ça :

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

-dontobfuscate
-dontoptimize

-dontwarn com.fasterxml.**

-keep class !android.support.v7.internal.view.menu.**, ** { *; }

Commentaires