Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ProGuard +MultiDex causes ClassNotFoundException

I have MultiDex enabled in my android project. It was working fine until I tried enabling proguard. I can successfully build the project but I get runtime exception on startup. It's unable to find the Application class and the MainActivity. I had the same problem before enabling MultiDex. Now I guess for some reason the MultiDex is not working properly with ProGuard. Here is what i get in the 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 

and after that the rest of the stack trace is about ClassNotFoundException for the 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

Edit- Here is my proguard rules file:

-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.**
like image 913
Sayed Jalil Hassan Avatar asked Feb 18 '15 06:02

Sayed Jalil Hassan


Video Answer


1 Answers

This page says:

The default proguard.cfg file tries to cover general cases, but you might encounter exceptions such as ClassNotFoundException, which happens when ProGuard strips away an entire class that your application calls.

You can fix errors when ProGuard strips away your code by adding a -keep line in the proguard.cfg file. For example:

-keep public class <MyClass>

There are many options and considerations when using the -keep option, so it is highly recommended that you read the ProGuard Manual for more information about customizing your configuration file. The Overview of Keep options and Examples sections are particularly helpful. The Troubleshooting section of the ProGuard Manual outlines other common problems you might encounter when your code gets stripped away.

Solution 1

You could try the following proguard.cfg I used to obfuscate the code while not optimising, and hence not remove classes/methods from your APK.

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-dontoptimize
-verbose

Solution 2

You have asked some classes to be kept but not for MainActivity. So you have to add this line:

-keep class com.mypackage.activities.MainActivity { *; }
like image 162
Sufian Avatar answered Sep 29 '22 00:09

Sufian