Android ProGuard + MultiDex вызывает ClassNotFoundException

У меня есть MultiDex включен в моем проекте Android. Он работал нормально, пока я не попытался включить proguard. Я могу успешно создать проект, но при запуске получаю исключение во время выполнения. Он не может найти класс Application и MainActivity . Перед тем как включить MultiDex меня была такая же проблема. Теперь я думаю, почему-то MultiDex не работает должным образом с ProGuard . Вот что я получаю в 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 

И после этого остальная трассировка стека относится к ClassNotFoundException для 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 

Изменить. Вот мой файл правил 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.** 

На этой странице написано:

Файл proguard.cfg умолчанию пытается охватить общие случаи, но вы можете столкнуться с такими исключениями, как ClassNotFoundException , которое происходит, когда ProGuard удаляет весь класс, который вызывает ваше приложение.

Вы можете исправить ошибки, когда ProGuard удаляет ваш код, добавив строку proguard.cfg файл proguard.cfg . Например:

 -keep public class <MyClass> 

Существует множество опций и соображений при использовании опции -keep, поэтому вам настоятельно рекомендуется прочитать руководство ProGuard для получения дополнительной информации о настройке файла конфигурации. Особенно полезны разделы «Обзор вариантов» и «Примеры». В разделе «Поиск и устранение неисправностей» Руководства ProGuard описаны другие распространенные проблемы, которые могут возникнуть при удалении кода.

Решение 1

Вы можете попробовать следующий proguard.cfg Я использовал для обфускации кода, не оптимизируя, и, следовательно, не удаляю классы / методы из вашего APK.

 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -dontoptimize -verbose 

Решение 2

Вы попросили сохранить некоторые классы, но не для MainActivity . Таким образом, вы должны добавить эту строку:

 -keep class com.mypackage.activities.MainActivity { *; }