代码之家  ›  专栏  ›  技术社区  ›  Alexey

在切换到android应用程序包分发后,应用程序有时会崩溃,资源为$NotFoundException

  •  13
  • Alexey  · 技术社区  · 6 年前

    该应用每月有超过20000名活跃用户。 在我最近从.apk的发行版切换到.aab的发行版之后,我开始在crashlytics和googleplay商店上收到随机崩溃的消息。在导致崩溃的构建中没有进行其他重大更改。

    崩溃发生在应用程序的第一个屏幕上,同时膨胀xml布局。所讨论的xml布局是一个简单的启动屏幕,它只包含一个图像视图和一个文本视图。imageview是android.widget.imageview,不是compat版本,它显示png图像,而不是矢量图像。图像存在于所有可绘制文件夹变体中:可绘制、可绘制mdpi、…、可绘制xxxhdpi。

    Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.company/com.company.ui.splash.SplashActivity}: android.view.InflateException: Binary XML file line #14: Binary XML file line #14: Error inflating class ImageView
              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
              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:1808)
              at android.os.Handler.dispatchMessage(Handler.java:106)
              at android.os.Looper.loop(Looper.java:193)
              at android.app.ActivityThread.main(ActivityThread.java:6669)
              at java.lang.reflect.Method.invoke(Method.java)
              at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    
       Caused by android.view.InflateException: Binary XML file line #14: Binary XML file line #14: Error inflating class ImageView
    
    
       Caused by android.view.InflateException: Binary XML file line #14: Error inflating class ImageView
    
    
       Caused by android.content.res.Resources$NotFoundException: Drawable (missing name) with resource ID #0x7f0800b2
    
    
       Caused by android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f0800b2
              at android.content.res.ResourcesImpl.getResourceName(ResourcesImpl.java:255)
              at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:785)
              at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:631)
              at android.content.res.Resources.loadDrawable(Resources.java:897)
              at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:955)
              at android.content.res.TypedArray.getDrawable(TypedArray.java:930)
              at android.widget.ImageView.<init>(ImageView.java:189)
              at android.widget.ImageView.<init>(ImageView.java:172)
              at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:71)
              at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:67)
              at android.support.v7.app.AppCompatViewInflater.createImageView(AppCompatViewInflater.java:181)
              at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:105)
              at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1035)
              at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1092)
              at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
              at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
              at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
              at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
              at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
              at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
              at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
              at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287)
              at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139)
              at com.company.ui.splash.SplashActivity.onCreate(SplashActivity.java:58)
              at android.app.Activity.performCreate(Activity.java:7136)
              at android.app.Activity.performCreate(Activity.java:7127)
              at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
              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:1808)
              at android.os.Handler.dispatchMessage(Handler.java:106)
              at android.os.Looper.loop(Looper.java:193)
              at android.app.ActivityThread.main(ActivityThread.java:6669)
              at java.lang.reflect.Method.invoke(Method.java)
              at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/center"
        android:layout_centerHorizontal="true"
        android:src="@drawable/logo" />
    

    崩溃发生在所有android版本上,从4.1.2到9.0。

    Android App Bundle introduces Resource Not found crash in Android app 但在这个问题上,作者使用了向量绘制的compat来解决自己的问题。这不是我的案子。

    似乎整个资源文件夹不知何故从apk中丢失了,尽管测试这个假设很困难。我无法重现这个问题,所以我必须重新分发应用程序,并等待几天,看看崩溃发生了什么变化,我宁愿不做现场用户测试。

    当这个错误发生时,它通常会在同一个设备上连续发生好几次,这让我相信,得到这个错误的用户永远无法启动这个应用程序。另外,我知道一些以前使用过该应用程序的用户已经不能再使用它了。

    所以,总结一下:

    2应用程序在第一次尝试恢复可绘制资源(一个简单的png图像)时崩溃
    三。崩溃不是特定于android版本的;它发生在根设备和非根设备上

    是什么导致了这次车祸?有解决办法吗?

    ==========

    在阅读了下面的答案后,我得出结论,唯一的解决方法是检测侧载安装,然后打开活动,没有任何可绘制的资源或风格的链接到谷歌播放和官方网站与旧的学校apk文件。然后用户可以从另一个来源重新下载应用程序。

    这是我用来检测应用程序是否被侧载的代码(您可能需要删除) nativeLibrariesPresent 部分(如果应用程序中没有本机库):

    private fun isValidInstallation(): Boolean {
        var resourcesPresent: Boolean
        try {
            // Any drawable id will suffice
            val logo = ResourcesCompat.getDrawable(resources, R.drawable.logo_white, null)
            resourcesPresent = logo != null
        } catch (e: Exception) {
            resourcesPresent = false
        }
    
        if (!resourcesPresent) {
            Timber.e("No drawable resources detected inside app")
        }
    
        var nativeLibrariesPresent: Boolean
        try {
            val nativeLibraryDir = File(applicationInfo.nativeLibraryDir)
            val primaryNativeLibraries = nativeLibraryDir.list()
            nativeLibrariesPresent = primaryNativeLibraries.isNotEmpty()
        } catch (e: Exception) {
            nativeLibrariesPresent = false
        }
    
        if (!nativeLibrariesPresent) {
            Timber.e("No native libraries detected inside app")
        }
    
        return resourcesPresent && nativeLibrariesPresent
    }
    

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        if (!isValidInstallation()) {
            val intent = Intent(this, InvalidInstallationActivity::class.java)
            startActivity(intent)
            finish()
            return
        }
    
        setContentView(R.layout.activity_main)
        ...
    

    InvalidInstallationActivity可以使用xml布局,如果不按语言拆分aab,它可以使用字符串资源( language { enableSplit = false } ),但它不能使用任何可提取的资源。

    1 回复  |  直到 6 年前
        1
  •  34
  •   Nick Fortescue    6 年前

    这几乎可以肯定是用户共享应用程序,或者通过P2P共享程序,或者将APK上传到web,然后其他用户从web下载和安装。

    on the help page . 如果用户在安装主APK时没有安装正确的拆分APK,那么应用程序第一次尝试加载资源时将发生“资源未找到”崩溃。

    如果你想支持用户侧载你的应用程序和只是主APK你可以尝试检测这种情况,并显示一条消息给用户(不使用任何资源),说“请安装从谷歌播放”。或者你可以决定不支持以这种方式共享apk的用户。

    我怀疑从长远来看,网站和P2P共享程序将更好地正确地共享这些apk,所以我不会花太长时间担心它。