material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.14k stars 3.05k forks source link

[AppBarLayout] App crashes with UnsupportedOperationException and InflateException #3666

Closed patrickfrei closed 8 months ago

patrickfrei commented 8 months ago

Description: I've updated Material Design from 1.11.0-alpha03 to 1.11.0-beta01. Since then, my app crashes shortly after startup with below exception (taken from the pre-launch report on Google Play Console). If I go back to 1.11.0-alpha03 the issue disappears. So, something has changed in the latest M3 version that causes now that issue.

The problem is that I cannot debug the issue as only one test device on Google Play Console is affected: "google Redfin 64-bit only" (Pixel 5) in combination with "Android 14 (SDK 34)". I cannot reproduce the crash on another emulator running on my computer with the same API level or lower.

To me it seems as if the system is looking at startup for an particular attribute in a Material theme in combination with AppBar and as this attribute is not found, the app crashes.

Do you have any idea where I could start to investigate?

Exception java.lang.RuntimeException: Unable to start activity ComponentInfo{ch.patrickfrei.MyApp/ch.patrickfrei.MyApp.MainActivity}: android.view.InflateException: Binary XML file line #18 in ch.patrickfrei.MyApp:layout/activity_main: Binary XML file line #18 in ch.patrickfrei.MyApp:layout/activity_main: Error inflating class com.google.android.material.appbar.AppBarLayout
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3781)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3921)
  at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:103)
  at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:139)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:96)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2442)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:205)
  at android.os.Looper.loop (Looper.java:294)
  at android.app.ActivityThread.main (ActivityThread.java:8170)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:552)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:971)
Caused by android.view.InflateException: Binary XML file line #18 in ch.patrickfrei.MyApp:layout/activity_main: Binary XML file line #18 in ch.patrickfrei.MyApp:layout/activity_main: Error inflating class com.google.android.material.appbar.AppBarLayout
Caused by: android.view.InflateException: Binary XML file line #18 in ch.patrickfrei.MyApp:layout/activity_main: Error inflating class com.google.android.material.appbar.AppBarLayout
Caused by: java.lang.reflect.InvocationTargetException
  at java.lang.reflect.Constructor.newInstance0
  at java.lang.reflect.Constructor.newInstance (Constructor.java:343)
  at android.view.LayoutInflater.createView (LayoutInflater.java:866)
  at android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:1018)
  at android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:973)
  at android.view.LayoutInflater.rInflate (LayoutInflater.java:1135)
  at android.view.LayoutInflater.rInflateChildren (LayoutInflater.java:1096)
  at android.view.LayoutInflater.inflate (LayoutInflater.java:694)
  at android.view.LayoutInflater.inflate (LayoutInflater.java:538)
  at android.view.LayoutInflater.inflate (LayoutInflater.java:485)
  at androidx.appcompat.app.AppCompatDelegateImpl.setContentView (AppCompatDelegateImpl.java:775)
  at androidx.appcompat.app.AppCompatActivity.setContentView (AppCompatActivity.java:197)
  at ch.patrickfrei.MyApp.MainActivity.initialize (MainActivity.java:159)
  at ch.patrickfrei.MyApp.MainActivity.onRequestPermissionsResult (MainActivity.java:639)
  at ch.patrickfrei.MyApp.MainActivity.checkPermissions (MainActivity.java:613)
  at ch.patrickfrei.MyApp.MainActivity.onCreate (MainActivity.java:122)
  at android.app.Activity.performCreate (Activity.java:8595)
  at android.app.Activity.performCreate (Activity.java:8573)
  at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1456)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3763)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3921)
  at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:103)
  at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:139)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:96)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2442)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:205)
  at android.os.Looper.loop (Looper.java:294)
  at android.app.ActivityThread.main (ActivityThread.java:8170)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:552)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:971)
Caused by java.lang.UnsupportedOperationException: Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f04013c a=10}, theme={InheritanceMap=[id=0x7f1402e1ch.patrickfrei.MyApp:style/ThemeOverlay.Material3.DynamicColors.Light], Themes=[ch.patrickfrei.MyApp:style/ThemeOverlay.Material3.DynamicColors.Light, forced, ch.patrickfrei.MyApp:style/AppTheme.NoActionBar, forced, ch.patrickfrei.MyApp:style/Theme.AppCompat.Empty, forced, android:style/Theme.DeviceDefault.Light.DarkActionBar, forced]}
  at android.content.res.TypedArray.getDrawableForDensity (TypedArray.java:1007)
  at android.content.res.TypedArray.getDrawable (TypedArray.java:991)
  at android.view.View.<init> (View.java:5706)
  at android.view.ViewGroup.<init> (ViewGroup.java:704)
  at android.widget.LinearLayout.<init> (LinearLayout.java:254)
  at android.widget.LinearLayout.<init> (LinearLayout.java:250)
  at com.google.android.material.appbar.AppBarLayout.<init> (AppBarLayout.java:237)
  at com.google.android.material.appbar.AppBarLayout.<init> (AppBarLayout.java:233)

Expected behavior: No crash when moving to 1.11.0-beta01

Source code: See above code.

Android API version: Android API 14

Material Library version: 1.11.0-beta01

Device: google Redfin 64-bit only

imhappi commented 8 months ago

Hi @patrickfrei ! Unfortunately I'm unable to repro this crash on our test app on a pixel 5 API 34 emulator :/

The logs do seem to indicate that this is an issue with theming/styling; based on the changes included from 1.11.0-alpha03 to 1.11.0-beta01, it looks like the only attribute-related changes dealing with the top app bar may have been related to color. Is there any custom styling in your app?

patrickfrei commented 8 months ago

Many thanks for your answer. Yes, I've some custom styling in my app. Below the according styles. I've customized them by using the Material Theme Builder: https://m3.material.io/theme-builder#/custom

Yes, it's very strange... I can also not reproduce the issue on the Android studio emulators but just on the one on the Google Play Console.

In the AndroidManifest.xml, I call MainActivity through "@style/AppTheme.NoActionBar".

themes.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Base application theme -->
    <style name="AppTheme" parent="AppTheme.Base" />
    <style name="AppTheme.Base" parent="Theme.Material3.Light">
        <!-- Base M3 colors -->
        <item name="colorPrimary">@color/md_theme_primary</item>
        <item name="colorOnPrimary">@color/md_theme_onPrimary</item>
        <item name="colorPrimaryContainer">@color/md_theme_primaryContainer</item>
        <item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer</item>
        <item name="colorSecondary">@color/md_theme_secondary</item>
        <item name="colorOnSecondary">@color/md_theme_onSecondary</item>
        <item name="colorSecondaryContainer">@color/md_theme_secondaryContainer</item>
        <item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer</item>
        <item name="colorTertiary">@color/md_theme_tertiary</item>
        <item name="colorOnTertiary">@color/md_theme_onTertiary</item>
        <item name="colorTertiaryContainer">@color/md_theme_tertiaryContainer</item>
        <item name="colorOnTertiaryContainer">@color/md_theme_onTertiaryContainer</item>
        <item name="colorError">@color/md_theme_error</item>
        <item name="colorErrorContainer">@color/md_theme_errorContainer</item>
        <item name="colorOnError">@color/md_theme_onError</item>
        <item name="colorOnErrorContainer">@color/md_theme_onErrorContainer</item>
        <item name="android:colorBackground">@color/md_theme_background</item>
        <item name="colorOnBackground">@color/md_theme_onBackground</item>
        <item name="colorSurface">@color/md_theme_surface</item>
        <item name="colorOnSurface">@color/md_theme_onSurface</item>
        <item name="colorSurfaceVariant">@color/md_theme_surfaceVariant</item>
        <item name="colorOnSurfaceVariant">@color/md_theme_onSurfaceVariant</item>
        <item name="colorOutline">@color/md_theme_outline</item>
        <item name="colorOnSurfaceInverse">@color/md_theme_inverseOnSurface</item>
        <item name="colorSurfaceInverse">@color/md_theme_inverseSurface</item>
        <item name="colorPrimaryInverse">@color/md_theme_inversePrimary</item>
        <!-- Snackbar rounded corners -->
        <item name="snackbarStyle">@style/Widget.App.Snackbar</item>
    </style>

    <!-- NoActionBar override -->
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <!-- Snackbar rounded corners -->
    <style name="Widget.App.Snackbar" parent="Widget.Material3.Snackbar">
        <item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Full</item>
    </style>
</resources>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorFrameLayout">#CCFFFFFF</color>
    <color name="colorStatusBar">#00677E</color>
    <color name="colorOldNavigationBar">#44000000</color>

    <color name="seed">#00677E</color>
    <color name="md_theme_primary">#00677E</color>
    <color name="md_theme_onPrimary">#FFFFFF</color>
    <color name="md_theme_primaryContainer">#B5EBFF</color>
    <color name="md_theme_onPrimaryContainer">#001F28</color>
    <color name="md_theme_secondary">#4C626A</color>
    <color name="md_theme_onSecondary">#FFFFFF</color>
    <color name="md_theme_secondaryContainer">#CFE6F0</color>
    <color name="md_theme_onSecondaryContainer">#071E26</color>
    <color name="md_theme_tertiary">#595C7E</color>
    <color name="md_theme_onTertiary">#FFFFFF</color>
    <color name="md_theme_tertiaryContainer">#E0E0FF</color>
    <color name="md_theme_onTertiaryContainer">#161937</color>
    <color name="md_theme_error">#BA1A1A</color>
    <color name="md_theme_errorContainer">#FFDAD6</color>
    <color name="md_theme_onError">#FFFFFF</color>
    <color name="md_theme_onErrorContainer">#410002</color>
    <color name="md_theme_background">#FBFCFE</color>
    <color name="md_theme_onBackground">#191C1D</color>
    <color name="md_theme_surface">#FBFCFE</color>
    <color name="md_theme_onSurface">#191C1D</color>
    <color name="md_theme_surfaceVariant">#DBE4E8</color>
    <color name="md_theme_onSurfaceVariant">#40484C</color>
    <color name="md_theme_outline">#70787C</color>
    <color name="md_theme_inverseOnSurface">#EFF1F2</color>
    <color name="md_theme_inverseSurface">#2E3132</color>
    <color name="md_theme_inversePrimary">#5BD5FA</color>
    <color name="md_theme_shadow">#000000</color>
    <color name="md_theme_surfaceTint">#00677E</color>
    <color name="md_theme_outlineVariant">#BFC8CC</color>
    <color name="md_theme_scrim">#000000</color>
</resources>

themes.xml in "values-v29" with some overrides

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- Base application theme -->
    <style name="AppTheme" parent="AppTheme.Base">
        <!-- Status / navigation bar -->
        <!-- Navigation bar is auto-semi-transparent as of API 29 -->
        <item name="android:windowLightStatusBar">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <!-- Override for old AlertDialog (non-M3) in the preference settings -->
        <item name="alertDialogTheme">@style/AppTheme.OldAlertDialog</item>
    </style>

    <!-- Override for old AlertDialog (non-M3) in the preference settings -->
    <style name="AppTheme.OldAlertDialog" parent="ThemeOverlay.Material3.MaterialAlertDialog">
        <item name="android:windowBackground">@drawable/bg_oldalertdialogv21</item>
        <item name="android:layout">@layout/m3_alert_dialog</item>
    </style>
</resources>
imhappi commented 8 months ago

Hi @patrickfrei ! Do you know what version of Android U the play console emulator is running? For API >=34, dynamic colours are mapped to the android sysUI color roles and there is an issue on Android U beta2 and earlier builds. That particular device may have an older version of U

patrickfrei commented 8 months ago

Hi @imhappi , oh I see... well, according to the info on the Play console, I can see the following parameters for that particular device ("Google Redfin 64-bit only"):

  1. Android 14 (SDK 34)
  2. Release version: 13
  3. SDK version: 33
  4. Build number: 10836537

I think that your explanation is probably the solution to that issue. It might also explain why we cannot reproduce the crash on the other emulators. Because at least abovementioned info from bullet point 1 in combination with bullet points 3&4 does not match.

Does that discrepancy mean that the device is indeed running a beta release of Android 14?

imhappi commented 8 months ago

I'm not sure why that discrepancy exists; will look into it to confirm if that device is on an older version of Android 14

kitfist0 commented 8 months ago

Hello! I had a similar problem after updating. I'm using PreferenceFragment with AppBarLayout.

Some code

styles.xml

<style name="ThemeOverlay.MyApp.Preference" parent="PreferenceThemeOverlay">
    <item name="android:layout">@layout/base_preference_layout</item>
</style>

base_preference_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/base_settings_app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundTint="?colorPrimaryContainer"
        android:fitsSystemWindows="true">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/base_settings_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            app:navigationIcon="@drawable/vd_round_arrow_back" />

    </com.google.android.material.appbar.AppBarLayout>

    <!--Android Studio says the new id requires API 24, but it also works on older APIs-->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@android:id/list_container" />

</LinearLayout>

BasePrefFragment.kt

abstract class BasePrefFragment : PreferenceFragmentCompat() {

    // ...

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = super.onCreateView(inflater, container, savedInstanceState)
        val toolbar = view.findViewById(R.id.base_settings_toolbar)
        toolbar.setTitle(toolbarTitleRes)
        setDivider(ColorDrawable(Color.TRANSPARENT))
        setDividerHeight(0)
        return view
    }
}

There were no problems with this code before updating the library to version 1.11.0-beta01.

Pre-launch report

Device(s) with issues Google Redfin 64-bit only (redfin_beta_64) - Android 14

Exceptions java.lang.NullPointerException: findViewById(...) must not be null

Crashlytics

This issue has 12 crash events affecting 9 users.

Stack trace

Fatal Exception: java.lang.NullPointerException: findViewById(...) must not be null
       at my.app.ui.base.fragment.BasePrefFragment.onCreateView(BasePrefFragment.kt:42)
       at androidx.fragment.app.Fragment.performCreateView(Fragment.java:3114)
       at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:557)
       at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272)
       at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
       at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455)
       at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034)
       at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2945)
       at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3148)
       at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:588)
       at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272)
       at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
       at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455)
       at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034)
       at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2952)
       at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263)
       at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:350)
       at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:251)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1512)
       at android.app.Activity.performStart(Activity.java:8353)
       at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3776)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:223)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:203)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:175)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:99)
       at android.app.ClientTransactionHandler.executeTransaction(ClientTransactionHandler.java:61)
       at android.app.ActivityThread.handleRelaunchActivityLocally(ActivityThread.java:5837)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2384)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:201)
       at android.os.Looper.loop(Looper.java:288)
       at android.app.ActivityThread.main(ActivityThread.java:8046)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:703)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)

Operating systems

patrickfrei commented 8 months ago

@imhappi , thank you, yes it would be great if you can have a look at this issue. I'm unsure if I can upgrade to beta01 with just having very few devices running Android 14 Beta impacted or if much more users will be impacted. Maybe, it's related to commit b5d6f1a ([ActionBar] Removed layered drawable for the background after tonal surface color)?

patrickfrei commented 8 months ago

@imhappi , I've just reversed commit b5d6f1a and recompiled the code. However, the issue persists, so it must be caused by something else

imhappi commented 8 months ago

Hi @patrickfrei , since this issue is only occurring on that device and it has that discrepancy in specs, I still suspect that it's due to the device being on an earlier version of Android U beta. I've reached out to folks on the appropriate channels to confirm! I'll update this thread once I get a response

imhappi commented 8 months ago

Hi @patrickfrei ! I've gotten confirmation that the device you saw the crash on was on Android U beta2, so unfortunately the crash is a known issue for that version. It is no longer an issue on beta3 and later, so you can consider this a non-issue; I'll request that that device gets updated to a later version of Android U

patrickfrei commented 8 months ago

@imhappi , many thanks for confirming that this is a non-issue and for requesting that device to be updated to a later Android U version.