dexguard 8.2.16 导致运行时崩溃

Posted

技术标签:

【中文标题】dexguard 8.2.16 导致运行时崩溃【英文标题】:Runtime crashes with dexguard 8.2.16 【发布时间】:2018-10-02 10:02:22 【问题描述】:

我的应用程序发生运行时崩溃,可能与Dexguard 混淆有关。该应用程序在没有混淆的调试和发布模式下没有问题,但是一旦我生成签名的 apk,我在运行时就会崩溃:

 java.lang.RuntimeException: Unable to start activity ComponentInfoit.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)

第 61 行是一个简单的 setContentView 指令。

这里是我的 styles.xml 文件:

<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>

这里有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>

我已经写信给DexGuard 支持,等待回复。有人知道吗?

【问题讨论】:

你有SignInActivity 吗?那有什么风格? SignInActivity 继承 AppTheme 并扩展 AppCompatActivity。它在 setContentView 上的 onCreate 之后立即崩溃 你没有尝试为 LoginActivity 和父级设置单独的样式:parent="Theme.AppCompat.Light.NoActionBar" 或清理重建项目吗? 我的活动被称为SignInActivity,我不认为不幸的是这个特定活动绑定的问题,整个应用程序继承了那个主题,我不想创建另一个我不需要的主题 【参考方案1】:

我已经被这个问题困扰了一周的大部分时间,不得不在构建时禁用 Dexguard,但我终于想通了。我希望这对你也有用。

问题似乎出在新的(ish)D8 desugar-er 中,它取代了旧的 DX 版本。 D8 在 Android Studio 3.x 中默认启用。因此,需要正确构建项目(据我所知,this article 帮助理解了这一点)。

对我有用的是从项目范围的 Gradle 设置 gradle.properies 中删除这一行:

android.enableD8.desugaring=false

我一直忽略 Gradle 同步阶段输出的以下警告:

警告:选项设置“android.enableD8.desugaring=false”是实验性的,不受支持。

我想不要忽视警告是我的教训!我找不到任何关于为什么这会导致问题发生的真正好的信息,但考虑到 D8 是 dexer 并且 Dexguard 当然也会影响到 dexing,它在这个领域是有道理的。

我还想与您分享崩溃的表面原因,因为了解它可能很有用,我当然很高兴我深入研究了它。

对于AppCompatActivity 活动,setContentView(...) 由实现setContentView 的具体类AppCompatDelegateImpl 处理。在第一次设置时,它将createSubDecor() 设置WindowViewGroup

我们都经历过的失败案例是这里的最后一个条件失败:

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 ...

因此windowNoTitle 的属性不会被错误地读取为缺失,因此默认为false,即使它应该为true。这就是为什么说使用以下Theme 属性的建议不起作用的原因,dexing(或脱糖,或其中的一部分)会搞砸。

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

无论如何,如果您是子主题Theme.AppCompat.Light.NoActionBar,那么这些已经设置好了,您不需要这样做。我在这条路线上浪费了一些时间,例如here、here、here、here 和 here。

然后发生错误,因为如果!mWindowNoTitle &amp;&amp; !(mIsFloating || mHasActionBar) 没有默认条件情况,您可以在此简化版本的代码中看到,该代码膨胀了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:  "
            + ....);

所以基本上我们需要mWindowNoTitle 为真。顺便说一句,它实际上并没有在这里设置,它是由requestWindowFeature(Window.FEATURE_NO_TITLE) 设置的,这正是我们将windowNoTitle 属性设置为true 时所调用的,正如预期的那样。有some advice建议手动调用它,但这最终不起作用,因为实际上我认为还有其他问题,这只是第一个受到打击。

这就是它发生的原因和方式。修复没有直接关系,所以正如我在开始时所说,看看你的 D8 配置。您还可能需要更新您的 Dexguard 配置或版本,使用 Dexguard 版本、Android Studio 版本管理 Gradle 版本一直是一场噩梦……这很困难。希望这对您有所帮助,并引起其他人的兴趣。

【讨论】:

以上是关于dexguard 8.2.16 导致运行时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

dexguard 混淆问题

带有 DexGuard 和 spongycastle 的 Java NoClassDefFoundError

启用 Dexguard 时,Crashlytics 的堆栈跟踪将文件名显示为未知来源

使用 dexguard 加密时,在运行时加载本机库需要更多时间

是啥导致应用程序在后台长时间运行后在恢复时崩溃?

运行签名的 apk 时出现 Dexguard 错误