Android App crashes after proguard obfuscation

11,973

Solution 1

You need to save some classes from being obfuscated. A typical proguard configuration file for an Android project is as below. This link should be useful: Proguard for Android

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * implements java.io.Serializable
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.support.v4.app.ListFragment



-keep public class org.spongycastle.** {
  <fields>;
  <methods>;
}

-keep public class org.apache.** {
  <fields>;
  <methods>;
}

-ignorewarnings

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}


-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

Solution 2

Quick working solution

-keep  class com.fasterxml.jackson.annotation.** {*;}
-keep  class com.fasterxml.jackson.core.** {*;}
-keep  class com.fasterxml.jackson.databind.** {*;}
Share:
11,973
DJ-DOO
Author by

DJ-DOO

Updated on June 04, 2022

Comments

  • DJ-DOO
    DJ-DOO about 2 years

    I have run proguard tool on my app to obfuscate. I do know that when obfuscation occurs that proguard shrinks and optimizes the app as it sees fit. So after obfuscating the app opens correctly and then when I try to log in it crashes. The best I could get was this log as I had the device connected.

    10-03 11:12:47.384: E/AndroidRuntime(15058): FATAL EXCEPTION: AsyncTask #1
    10-03 11:12:47.384: E/AndroidRuntime(15058): java.lang.RuntimeException: An error     occured while executing doInBackground()
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at     android.os.AsyncTask$3.done(AsyncTask.java:299)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at     java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.lang.Thread.run(Thread.java:856)
    10-03 11:12:47.384: E/AndroidRuntime(15058): Caused by: java.lang.ExceptionInInitializerError
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at com.winwin.a.d.c.doInBackground(Unknown Source)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at com.winwin.a.d.c.doInBackground(Unknown Source)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    ... 4 more
    10-03 11:12:47.384: E/AndroidRuntime(15058): Caused by: java.lang.ExceptionInInitializerError
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at com.winwin.a.c.d.<clinit>(Unknown Source)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    ... 8 more
    10-03 11:12:47.384: E/AndroidRuntime(15058): Caused by: java.lang.ExceptionInInitializerError
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at com.b.a.c.ad.<clinit>(Unknown Source)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    ... 9 more
    10-03 11:12:47.384: E/AndroidRuntime(15058): Caused by: java.lang.NoSuchFieldError: ANY
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.lang.Class.getDeclaredAnnotation(Native Method)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at java.lang.Class.getAnnotation(Class.java:260)
    10-03 11:12:47.384: E/AndroidRuntime(15058):    at com.b.a.c.f.ag.<clinit>(Unknown Source)
    

    I had thought that this would be because proguard had removed some classes or methods it deemed unnecessary and therefore cause the crash. What I did was I ran proguard again this time including

    -dontobfuscate
    

    so I wanted the tool to shrink and optimize but not obfuscate so I could then get a proper reading as to what was missing. However, when I generated the apk using the tool this time around it ran perfectly. Problem being it wasn't obfuscated.

    So I don't know what to do now.

    Does anyone have any ideas?

    *EDIT*

    Here is my config file

    To enable ProGuard in your project, edit project.properties
    to define the proguard.config property as described in that file.
    
    Add project specific ProGuard rules here.
    By default, the flags in this file are appended to flags specified
    in ${sdk.dir}/tools/proguard/proguard-android.txt
    You can edit the include path and order by changing the ProGuard
    include property in project.properties.
    
    For more details, see
    http://developer.android.com/guide/developing/tools/proguard.html
    
    Add any project specific keep options here:
    
    -libraryjars libs/crashlytics.jar
    
    -keep class com.facebook.** {
    *;
    }
    
    
    -keepattributes Signature
    
    -optimizationpasses 5
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -dontpreverify
    -verbose
    
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    
    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Application
    -keep public class * extends android.app.Service
    -keep public class * extends android.content.BroadcastReceiver
    -keep public class * extends android.content.ContentProvider
    -keep public class * extends android.app.backup.BackupAgentHelper
    -keep public class * extends android.preference.Preference
    -keep public class com.android.vending.licensing.ILicensingService
    
    keep all classes that might be used in XML layouts
    -keep public class * extends android.view.View
    -keep public class * extends android.app.Fragment
    -keep public class * extends android.support.v4.Fragment
    
    -keepattributes *Annotation*, EnclosingMethod
    
    -keep class com.winwin.** { *; }
    -keepnames class org.codehaus.jackson.** { *; }
    
    
    -dontoptimize
    -dontshrink
    
    keep all public and protected methods that could be used by java reflection
    -keepclassmembernames class * {
     public protected <methods>;
    }
    
    -keepclasseswithmembernames class * {
    native <methods>;
    }
    
    -keepclasseswithmembernames class * {
     public <init>(android.content.Context, android.util.AttributeSet);
    }
    
    -keepclasseswithmembernames class * {
      public <init>(android.content.Context, android.util.AttributeSet, int);
    }
    
    
    -keepclassmembers enum * {
      public static **[] values();
      public static ** valueOf(java.lang.String);
     }
    
    -keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
    }
    
     -dontwarn **CompatHoneycomb
     -dontwarn org.htmlcleaner.*
    
     -dontwarn com.fasterxml.jackson.databind.ext.**
    
     If your project uses WebView with JS, uncomment the following
     and specify the fully qualified class name to the JavaScript interface
     class:
    -keepclassmembers class fqcn.of.javascript.interface.for.webview {
    public *;
    }
    

    ==========================

    Here is my project explorer pane


    android-support-v7-appcompat / ConverserSdk / facebook / google-play-services_lib / library / Main / MainWs / SlidingMenu


    So my main is dependant on each of the other packages.

    • GrIsHu
      GrIsHu over 10 years
      Do you have getter setter methods in your doInBackground method ?
    • DJ-DOO
      DJ-DOO over 10 years
      @GrIsHu I have no getter or setter methods within the doInBackground() however there is error checking within this method, if there is an error, I call methods that have setter methods..could this be a factor?
    • laalto
      laalto over 10 years
      You have some code (guess: some JSON object mapper library) that relies on reflection to access annotations and the obfuscator breaks when reflection access is used. You need to add -keepattributes *Annotation*,EnclosingMethod -keep class reflection.using.package.name.** { *; }
    • GrIsHu
      GrIsHu over 10 years
      Do not add the class to be obfuscate in your proguard file add the line containing your class package name. -keep class reflection.using.package.name.** { *; } in your proguard file.
    • DJ-DOO
      DJ-DOO over 10 years
      @laalto Yes I have some JSON mapper in my do in background. Where it says '-keep class reflection.using.package.name.**' Do I modify that to '-keep class reflection.using.com.DJ-DOO.name.**'?
    • laalto
      laalto over 10 years
      @dj-doo replace reflection.using.package.name with the package name of the library. For example, if it's Jackson, org.codehaus. (That probably keeps too much unobfuscated but gives you a safer starting point.)
    • DJ-DOO
      DJ-DOO over 10 years
      it is jackson. I unfortunately didn't do the webservices work on this. There are alot of ws calls in this app. so I change it to '-keep class org.codehaus.** {*;}' ?
    • laalto
      laalto over 10 years
    • DJ-DOO
      DJ-DOO over 10 years
      @laalto thank you for your help, however even with -keepattributes Annotation, EnclosingMethod and -keepnames class org.codehaus.jackson.** { *; } I still get the very same issues. In my project explorer I have my main project package, however, I also have other packages that include jars that my main package is dependant on, could this make a difference? for example all my webservice methods are in seperate package to my main package.
    • akash89
      akash89 over 4 years
      @DJ-DOO- I am facing same issue. How to fix this?Also, how did you manage to read the obfuscated crash logs? Any help will be highly appreciated.
  • DJ-DOO
    DJ-DOO over 10 years
    Thanks for your reply, I have been there already though and followed that site.
  • W.M.
    W.M. over 4 years
    How to know which classes to keep?
  • Vinayak
    Vinayak over 4 years
    It depends on libs you used .For android by default several classes will be kept as is.