Android Proguard - ClassNotFoundException

11,720

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.

Share:
11,720
Sayed Jalil Hassan
Author by

Sayed Jalil Hassan

SOreadytohelp

Updated on June 04, 2022

Comments

  • Sayed Jalil Hassan
    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