I have an Android app whose debug builds work perfectly. Its release build however, which includes obfuscation with ProGuard (config is shown below), doesn't work and always crashes on start with the following log:
01-26 15:33:34.048 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.alxdroiddev.cameragear, PID: 6551
co: Fragment FragmentIntro{13af572c id=0x7f100177 android:switcher:2131755383:0} did not call through to super.onAttach()
at android.support.v4.app.FragmentManagerImpl.a(SourceFile:1232)
at android.support.v4.app.FragmentManagerImpl.v(SourceFile:2323)
at android.support.v4.app.FragmentManagerImpl.a(SourceFile:2136)
at android.support.v4.app.FragmentManagerImpl.b(SourceFile:2092)
at android.support.v4.app.FragmentManagerImpl.b(SourceFile:1969)
at bu.commitNowAllowingStateLoss(SourceFile:620)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(SourceFile:143)
at android.support.v4.view.ViewPager.populate(SourceFile:1268)
at android.support.v4.view.ViewPager.populate(SourceFile:1116)
at android.support.v4.view.ViewPager.onMeasure(SourceFile:1642)
at android.view.View.measure(View.java:17430)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.support.v7.widget.ContentFrameLayout.onMeasure(SourceFile:139)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
at android.view.View.measure(View.java:17430)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2001)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1166)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
I have tried adding the required calls (overriding onAttach()
in the faulty fragment), but that didn't make any difference. The fragment in question, is in the code below and it is used with the library AppIntro. This is the code for FragmentIntro.java
:
public class FragmentIntro extends Fragment implements ISlideBackgroundColorHolder { /* Static stuff */ private static final String ARG_LAYOUT_TITLE_ID = "titleId"; private static final String ARG_LAYOUT_MESSAGE_ID = "messageId"; private static final String ARG_LAYOUT_DRAWABLE_ID = "drawableId"; private static final String ARG_LAYOUT_COLOR_ID = "colorId"; //private static final int layoutResId = R.layout.intro_fragment; /* Private instance variables */ private int titleRedId, messageResId, drawableId, colorResId, colorCode; private RelativeLayout mainLayout; public static FragmentIntro newInstance(@StringRes int titleId, @StringRes int messageId, @DrawableRes int drawableId, @ColorRes int colorId) { FragmentIntro fragSlide = new FragmentIntro(); Bundle args = new Bundle(); args.putInt(ARG_LAYOUT_TITLE_ID, titleId); args.putInt(ARG_LAYOUT_MESSAGE_ID , messageId); args.putInt(ARG_LAYOUT_DRAWABLE_ID , drawableId ); args.putInt(ARG_LAYOUT_COLOR_ID, colorId ); fragSlide.setArguments(args); return fragSlide; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { this.titleRedId = getArguments().getInt(ARG_LAYOUT_TITLE_ID); this.messageResId = getArguments().getInt(ARG_LAYOUT_MESSAGE_ID); this.drawableId = getArguments().getInt(ARG_LAYOUT_DRAWABLE_ID); this.colorResId = getArguments().getInt(ARG_LAYOUT_COLOR_ID); } } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //super.onCreateView(inflater, container, savedInstanceState); //if (container == null) return null; View view = inflater.inflate(R.layout.intro_fragment, container, false); Utils.globalAppContext = getContext().getApplicationContext(); colorCode = ContextCompat.getColor(getContext().getApplicationContext(), colorResId); mainLayout = (RelativeLayout) view.findViewById(R.id.introLayout); mainLayout.setBackgroundColor(colorCode); ((TextView) view.findViewById(R.id.textViewIntroTitle)).setText(titleRedId); ((TextView) view.findViewById(R.id.textViewIntroMessage)).setText(messageResId); ((ImageView) view.findViewById(R.id.imageViewIntro)).setImageDrawable(Utils.getDrawableFromResource(drawableId)); return view; } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(ARG_LAYOUT_TITLE_ID, titleRedId); outState.putInt(ARG_LAYOUT_MESSAGE_ID, messageResId); outState.putInt(ARG_LAYOUT_DRAWABLE_ID, drawableId); outState.putInt(ARG_LAYOUT_COLOR_ID, colorResId); super.onSaveInstanceState(outState); } @Keep @TargetApi(23) @Override public void onAttach(Context context) { super.onAttach(context); } @Keep @SuppressWarnings("deprecation") @Override public void onAttach(Activity activity) { super.onAttach(activity); } @Override public void onDestroy() { super.onDestroy(); } @Override public void onPause() { super.onPause(); } @Override public void onResume() { super.onResume(); } @Override public void onStart() { super.onStart(); } @Override public void onStop() { super.onStop(); } // Implementation of ISlideBackgroundColorHolder @Override public int getDefaultBackgroundColor() { return colorCode; } @Override public void setBackgroundColor(@ColorInt int backgroundColor) { mainLayout.setBackgroundColor(backgroundColor); } }
The proguard config file I am using is this (and only this) :
#################################################################### GENERAL OPTIONS -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers -verbose -dontpreverify -repackageclasses '' -allowaccessmodification -mergeinterfacesaggressively -overloadaggressively -keepattributes *Annotation*,Signature,EnclosingMethod,InnerClasses -assumenosideeffects class com.alxdroiddev.cameragear.FragmentQueryRunner { *; } -assumenosideeffects class com.alxdroiddev.cameragear.FragmentCards { *; } -assumenosideeffects class com.alxdroiddev.cameragear.db.InitialSampleData { *; } # Required for Firebase Database (Models and POJOs) -keepclassmembers class com.alxdroiddev.cameragear.models.** { *; } #################################################################### 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(...); } -assumenosideeffects class com.alxdroiddev.utils.CLog { *; } #################################################################### IMAGECROPPER -keepnames class com.theartofdev.edmodo.cropper.** { *; } #################################################################### APPINTRO -keep class com.github.paolorotolo.** {*;} -keep public class com.alxdroiddev.cameragear.utils.FragmentIntro -keepclassmembers public class com.alxdroiddev.cameragear.utils.FragmentIntro {*;} -keep public class com.alxdroiddev.cameragear.ActivityIntro -keepclassmembers public class com.alxdroiddev.cameragear.ActivityIntro {*;} #################################################################### METADATA-EXTRACTOR -keep class com.drew.imaging.** { *; } -keep class com.drew.metadata.** { *; } -keep class com.drew.lang.** { *; } #################################################################### MISC STUFF -keep class * extends java.util.ListResourceBundle { protected java.lang.Object[][] getContents(); } # Needed for Parcelable/SafeParcelable Creators to not get stripped -keepnames class * implements android.os.Parcelable { public static final ** CREATOR; } -keepclassmembers class * implements android.os.Parcelable { static ** CREATOR; } # Needed when building against pre-Marshmallow SDK. -dontwarn android.security.NetworkSecurityPolicy -keep class android.support.customtabs.** { *; } -dontwarn android.support.customtabs.** -keep class com.google.android.gms.** { *; } -dontwarn com.google.android.gms.** #################################################################### IN-APP BILLING -keep public interface com.android.vending.licensing.ILicensingService -keep public class com.google.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService #################################################################### 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 (android.content.Context); } -keep public class android.support.v14.preference.** { *; } -keep public class android.support.v7.app.** { *; } -keep public class android.support.v7.preference.** { *; } -keep public class android.support.v4.app.** { *; } -dontwarn android.support.** -keep interface android.support.v4.** { *; } -keep interface android.support.v7.** { *; } -keep interface android.support.v13.** {*; } -keep interface android.support.v14.** {*; } #################################################################### ORG.APACHE.HTTP -keep class org.apache.http.** { *; } -keep interface org.apache.http.** -dontwarn org.apache.** #################################################################### 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 *; } #################################################################### FIREBASE -keep public class com.google.firebase.** { *; } -keep public class com.google.firebase.analytics.** { *; } -keep public class com.google.firebase.provider.** { *; } -keep public class com.google.firebase.auth.** { *; } -keep interface com.google.firebase.** {*; } -keep class com.firebase.** { *; } #################################################################### SUGGESTED OPTIMIZATIONS BY GOOGLE # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native -keepclasseswithmembernames class * { native ; } # keep setters in Views so that animations can still work. # see http://proguard.sourceforge.net/manual/examples.html#beans -keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); } # We want to keep methods in Activity that could be used in the XML attribute onClick -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keepclassmembers class **.R$* { public static ; } # Understand the @Keep support annotation. -keep class android.support.annotation.Keep -keep @android.support.annotation.Keep class * {*;} -keepclasseswithmembers class * { @android.support.annotation.Keep ; } -keepclasseswithmembers class * { @android.support.annotation.Keep ; } -keepclasseswithmembers class * { @android.support.annotation.Keep (...); }
I've lost track of how many hours I've spent trying to solve this, specially because everything runs in debug mode, and with no complaint about the super.onAttach()
. It only fails after obfuscating with the config above.
Thank you very much for your attention and any help is appreciated.
Best regards.