2

I have a runtime crash in our app probably bound to Dexguard obfuscation. The app has no problems in debug and release mode without obfuscation, however once I generate the signed apk I get this crash at runtime:

 java.lang.RuntimeException: Unable to start activity ComponentInfo{it.package.name/it.package.name.login.SignInActivity}: java.lang.IllegalArgumentException: AppCompat does not support the current theme features: { windowActionBar: false, windowActionBarOverlay: false, android:windowIsFloating: false, windowActionModeOverlay: false, windowNoTitle: false }
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2815)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1614)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:171)
        at android.app.ActivityThread.main(ActivityThread.java:6649)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
     Caused by: java.lang.IllegalArgumentException: AppCompat does not support the current theme features: { windowActionBar: false, windowActionBarOverlay: false, android:windowIsFloating: false, windowActionModeOverlay: false, windowNoTitle: false }
        at o.ﭥ.ʿ(:469)
        at o.ﭥ.ʽॱ(:323)
        at o.ﭥ.ˋ(:284)
        at o.ᵈ.setContentView(:139)
        at it.package.name.login.SignInActivity.onCreate(:61)

Line 61 is a simple setContentView instruction.

Here my styles.xml file:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@android:color/transparent</item>
        <item name="colorPrimaryDark">@color/colorPrimaryGrey</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColorHint">@color/hintColor</item>
        <item name="android:fontFamily">@font/montserrat_regular</item>
        <item name="android:background">@android:color/transparent</item>
    </style>

    <style name="AppThemeTranslucent" parent="AppTheme">
        <!-- Customize your theme here. -->
        <item name="android:background">@null</item>
    </style>

    <style name="DialogFragmentStyle" parent="Base.Theme.AppCompat.Light.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsFloating">false</item>
    </style>

    <style name="RegistrationTheme" parent="AppTheme">
        <item name="android:windowBackground">@color/registrationBackgroundColor</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkGreen</item>
        <item name="colorAccent">@color/colorPrimary</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:textColorSecondary">@color/colorPrimary</item>
    </style>

    <style name="RegistrationTitle" parent="RegistrationTheme">
        <item name="android:textSize">@dimen/registration_title_font_size</item>
        <item name="android:textColor">@color/registrationTitleTextColor</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="PopupTitle" parent="RegistrationTitle">
        <item name="android:textSize">@dimen/popup_title_font_size</item>
    </style>

    <style name="PermissionButton" parent="Base.Widget.AppCompat.Button.Borderless">
        <item name="android:height">56dp</item>
        <item name="android:textColor">@color/registrationTitleTextColor</item>
        <item name="android:textSize">14sp</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:padding">0dp</item>
    </style>

    <style name="PopupSubtitle" parent="RegistrationAbstract">
        <item name="android:textSize">@dimen/popup_subtitle_font_size</item>
    </style>

    <style name="RegistrationAbstract" parent="RegistrationTheme">
        <item name="android:textSize">@dimen/registration_abstract_font_size</item>
        <item name="android:textColor">@color/registrationTitleTextColor</item>
        <item name="android:lineSpacingExtra">@dimen/registration_abstract_spacing_extra</item>
    </style>

    <style name="RegistrationEditText" parent="RegistrationTheme">
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">@color/colorPrimary</item>
        <item name="android:background">@android:color/white</item>
        <item name="android:paddingStart">@dimen/activity_horizontal_margin</item>
        <item name="android:paddingEnd">@dimen/activity_horizontal_margin</item>
        <item name="android:paddingTop">@dimen/base_padding</item>
        <item name="android:paddingBottom">@dimen/base_padding</item>
        <item name="android:minHeight">@dimen/edit_text_min_height</item>
    </style>

    <style name="FabStyle" parent="RegistrationTheme">
        <item name="colorAccent">@android:color/white</item>
    </style>

    <style name="AndroidImageSlider_Magnifier_Oval_Green">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:gravity">center</item>
        <item name="android:paddingLeft">5dp</item>
        <item name="android:paddingRight">5dp</item>
        <item name="shape">oval</item>
        <item name="padding_left">6dp</item>
        <item name="padding_right">6dp</item>
        <item name="padding_top">4dp</item>
        <item name="padding_bottom">4dp</item>

        <item name="selected_color">@color/green</item>
        <item name="unselected_color">#95D8B9</item>
        <item name="selected_width">10dp</item>
        <item name="selected_height">10dp</item>
        <item name="unselected_width">10dp</item>
        <item name="unselected_height">10dp</item>
    </style>

    <style name="CustomToggleButton" parent="Widget.AppCompat.Button">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:background">@null</item>
        <item name="android:minHeight">0dp</item>
        <item name="android:minWidth">0dp</item>
        <item name="android:padding">10dp</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:textOff">@string/SignIn_HidePassword_Button</item>
        <item name="android:textOn">@string/SignIn_ShowPassword_Button</item>
    </style>

    <style name="ThemeOverlay.AppCompat.navTheme">
        <!-- Color of text and icon when SELECTED -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <!-- Background color when SELECTED -->
        <item name="colorControlHighlight">@android:color/transparent</item>
    </style>

    <style name="DefaultCardLayout">
        <item name="android:background">@color/white</item>
        <item name="android:paddingStart">13dp</item>
        <item name="android:paddingEnd">13dp</item>
        <item name="android:paddingTop">22dp</item>
        <item name="android:paddingBottom">22dp</item>
    </style>

    <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
        <!--<item name="tabMaxWidth">@dimen/tab_max_width</item>-->
        <item name="tabIndicatorColor">@color/colorPrimary</item>
        <item name="tabIndicatorHeight">2dp</item>
        <item name="tabPaddingStart">12dp</item>
        <item name="tabPaddingEnd">12dp</item>
        <item name="tabBackground">?attr/selectableItemBackground</item>
        <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
        <item name="tabSelectedTextColor">?android:textColorPrimary</item>
    </style>

    <style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
        <item name="android:textSize">14sp</item>
        <item name="android:textColor">?android:textColorSecondary</item>
        <item name="textAllCaps">false</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <!-- Splash Screen theme. -->
    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/splash_background</item>
    </style>

    <style name="GreenText" parent="AppTheme">
        <item name="android:textColor">@color/green</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="DarkGreenText" parent="AppTheme">
        <item name="android:textColor">@color/zehus_dark_green</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="CheckboxStyle" parent="Widget.AppCompat.CompoundButton.CheckBox">
        <item name="android:button">@drawable/custom_checkbox</item>
    </style>

    <style name="StartRentalStyle" parent="Widget.AppCompat.Button.Colored">
        <item name="colorControlNormal">@color/green</item>
        <item name="android:textColor">@color/white</item>
    </style>

    <style name="GreenTint" parent="ThemeOverlay.AppCompat.Dark">
        <!-- customize colorButtonNormal for the disable color -->
        <!-- customize colorAccent for the enabled color -->
        <item name="colorButtonNormal">@color/zehus_dark_green_disabled</item>
        <item name="colorAccent">@color/zehus_dark_green</item>
        <item name="textColor">@color/white</item>
        <item name="textAllCaps">false</item>
    </style>

    <style name="BookedTint" parent="Widget.AppCompat.Button.Colored">
        <item name="colorControlNormal">@color/base_orange</item>
        <item name="textColor">@color/white</item>
        <item name="textAllCaps">false</item>
    </style>


    <style name="WhiteTint" parent="Widget.AppCompat.Button.Colored">
        <item name="colorControlNormal">@color/white</item>
        <item name="textAllCaps">false</item>
    </style>

</resources>

Here there is styles.xml (v21)

<resources>

    <style name="StartRentalStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:backgroundTint">@color/green</item>
        <item name="android:textColor">@color/white</item>
    </style>

    <style name="AppThemeTranslucent" parent="AppTheme">
        <!-- Customize your theme here. -->
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:background">@null</item>
    </style>
</resources>

I've already written to DexGuard support, waiting for a response. Does anybody have a clue?

Nicola Gallazzi
  • 7,897
  • 6
  • 45
  • 64
  • Do you have `SignInActivity` ? What are the styles for that? – ʍѳђઽ૯ท Oct 02 '18 at 10:15
  • SignInActivity inherits AppTheme and extends AppCompatActivity. It crashes right after onCreate on setContentView – Nicola Gallazzi Oct 02 '18 at 10:18
  • Haven't you tried setting seperated styles for LoginActivity and parent of : `parent="Theme.AppCompat.Light.NoActionBar"` or clean-rebuild the project? – ʍѳђઽ૯ท Oct 02 '18 at 10:21
  • My activity is called SignInActivity, I don't think unfortunately is a problem bound to this specific activity, the entire app inherits that theme and I don't want to create another theme I don't need – Nicola Gallazzi Oct 02 '18 at 10:30

1 Answers1

1

I've been stuck on this for the better part of a week and have had to disable Dexguard on builds, but I finally figured it out. I hope this works for you too.

The issue appears to be in the new(ish) D8 desugar-er, which replaced the old DX version. D8 is enabled by default in Android Studio 3.x. As such it is required to build project correctly (as far as I can make out, this article helped understand that).

What worked for me was removing this line from gradle.properies, the project-wide Gradle settings:

android.enableD8.desugaring=false

I had been ignoring the following warning from Gradle's sync phase output:

WARNING: The option setting 'android.enableD8.desugaring=false' is experimental and unsupported.

I guess don't ignore the warnings is my lesson here! I couldn't find any really good information about why this causes the issue to happen, but it makes sense that it would be in this area considering that D8 is the dexer, and Dexguard is of course also impacting on dexing.

I'd like to also share with you the surface level cause of the crash as it might be useful to know, and I'm certainly happy I looked deeply at it.

For AppCompatActivity activities, setContentView(...) is handled by AppCompatDelegateImpl concrete class which implements setContentView. On first time set up it will createSubDecor() to set up the Window root ViewGroup.

The failing case here that we have both experienced is that the last condition here fails:

private ViewGroup createSubDecor() {
        TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme);

        if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
            a.recycle();
            throw new IllegalStateException(
                    "You need to use a Theme.AppCompat theme (or descendant) with this activity.");
        }

        if (a.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false)) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        } else ...

So the attribute for windowNoTitle is not read incorrectly as missing, and so defaults to false, even though it should be true. This is why the advice saying to use the following Theme attributes will not work, dexing (or desugaring, or some part of this) messes it up.

    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>

In any case if you are sub-Theming Theme.AppCompat.Light.NoActionBar then these are already set and you shouldn't need to. I lost some time going down this route, e.g. here, here, here, here and here.

The error then occurs because there is no default condition case if !mWindowNoTitle && !(mIsFloating || mHasActionBar), as you can see in this simplified version of the code that inflates the subDecor ViewGroup:

if (!mWindowNoTitle) {
    if (mIsFloating) {
        subDecor = ...
    } else if (mHasActionBar) {
        subDecor = ...
    }
    // else, nothing! subDecor remains null, problem case
} else {
    if (mOverlayActionMode) {
        subDecor = ...
    } else {
        subDecor = ...
    }
}

if (subDecor == null) {
    throw new IllegalArgumentException(
        "AppCompat does not support the current theme features: { "
            + ....);
}

So basically we need mWindowNoTitle to be true. Incidentally it has actually not set here, it's set by requestWindowFeature(Window.FEATURE_NO_TITLE), which is exactly what is called if we have the windowNoTitle attribute set to true, as expected. There is some advice suggesting calling it manually, but this ultimately doesn't work, as there are in fact I think other problems, this is just the first that gets hit.

So that's why and how it happens. The fix is not directly related, so as I said at the start, look at your D8 configuration. There's also a chance you need to update your Dexguard config or version, it has been a nightmare managing Gradle versions with Dexguard versions, Android Studio versions... it's difficult. Hopefully this helps you and is of interest to others.

r3flss ExlUtr
  • 720
  • 7
  • 17