Android Proguard - ClassNotFoundException
Solution 1
You'll want to also make sure to add in the New Relic proguard exceptions found here: https://docs.newrelic.com/docs/mobile-monitoring/mobile-monitoring-installation/android/installing-android-apps-gradle-android-studio#proguard
-keep class com.newrelic.** { *; }
-dontwarn com.newrelic.**
-keepattributes Exceptions, Signature, InnerClasses
Solution 2
Remove the obfuscation rules related to activity and all also related to support libaries.Android studio by default has those templates.You could enable them by adding this rule in your gradle
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
Also please edit the rule for Jackson processor
-keep public class your.class.** {
public void set*(***);
public *** get*();
}
In this your class.** is the POJO(getter/setter) class that you have created for parsing your response
Solution 3
I know this is a rather old post but I would like to highlight the following should it help someone in the future.
The ClassNotFoundException
is an exception caused by applying name obfuscation to a class that's accessed using reflection. For example if ProGuard renames the class MyClass
, which is accessed in the code like this: Class.forName("MyClass");
, a ClassNotFoundException
will be thrown if the string still refers to MyClass
.
This is where we would need to add a -keep
option in order for ProGuard to not rename that class;
-keep class com.example.MyClass
When using broad -keep
options (ending with .** { *; }
), you will instruct ProGuard not to shrink, optimize or obfuscate all classes and classmembers for the package name mentioned before the wildcards. This will eventually lead in a poorly optimized project. Therefore it's better to narrow down such -keep
option to only target the missing class. In OP's example, the following error is thrown:
Caused by: java.lang.ClassNotFoundException: Didn't find class "mypackage.activities.MainActivity"
Adding a -keep
option for the missing class like shown below will tackle this particular issue;
-keep class mypackage.activities.MainActivity
ProGuard can help you set up narrowed down -keep
options if you add -addconfigurationdebugging
to the configuration file, more details on this feature is documented in the ProGuard manual, here.
Recently the ProGuard Playground was released, you can quickly visualise the effect of the broad -keep
options vs the narrowed down ones. A nice benefit here is that you do not need to continuously (re-)build the project.
Comments
-
Sayed Jalil Hassan about 2 years
I enabled proguard for my android app. I can build the project successfully but it crashes on startup with classNotFoundException. It doesn't even find the launcher activity. Here is my proguard rules file
-libraryjars libs -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keepnames class com.mypackage.** { *; } //someone suggested this but doesn't work # We only want obfuscation -keepattributes InnerClasses,Signature # 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 your.class.** { 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.**
and here is my build.gradle file if that helps but it doesn't include all the dependencies. I have some jars in the libs folder as well.
apply plugin: 'com.android.application' apply plugin: 'robolectric' apply plugin: 'android' apply plugin: 'newrelic' android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.mypackage" minSdkVersion 14 targetSdkVersion 21 versionCode 54 versionName "2.002" multiDexEnabled true testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner" resConfigs "en", "fr" , "ar" } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } sourceSets { androidTest { setRoot('src/test') } } dexOptions { javaMaxHeapSize "4g" } lintOptions { checkReleaseBuilds false // Or, if you prefer, you can continue to check for errors in release builds, // but continue the build even when errors are found: abortOnError false } repositories{ maven { url 'https://zendesk.artifactoryonline.com/zendesk/repo' } } repositories { mavenCentral() } dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile 'com.android.support:appcompat-v7:21.+' compile 'com.github.chrisbanes.photoview:library:1.2.3' compile 'com.etsy.android.grid:library:1.0.5' compile 'com.facebook.android:facebook-android-sdk:3.21.1' compile 'com.google.android.gms:play-services-base:6.5.+' compile 'com.google.android.gms:play-services-wallet:6.5.+' compile 'com.google.android.gms:play-services-ads:6.5.+' compile 'com.google.android.gms:play-services-maps:6.5.+' compile 'com.google.android.gms:play-services-drive:6.5.+' compile 'com.google.android.gms:play-services-appindexing:6.5.+' compile 'com.google.android.gms:play-services-location:6.5.+' compile 'com.google.android.gms:play-services-identity:6.5.+' compile 'com.google.android.gms:play-services-plus:6.5.+' compile 'com.android.support:multidex:1.0.+' compile project(':Adjust') compile project(':aFileChooser-cbccac1d1cb74a6d57d25c5ded61e4bf4fc40c91') compile 'com.parse.bolts:bolts-android:1.+' compile 'com.squareup.picasso:picasso:2.4.0' compile 'com.android.support:recyclerview-v7:+' compile (group: 'com.zendesk', name: 'sdk', version: '1.0.0.1'){ // exclude group:'picasso' } compile 'com.android.support:recyclerview-v7:+' compile 'com.newrelic.agent.android:android-agent:4.+' compile 'com.fasterxml.jackson.core:jackson-databind:2.4.2' compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.2' compile 'com.fasterxml.jackson.core:jackson-core:2.4.2' /*compile ('oauth.signpost:signpost-commonshttp4:1.2.1.2') { exclude module: 'commons-logging' exclude module: 'httpcore' exclude module: 'httpclient' } compile ('oauth.signpost:signpost-core:1.2.1.2') { exclude module: 'commons-codec' }*/ androidTestCompile 'org.robolectric:robolectric:2.4' androidTestCompile('junit:junit:4.12') androidTestCompile('org.mockito:mockito-core:1.10.19') } packagingOptions { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/NOTICE.txt' exclude 'META-INF/ASL2.0' exclude 'LICENSE.txt' } } robolectric { include '**/*Test.class' }
Here is the full stack trace:
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: Below is the missing part from the stacktrace.
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