Android 10 台设备上的 Resources$NotFoundException

Resources$NotFoundException on Android 10 devices

问题

我注意到仅在 Android 10 台设备上发生了很多意外崩溃。崩溃是指在不同的布局中缺少资源 ID,但我什至无法在同一设备上重现它,并且 OS 正如我在崩溃 reports.Weirdly 中看到的那样,经过数小时的挖掘 google搜索结果第 4 页及更多(我迷路了,结果是普通话)我发现 post 指向开发人员选项 -> 启用视图属性检查。在我的设备上启用它后,我可以重现它,但仍然不清楚如何修复它。禁用它有帮助,应用程序用户不会在那里看到崩溃。

问题

尽管这有帮助,但我想知道它的罪魁祸首是什么以及修复它的正确方法是什么。

崩溃日志

android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f040378
    at android.content.res.ResourcesImpl.getResourceTypeName(ResourcesImpl.java:305)
    at android.content.res.Resources.getResourceTypeName(Resources.java:2111)
    at android.content.res.Resources$Theme.getExplicitStyle(Resources.java:1769)
    at android.view.View.retrieveExplicitStyle(View.java:6731)
    at android.view.View.<init>(View.java:5639)
    at android.view.ViewGroup.<init>(ViewGroup.java:687)
    at android.widget.FrameLayout.<init>(FrameLayout.java:99)
    at android.widget.FrameLayout.<init>(FrameLayout.java:94)
    at androidx.cardview.widget.CardView.<init>(SourceFile:121)
    at com.google.android.material.card.MaterialCardView.<init>(SourceFile:52)
    at com.google.android.material.card.MaterialCardView.<init>(SourceFile:48)
    at java.lang.reflect.Constructor.newInstance0(Constructor.java)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
    at android.view.LayoutInflater.createView(LayoutInflater.java:854)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:1126)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:682)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
    at androidx.databinding.DataBindingUtil.inflatecd3863(SourceFile:126)
    at androidx.databinding.ViewDataBinding.inflateInternal50870e(SourceFile:1366)
    at com.example.app.LoginFragmentBinding.inflate(SourceFile:1090)
    at com.example.app.LoginFragment.onCreateView(SourceFile:66)
    at androidx.fragment.app.Fragment.performCreateView(SourceFile:2439)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(SourceFile:1460)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(SourceFile:1784)
    at androidx.fragment.app.BackStackRecord.executeOps(SourceFile:797)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(SourceFile:2625)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(SourceFile:2411)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(SourceFile:2366)
    at androidx.fragment.app.FragmentManagerImpl.execPendingActions(SourceFile:2273)
    at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(SourceFile:3273)
    at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:3229)
    at androidx.fragment.app.Fragment.performActivityCreated(SourceFile:2466)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(SourceFile:1483)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(SourceFile:1784)
    at androidx.fragment.app.BackStackRecord.executeOps(SourceFile:797)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(SourceFile:2625)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(SourceFile:2411)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(SourceFile:2366)
    at androidx.fragment.app.FragmentManagerImpl.execPendingActions(SourceFile:2273)
    at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(SourceFile:3273)
    at androidx.fragment.app.FragmentActivity.androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:17229)
    at androidx.appcompat.app.AppCompatActivity.onStart(SourceFile:178)
    at com.ing.mobile.app.activities.INGMobileActivity.onStart(SourceFile:145)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1433)
    at android.app.Activity.performStart(Activity.java:7978)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3472)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:237)
    at android.app.ActivityThread.main(ActivityThread.java:7814)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)

布局

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <import type="model.CustomerType" />

        <import type="android.view.View" />

        <import type="AccessibilityUtils" />

        <variable
            name="view"
            type="login.LoginView" />

        <variable
            name="presenter"
            type="login.LoginPresenter" />
    </data>

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:liftOnScroll="?attr/myAppBarLayoutScrollingBehaviorEnabled">
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                app:navigationContentDescription="@string/login__cancel_content_description"
                app:navigationIcon="?attr/navigationCloseDrawable">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:contentDescription="@string/login__header_content_description"
                    app:srcCompat="@drawable/logo" />
            </androidx.appcompat.widget.Toolbar>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="?attr/myAppBarLayoutScrollingBehavior">

            <com.google.android.material.card.MaterialCardView
                style="?attr/myCardViewFullWidthStyle"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                app:contentPadding="0dp">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <com.google.android.material.tabs.TabLayout
                        android:id="@+id/tabs"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:tabGravity="fill"
                        app:tabMode="fixed" />

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="@dimen/card_content_padding">

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:focusable="true"
                            android:orientation="vertical"
                            android:visibility="@{view.customerType == CustomerType.PRIVATE ? View.VISIBLE : View.GONE}">

                            <TextView
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:layout_marginBottom="@dimen/text_vertical_spacing"
                                android:text="@string/login__title_private"
                                android:textAppearance="?attr/textAppearanceHeadline5" />

                            <TextView
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:contentDescription="@string/login__body_private_accessibility"
                                android:text="@{AccessibilityUtils.makeWordAccessible(@string/login__body_private)}" />

                        </LinearLayout>

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:focusable="true"
                            android:orientation="vertical"
                            android:visibility="@{view.customerType == CustomerType.BUSINESS ? View.VISIBLE : View.GONE}">

                            <TextView
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:layout_marginBottom="@dimen/text_vertical_spacing"
                                android:text="@string/login__title_business"
                                android:textAppearance="?attr/textAppearanceHeadline5" />

                            <TextView
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:contentDescription="@string/login__body__accessibility"
                                android:text="@{AccessibilityUtils.makeWordAccessible(@string/login__body)}" />

                        </LinearLayout>

                        <com.google.android.material.textfield.TextInputLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginStart="-4dp"
                            android:layout_marginTop="16dp"
                            android:layout_marginEnd="-4dp"
                            android:layout_marginBottom="@dimen/input_vertical_spacing"
                            android:hint="@string/login__username">

                            <com.google.android.material.textfield.TextInputEditText
                                android:id="@+id/username"
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:singleLine="true"
                                android:text="@={view.username}" />

                        </com.google.android.material.textfield.TextInputLayout>

                        <com.google.android.material.textfield.TextInputLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginStart="-4dp"
                            android:layout_marginEnd="-4dp"
                            android:hint="@string/login_password_hint">

                            <com.google.android.material.textfield.TextInputEditText
                                android:id="@+id/password"
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:inputType="textPassword"
                                android:singleLine="true"
                                android:text="@={view.password}" />
                        </com.google.android.material.textfield.TextInputLayout>

                        <com.google.android.material.button.MaterialButton
                            android:id="@+id/login_button"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginTop="@dimen/buttons_margin_top"
                            android:layout_marginBottom="@dimen/button_vertical_spacing"
                            android:onClick="@{() -> presenter.onLoginClicked(view.username, view.password)}"
                            android:text="@string/login_label" />

                        <com.google.android.material.button.MaterialButton
                            android:id="@+id/help_button"
                            style="?attr/buttonTextStyle"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:onClick="@{() -> presenter.onForgotCredentialsClicked()}"
                            android:text="@string/login_help" />
                    </LinearLayout>
                </LinearLayout>
            </com.google.android.material.card.MaterialCardView>
        </androidx.core.widget.NestedScrollView>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

Attribute/Style

<item name="myCardViewFullWidthStyle">@style/CardView.FullWidth</item>
    <style name="CardView.FullWidth" parent="Widget.MaterialComponents.CardView">
        <item name="cardCornerRadius">@dimen/card_fullwidth_corner_radius</item>
        <item name="cardElevation">@dimen/card_fullwidth_elevation</item>
        <item name="contentPadding">@dimen/card_fullwidth_content_padding</item>
        <item name="android:layout_width">@dimen/card_fullwidth_width</item>
        <item name="android:layout_marginTop">@dimen/card_fullwidth_margin_top</item>
        <item name="android:layout_marginBottom">@dimen/card_fullwidth_margin_bottom</item>
    </style>

并且系统无法找到的资源 ID #0x7f040378 似乎是 style="?attr/myCardViewFullWidthStyle" 或至少与 CardView 相关的东西,因为那是崩溃指向布局的地方。

    <com.google.android.material.card.MaterialCardView
        style="?attr/myCardViewFullWidthStyle"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        app:contentPadding="0dp">

设置

我使用属性是因为 style/theme 在单独的模块中定义并使用 material lib 1.1。它发生在带有混淆器的产品应用程序版本上。

好的,在对混淆构建进行更多调查后发现问题出在缺少自定义属性本身。

在资产管理器的以下查找过程中:

@UnsupportedAppUsage @Nullable String getResourceEntryName(@AnyRes int resId) { synchronized (this) { ensureValidLocked(); return nativeGetResourceEntryName(mObject, resId); } }

找不到自定义样式属性。 只有在混淆构建上启用开发选项“查看属性检查”时才会发生。

更新 dexguard 规则如下修复

-keepresources attr/**