1

I am frequently getting inflate exception for android bottom navigation view on my firebase console. I have double checked my code. I made few changes but still application is crashing with inflate exception. It has no specific pattern and occurring on every make and model and also on all versions of android starting from 4 to 10. Initially i though it was due to the vectors i have used. Then I replaced all vectors with PNG but the error still persists. The reason for the error as per firebase console is resource not found exception. Caused by android.content.res.Resources$NotFoundException Resource ID #0x7f0800ac This exception is effecting 1% of user sessions. I am using bottomnavigation with android navcontroller. I am not able to reproduce it on any of the devices which was reported by firebase. I tried with AS emulator as well but the issue is not being reproduced.

Here is complete stack trace.

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{myapp.com/myapp.com.HomeActivity}: android.view.InflateException: Binary XML file line #97: Binary XML file line #97: Error inflating class com.google.android.material.bottomnavigation.BottomNavigationView
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2956)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3091)
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
       at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1843)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:6758)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)

This is on line 97 of xml file

 <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottomNav"
                style="@style/BottomNavigationView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:itemTextColor="@drawable/bottom_navigation_text_tint"
                app:labelVisibilityMode="labeled"
                app:layout_constraintBottom_toBottomOf="parent"
                app:menu="@menu/bottommenu" />

Here are rest of the layout file. This is bottom menu xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/fragHome"
        android:icon="@drawable/home"
        android:title="@string/home" />

    <item
        android:id="@+id/fragUsage"
        android:icon="@drawable/usage"
        android:title="@string/usage" />

    <item
        android:id="@+id/fragWishList"
        android:icon="@drawable/withList"
        android:title="@string/withList" />

    <item
        android:id="@+id/fragShop"
        android:icon="@drawable/cart"
        android:title="@string/shop" />
    <item
        android:id="@+id/fragMore"
        android:icon="@drawable/more"
        android:title="@string/more" />
</menu>

This is Bottom_navigation_text_tint

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_checked="true" />
    <item android:color="@color/lightGrey" />
</selector>

This is the style used on bottom navigation.

<style name="BottomNavigationView">
        <item name="itemTextAppearanceActive">
            @style/TextAppearance.BottomNavigationView.Active
        </item>
        <item name="itemTextAppearanceInactive">
            @style/TextAppearance.BottomNavigationView.Inactive
        </item>
    </style>

    <style name="TextAppearance.BottomNavigationView.Inactive">
        <item name="android:textSize">@dimen/_8sdp</item>
        <item name="fontFamily">@font/roboto_regular</item>
    </style>

    <!-- active tab icon style -->
    <style name="TextAppearance.BottomNavigationView.Active">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">@dimen/_8sdp</item>
    </style>

Update 1 Here is my home activity class

class HomeActivity : AppCompatActivity(), HasSupportFragmentInjector,
    NavigationView.OnNavigationItemSelectedListener,
    ConfirmationDialogue.OnActivateClicked, Injectable,
    DrawerLocker, DialogAccounts.OnActivateClicked, DialogAccounts.OnDismissClicked {

    private var isMaintenance: Boolean = false

    @Inject
    lateinit var notificationRepo: NotificationRepo

    private lateinit var drawerToggle: ActionBarDrawerToggle

    @Inject
    lateinit var tokenRepository: TokenRepository

    @Inject
    lateinit var hyperLinksRepository: HyperlinkRepository

    @Inject
    lateinit var remoteDataSource: RemoteDataSource

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

    override fun supportFragmentInjector() = dispatchingAndroidInjector


    private lateinit var navController: NavController
    private lateinit var bottomNav: BottomNavigationView
    private lateinit var mActionBar: View
    private lateinit var btnHamBurger: ImageButton
    private lateinit var sideNavView: NavigationView
    private lateinit var btnBell: ImageButton
    private lateinit var drawerLayout: DrawerLayout
    private lateinit var userDetails: RegistrationDetails
    private lateinit var dialogAccounts: DialogAccounts

    companion object {
        var selected = RegistrationUtility.getUserDetails()

    }

    override fun onStart() {
        super.onStart()
     }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)

        initViews()
        initEvents()

    }

    override fun onSupportNavigateUp() = navController.navigateUp()

    private fun initViews() {
        bottomNav = findViewById(R.id.bottomNav)
        mActionBar = findViewById(R.id.myActionBar)
        btnHamBurger = findViewById(R.id.btnHamBurger)
        navController = findNavController(R.id.navigationHostFragment)
        sideNavView = findViewById(R.id.nav_view)
        btnBell = findViewById(R.id.btnBell)
        drawerLayout = findViewById(R.id.drawer_layout)

        Glide.with(BaseClass.appContext).asGif().load(R.drawable.loader_png).diskCacheStrategy(
            DiskCacheStrategy.ALL
        ).into(loader_gif)
     }


    @SuppressLint("IntentReset")
    private fun initEvents() {
        onDestinationChanged()
        sideNavView.setupWithNavController(navController)
        bottomNav.setupWithNavController(navController)
        sideNavView.setNavigationItemSelectedListener(this)

        btnHamBurger.setOnClickListener {
            if (!sideNavView.isShown) {
                drawerLayout.openDrawer(GravityCompat.END)
            }
        }
        btnBell.setOnClickListener {
            navController.navigate(R.id.frag_Notif)
        }
        drawerToggle = object : ActionBarDrawerToggle(
            this,
            drawerLayout,
            null,
            R.string.empty,
            R.string.empty
        ) {

            override fun onDrawerOpened(drawerView: View) {
                super.onDrawerOpened(drawerView)
                setNavHeader()
            }
        }
        drawerToggle.isDrawerIndicatorEnabled = true
        drawerLayout.addDrawerListener(drawerToggle)
        drawerToggle.syncState()


        tvTitle.setOnClickListener {
        }
    }



    private fun onDestinationChanged() {
        navController.addOnDestinationChangedListener { _, destination, _ ->

            btnBell.visibility = View.VISIBLE
            Lingver.getInstance().setLocale(this, getLocale())
            when (destination.id) {
                R.id.fragBundles -> tvTitle.text = getString(R.string.bundles)
                //other code
            }

        }
    }



    private fun setNavHeader() {
        userDetails = RegistrationUtility.getUserDetails()
        val headerView = sideNavView.getHeaderView(0)
        val view = sideNavView.menu.findItem(R.id.nav_log_version).actionView
        val tvVersion = view.findViewById<TextView>(R.id.lblVersion)
        var currentVersion = getString(R.string.version) + " " + BuildConfig.VERSION_NAME
        if (BuildConfig.DEBUG) {
            currentVersion = currentVersion + " " + BuildConfig.FLAVOR
        }
        tvVersion.text = currentVersion
        val navUsername = headerView.findViewById(R.id.tvUserName) as TextView
        navUsername.text = userDetails.userName
        val nvMobile = headerView.findViewById(R.id.tvUserNumber) as TextView
        nvMobile.text = userDetails.mobileNumber
        val imgProfile = headerView.findViewById(R.id.ivUserImage) as ImageView
        imgProfile.setImageResource(userDetails.userAvatar ?: R.drawable.ic_av1)

    }

    override fun onBackPressed() {
        if (sideNavView.isShown) {
            drawerLayout.closeDrawer(GravityCompat.END)
        }
        if (loader_loader.isVisible) {
            loader_loader.visibility = View.GONE
        } else {
            super.onBackPressed()
        }
    }


    override fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
        var screenName = ""
        when (menuItem.itemId) {
            R.id.fragProfile -> {
                navController.popBackStack(R.id.fragHome, false)
                navController.navigate(R.id.fragProfile)
                screenName = LoggingScreens.MyProfile.screenName
            }
            // other code.
        }
        drawerLayout.closeDrawer(GravityCompat.END)
        return true
    }




    override fun setDrawerEnabled(enabled: Boolean) {
        val lockMode: Int = if (enabled) {
            DrawerLayout.LOCK_MODE_UNLOCKED
        } else {
            DrawerLayout.LOCK_MODE_LOCKED_CLOSED
        }
        drawerLayout.setDrawerLockMode(lockMode)
        drawerToggle.isDrawerIndicatorEnabled = enabled
    }




    override fun onDestroy() {
        super.onDestroy()
        Glide.get(applicationContext).clearMemory();
        thread(start = true) {
            Glide.get(this).clearDiskCache()
        }
    }



    private fun showUpdateDialog(
        title: String,
        message: String,
        cancelable: Boolean,
        buttonText: Int
    ) {
        dialogAccounts = DialogAccounts(
            this@HomeActivity,
            message,
            title,
            R.drawable.ic_av1_happy,
            this@HomeActivity,
            this@HomeActivity,
            cancelable,
            buttonText
        )
        dialogAccounts.showDialog()


    }

    override fun onActivateClicked() {
        if (!isMaintenance) {
            val intent =
                Intent(
                    Intent.ACTION_VIEW,
                    Uri.parse("market://details?id=" + applicationContext.packageName)
                )
            if (intent.resolveActivity(packageManager) != null) {
                startActivity(intent)
            }
        }
    }

    override fun onDismissClicked() {
    }




}


interface DrawerLocker {
    fun setDrawerEnabled(enabled: Boolean)
}

and this is my proguard configuration

# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class screenName to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file screenName.
#-renamesourcefileattribute SourceFile
# Application classes that will be serialized/deserialized over moshi

#project related
-keep class app.com.pk.constants
-keep class app.com.pk.service.model.** { *; }
-keep class  app.com.pk.service.database.models.** { *; }
-keep class app.com.pk.languageutility.** { *; }
-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*
-keepattributes EnclosingMethod
-keepattributes InnerClasses
-dontwarn org.xmlpull.v1.**
-dontwarn android-support-v4.**
-dontwarn  com.crashlytics.**
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
-keep public class com.google.** {*;}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8


# For OkHttp 3.x
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }

# crashlytics
-keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.**
kartoos khan
  • 409
  • 6
  • 22
  • Do you see a pattern in the devices that are affected by the issue? Like a specific brand / screen size or CPU architecture? – janavarro Mar 10 '20 at 11:51
  • Yes its mostly on samsung devices. With android version 4 to 10. All have this crash from time to time. – kartoos khan Mar 10 '20 at 12:38
  • I've faced problems like this before in a large app and the best way to solve it is to get a Samsung device and see if you can reproduce it. It can be because the ROM of samsung or the architecture of the devices, samsung has it's own CPUs. – janavarro Mar 10 '20 at 12:40
  • I've found this thread that may shed some light to your problem, it may be caused by the repackaging process. https://stackoverflow.com/questions/7619945/android-resources-not-found-on-some-devices – janavarro Mar 10 '20 at 12:43
  • Have you used Kotlin language? If yes, it can be a bug related to view cache. Please place your classes where you're trying to get @+id/bottomNav – Alex Mar 11 '20 at 21:47
  • Can you provide your proguard file content? – M D P Mar 11 '20 at 23:43
  • @Alex yes I have used kotlin. I have updated my question with proguard and home activity class – kartoos khan Mar 12 '20 at 05:32
  • I have the same issue. Can't reproduce it either on any device I have. Looks like a bug in Google Play APK generation :/ – Yev Kanivets Oct 09 '20 at 07:17
  • BTW, do you see those crashes in Google Play Developer Console? I don't and I have a theory that those crashes are coming from people, who download the app from 3rd party stores, which tries to scrap the Google Play for APKs. But those APKs are generated from bundle and not good for wide variety of devices, which people tries to download them to. – Yev Kanivets Oct 09 '20 at 07:27
  • That could be a reason, I don`t have access to Play Console, I will ask relevant team to provide play console logs, will then check and verify same. – kartoos khan Oct 11 '20 at 15:09

0 Answers0