Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apps crashes after obfuscation with ProGuard

I've been fighting this problem over the last 3 days.

My app is finished, tested on a few devices and emulator and ready to be published... or so I thought. After Exporting and signing it (I am using Eclipse with ADT, by the way), it stops working in any device or emulator. I figure the problem is with my ProGuard configuration, because if I disable ProGuard in project.properties, it works flawlessly after being exported.

This is my project.properties:

# Project target.
target=android-23
android.library.reference.1=..\\google-play-services_lib
android.library.reference.2=..\\android-support-design
proguard.config=proguard.cfg

(everything works after export if I jusst comment the proguard.config= line above)

proguard.cfg:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-dontwarn com.google.android.gms.**
-dontwarn android.support.v4.app.**
-dontwarn android.support.design.internal.**
-allowaccessmodification
-mergeinterfacesaggressively
-overloadaggressively
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*

-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.support.v4.app.FragmentPagerAdapter
-keep public class * extends android.app.Fragment
-keep public class * extends android.widget.**
-keep public class * extends android.view.View
-keep class * extends android.support.v7.**

-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }

-dontwarn android.support.v7.**
-keep class android.support.v7.internal.** { *; }
-keep interface android.support.internal.v7.** { *; }


-keep class com.google.android.gms.**

# For Google Play Services
-keep public class com.google.android.gms.ads.**{
   public *;
}

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}

-keep class android.support.**

-keepnames class * implements android.os.Parcelable
-keepclassmembers class * implements android.os.Parcelable {
  public static final *** CREATOR;
}

-keep @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclasseswithmembers class * {
  @android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
  @android.support.annotation.Keep <methods>;
}

-keep @interface com.google.android.gms.common.annotation.KeepName
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
  @com.google.android.gms.common.annotation.KeepName *;
}

-keep @interface com.google.android.gms.common.util.DynamiteApi
-keep public @com.google.android.gms.common.util.DynamiteApi class * {
  public <fields>;
  public <methods>;
}

# Other required classes for Google Play Services
# Read more at http://developer.android.com/google/play-services/setup.html
-keep class * extends java.util.ListResourceBundle {
   protected Object[][] getContents();
}


# Needed when building against pre-Marshmallow SDK.
-dontwarn android.security.NetworkSecurityPolicy

# Keep metadata about included modules.
-keep public class com.google.android.gms.dynamite.descriptors.** {
  public <fields>;
}

# Keep the implementation of the flags api for google-play-services-flags

-keep public class com.google.android.gms.flags.impl.FlagProviderImpl {
  public <fields>; public <methods>;
}


-keep class org.apache.http.**
-keep interface org.apache.http.**
-dontwarn org.apache.**
-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient

-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-dontwarn android.webkit.WebViewClient


-assumenosideeffects class android.util.Log {
    public static *** e(...);
    public static *** w(...);
    public static *** wtf(...);
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}

And finally, the error log I get when I run my app on a real device:

06-08 21:19:23.448: E/AndroidRuntime(12411): FATAL EXCEPTION: main
06-08 21:19:23.448: E/AndroidRuntime(12411): Process: com.alxdroiddev.cchecker, PID: 12411
06-08 21:19:23.448: E/AndroidRuntime(12411): android.view.InflateException: Binary XML file line #12: Error inflating class Button
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at com.alxdroiddev.cchecker.LinksFragment.onCreateView(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.Fragment.performCreateView(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.BackStackRecord.run(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.app.FragmentPagerAdapter.finishUpdate(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.view.ViewPager.populate(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.view.ViewPager.setCurrentItemInternal(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.view.ViewPager.setCurrentItemInternal(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.view.ViewPager.setCurrentItem(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.a(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.design.widget.TabLayout.a(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.design.widget.TabLayout$Tab.a(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.design.widget.TabLayout$TabView.performClick(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.View$PerformClick.run(View.java:20916)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.os.Handler.handleCallback(Handler.java:739)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.os.Handler.dispatchMessage(Handler.java:95)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.os.Looper.loop(Looper.java:145)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.app.ActivityThread.main(ActivityThread.java:5944)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at java.lang.reflect.Method.invoke(Native Method)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at java.lang.reflect.Method.invoke(Method.java:372)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
06-08 21:19:23.448: E/AndroidRuntime(12411): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.AppCompatBackgroundHelper.b(android.content.res.ColorStateList)' on a null object reference
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v7.widget.AppCompatButton.setBackgroundDrawable(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.View.setBackground(View.java:17237)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.View.<init>(View.java:4335)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.widget.TextView.<init>(TextView.java:1002)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.widget.Button.<init>(Button.java:115)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.widget.Button.<init>(Button.java:108)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v7.widget.AppCompatButton.<init>(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v7.widget.AppCompatButton.<init>(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(Unknown Source)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:181)
06-08 21:19:23.448: E/AndroidRuntime(12411):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:732)
06-08 21:19:23.448: E/AndroidRuntime(12411):    ... 28 more

My app has 1 activity with a TabLayout and 4 tabs. The first tab always opens successfully. I get the error above if I switch to another tab (change fragment). I get the same error even if the Fragment being switched to doesn't have a Button view in it.

Thanks in advance for the help. I've been struggling with this for the last 3 days.

like image 923
AlxDroidDev Avatar asked Jun 09 '16 00:06

AlxDroidDev


1 Answers

I got my problem solved.

This is the final proguard.cfg file I ended up with, that compiles with several optimizations and makes my app run smoothly:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-verbose
-dontpreverify
-allowaccessmodification
-mergeinterfacesaggressively
-overloadaggressively
-keepattributes *Annotation*


####################################################################  KEEP ANDROID SUPPORT V7 AND DESIGN

-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }

-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }

-keep public class * extends android.support.v4.view.ActionProvider {
    public <init>(android.content.Context);
}

-keep interface android.support.v4.** { *; }
-keep interface android.support.v7.** { *; }
-keep class android.support.** { *; }

####################################################################  REMOVE WARNINGS 


-dontwarn android.support.design.internal.**
-dontwarn com.google.android.gms.**
-dontwarn android.support.v4.**


####################################################################  REMOVE LOGGING 

-assumenosideeffects class android.util.Log {
    public static *** e(...);
    public static *** w(...);
    public static *** wtf(...);
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}

####################################################################  ORG.APACHE.HTTP 

-keep class org.apache.http.**
-keep interface org.apache.http.**
-dontwarn org.apache.**

####################################################################  WEVVIEW 

-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient
-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-dontwarn android.webkit.WebViewClient

####################################################################  GOOGLE PLAY SERVICES LIB - ADS

-keep public class com.google.android.gms.* { public *; }
#-keep class com.google.android.gms.**

# For Google Play Services
-keep public class com.google.android.gms.ads.**{
   public *;
}

####################################################################  GOOGLE PLAY SERVICES LIB

-keep class * extends java.util.ListResourceBundle {
    protected java.lang.Object[][] getContents();
}

# Keep SafeParcelable value, needed for reflection. This is required to support backwards
# compatibility of some classes.
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}

# Keep the names of classes/members we need for client functionality.
-keep @interface com.google.android.gms.common.annotation.KeepName
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
    @com.google.android.gms.common.annotation.KeepName *;
}

# Needed for Parcelable/SafeParcelable Creators to not get stripped
-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

# Needed when building against pre-Marshmallow SDK.
-dontwarn android.security.NetworkSecurityPolicy

# Keep metadata about included modules.
-keep public class com.google.android.gms.dynamite.descriptors.** {
  public <fields>;
}

# Keep the implementation of the flags api for google-play-services-flags

-keep public class com.google.android.gms.flags.impl.FlagProviderImpl {
  public <fields>; public <methods>;
}

I am placing this here as an answer to my own question because the config above might help someone who's also losing time and sleep with ProGuard.

Some of the optmizations were taken from this page:

https://github.com/krschultz/android-proguard-snippets/tree/master/libraries

The page above offers a collection of several library-specific ProGuard configurations, inclusing android.support.v7, and android.support.design.

like image 75
AlxDroidDev Avatar answered Nov 11 '22 10:11

AlxDroidDev