Android ProGuard + MultiDex causa ClassNotFoundException

Tengo MultiDex habilitado en mi proyecto androide. Estaba funcionando bien hasta que intenté habilitar proguard. Puedo construir con éxito el proyecto pero consigo la excepción del tiempo de ejecución en el arranque. No puede encontrar la clase Application y MainActivity . Tuve el mismo problema antes de habilitar MultiDex . Ahora supongo que por alguna razón MultiDex no está funcionando correctamente con ProGuard . Esto es lo que obtengo en el logcat –

 02-17 19:01:09.749: I/MultiDex(2079): VM with version 2.1.0 has multidex support 02-17 19:01:09.749: I/MultiDex(2079): install 02-17 19:01:09.749: I/MultiDex(2079): VM has multidex support, MultiDex support library is disabled. 02-17 19:01:09.750: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.app.FragmentActivity> 02-17 19:01:09.750: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.app.FragmentActivity> 02-17 19:01:09.751: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<mypackage.activities.MainActivity> 02-17 19:01:09.751: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<mypackage.activities.MainActivity> 02-17 19:01:09.751: D/AndroidRuntime(2079): Shutting down VM 02-17 19:01:09.751: D/AndroidRuntime(2079): --------- beginning of crash 

Y después de que el resto de la traza de pila es sobre ClassNotFoundException para MainActivity:

 02-17 19:01:09.752: E/AndroidRuntime(2079): FATAL EXCEPTION: main 02-17 19:01:09.752: E/AndroidRuntime(2079): Process: com.mypackage, PID: 2079 02-17 19:01:09.752: E/AndroidRuntime(2079): java.lang.NoClassDefFoundError: Failed resolution of: Lcom/mypackage/activities/MainActivity; 02-17 19:01:09.752: E/AndroidRuntime(2079): at cmypackage.application.ApplicationContextProvider.onCreate(Unknown Source) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.app.ActivityThread.access$1500(ActivityThread.java:144) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.os.Handler.dispatchMessage(Handler.java:102) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.os.Looper.loop(Looper.java:135) 02-17 19:01:09.752: E/AndroidRuntime(2079): at android.app.ActivityThread.main(ActivityThread.java:5221) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.reflect.Method.invoke(Native Method) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.reflect.Method.invoke(Method.java:372) 02-17 19:01:09.752: E/AndroidRuntime(2079): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 02-17 19:01:09.752: E/AndroidRuntime(2079): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 02-17 19:01:09.752: E/AndroidRuntime(2079): Caused by: java.lang.ClassNotFoundException: Didn't find class "mypackage.activities.MainActivity" on path: DexPathList[[zip file "/data/app/mypackage-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]] 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.ClassLoader.loadClass(ClassLoader.java:511) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.ClassLoader.loadClass(ClassLoader.java:469) 02-17 19:01:09.752: E/AndroidRuntime(2079): ... 12 more 02-17 19:01:09.752: E/AndroidRuntime(2079): Suppressed: java.lang.NoClassDefFoundError: mypackage.activities.MainActivity 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.DexFile.defineClassNative(Native Method) 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.DexFile.defineClass(DexFile.java:226) 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219) 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.DexPathList.findClass(DexPathList.java:321) 02-17 19:01:09.752: E/AndroidRuntime(2079): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54) 02-17 19:01:09.752: E/AndroidRuntime(2079): ... 14 more 02-17 19:01:09.752: E/AndroidRuntime(2079): Suppressed: java.lang.ClassNotFoundException: mypackage.MainActivity 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.Class.classForName(Native Method) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.BootClassLoader.findClass(ClassLoader.java:781) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) 02-17 19:01:09.752: E/AndroidRuntime(2079): at java.lang.ClassLoader.loadClass(ClassLoader.java:504) 02-17 19:01:09.752: E/AndroidRuntime(2079): ... 13 more 02-17 19:01:09.752: E/AndroidRuntime(2079): Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available 

Editar- Aquí está mi archivo de reglas proguard:

 -libraryjars libs # We only want obfuscation -keepattributes InnerClasses,Signature -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -dontoptimize -verbose # Sdk -keep public interface com.zendesk.sdk.** { *; } -keep public class com.zendesk.sdk.** { *; } # Appcompat and support #-keep interface android.support.v7.** { *; } #-keep class android.support.v7.** { *; } #-keep interface android.support.v4.** { *; } #-keep class android.support.v4.** { *; } # Gson -keep interface com.google.gson.** { *; } -keep class com.google.gson.** { *; } # Retrofit #-keep class com.google.inject.** { *; } #-keep class org.apache.http.** { *; } #-keep class org.apache.james.mime4j.** { *; } #-keep class javax.inject.** { *; } #-keep class retrofit.** { *; } #-keep interface retrofit.** { *; } # Retrofit -keep class com.squareup.okhttp.** { *; } -keep interface com.squareup.okhttp.** { *; } -dontwarn com.squareup.okhttp.** -dontwarn rx.** -dontwarn retrofit.** -dontwarn okio.** -keep class retrofit.** { *; } -keepclasseswithmembers class * { @retrofit.http.* <methods>; } # Jackson -keepattributes *Annotation*,EnclosingMethod,Signature -keepnames class com.fasterxml.jackson.** { *; } -dontwarn com.fasterxml.jackson.databind.** -keep class org.codehaus.** { *; } -keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility { public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; } -keep public class mypackage.parsers.JacksonParser.** { public void set*(***); public *** get*(); } #Picasso -dontwarn com.squareup.okhttp.** #-dontwarn javax.management.** #-dontwarn java.lang.management.** #-dontwarn org.apache.log4j.** #-dontwarn org.apache.commons.logging.** #-dontwarn org.json.* #-dontwarn org.apache.commons.codec.binary.Base64 #-keep class javax.** {* ; } #-keep class org.** { *; } -dontwarn org.mortbay.** -dontwarn org.slf4j.** -dontwarn org.apache.log4j.** -dontwarn org.apache.commons.logging.** -dontwarn org.apache.commons.codec.binary.** 

Esta página dice:

El archivo proguard.cfg predeterminado intenta cubrir casos generales, pero es posible que encuentre excepciones como ClassNotFoundException , lo que sucede cuando ProGuard elimina una clase completa que su aplicación llama.

Puede corregir errores cuando ProGuard quita el código añadiendo una línea de -keep en el archivo proguard.cfg . Por ejemplo:

 -keep public class <MyClass> 

Hay muchas opciones y consideraciones al usar la opción -keep, por lo que es muy recomendable que lea el Manual de ProGuard para obtener más información acerca de cómo personalizar su archivo de configuración. Las secciones Resumen de opciones de mantenimiento y Ejemplos son particularmente útiles. La sección Solución de problemas del Manual de ProGuard esboza otros problemas comunes que puede encontrar cuando el código se quita.

Solución 1

Usted podría intentar el proguard.cfg siguiente que utilizó para ofuscar el código mientras que no optimiza, y por lo tanto no quita clases / métodos de su APK.

 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -dontoptimize -verbose 

Solución 2

Ha solicitado que se mantengan algunas clases, pero no para MainActivity . Así que tienes que añadir esta línea:

 -keep class com.mypackage.activities.MainActivity { *; } 
  • Ofuscación Clases parcelables con proguard
  • ¿Cuál es la diferencia entre proguard-android.txt y proguard-rules.pro? - Android
  • La aplicación de Android se bloquea en la generación de versiones con el uso de Proguard y Dagger
  • Ofuscación de clases de modelo ORMLite con Proguard
  • Con ProGuard, ¿cuál es el impacto en la estrategia de pruebas?
  • Proguard convierte todos los enums en int o necesita ser configurado para este
  • Archivo proguard obsoleto; Usar -contienen a los miembros en vez de -contemplarlosconmiembros
  • Eliminar el registro con Proguard
  • Comprensión de bloqueos y ANR con Proguard habilitado
  • NullPointerException al usar el archivo XML en res / raw con Proguard
  • ¿Cómo configurar proguard para la aplicación de Android con Google Drive SDK?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.