当前位置: 首页 > 知识库问答 >
问题:

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

廉志强
2023-03-14

应用程序每月活跃用户超过20000人。它已经在google play上发布好几个月了。在我最近从. apk分发切换到. aab分发之后,我开始在crashlytics和google play store上收到随机崩溃。在引入崩溃的构建中没有进行其他重大更改。

崩溃发生在应用程序的第一个屏幕上,同时扩展了xml布局。讨论中的xml布局是一个简单的启动屏幕,只包含一个图像视图和一个文本视图。imageview是android。小装置。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)

导致崩溃的xml文件的一部分:

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

除了其他设备外,我还收到过谷歌Pixel和Nexus 5X的崩溃,这两款设备都没有根目录。我碰巧拥有这两台设备。我曾尝试从google play和pureapk等侧载服务将我的应用程序安装到他们身上,但我无法重现崩溃。

这个问题类似于Android应用程序捆绑介绍资源未在Android应用程序中找到崩溃,但在这个问题中,作者能够通过使用矢量绘图比较来解决他的问题。这不是我的案子。

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

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

所以,总结一下:
1。在google play
2上切换到android应用程序包分发之后,崩溃就开始出现了。应用程序在第一次尝试恢复可绘制资源时崩溃-一个简单的png图像
3。崩溃不是android版本特有的;它发生在根深蒂固和非根深蒂固的设备上
4。如果用户感染了这个漏洞,他可能会永远卡住

是什么导致了这次坠机?有解决办法吗?

==========

更新:阅读下面的答案后,我得出结论,唯一的解决方法是检测侧载安装,然后在没有任何可绘制资源或样式的情况下打开活动,并链接到Google Play和带有老式apk文件的官方网站。然后,用户可以从其他来源重新下载应用程序。

这是我用来检测应用程序是否已侧载的代码(如果应用程序中没有本机库,则可能需要删除nativelibrariesprentpart):

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{enablespilt=false}),它可以使用字符串资源,但不能使用任何可绘制的资源。

共有2个答案

鱼恩
2023-03-14

您可以通过使用com.google.android.play.core.missingsplits.MisSingSplitsDetectingApplication作为您的应用程序来解决这个问题,或者在您自己的应用程序中这样做:

class MyApplication : Application() {
    override fun onCreate() {
        if (MissingSplitsManagerFactory.create(this).disableAppIfMissingRequiredSplits()) {
            // Skip app initialization when the app is missing required splits.
            return
        }
        super.onCreate()
        // ...
    }
}

你需要google play核心依赖项来实现这一点。仅供参考:它已经被弃用了:谷歌Play protect和Android 10或更高版本的设备已经自动捕捉到缺少所需的拆分。

徐奇
2023-03-14

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

以前处理非Android应用捆绑应用的人只需传输和共享主APK。但是你的应用程序包有很多“拆分APK”,比如资源,这就是节省大小的方式。您可以在帮助页面上阅读有关此过程的所有信息。如果用户在安装主APK时没有安装正确的拆分APK,则应用程序首次尝试加载资源时将发生“未找到资源”崩溃。

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

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

 类似资料:
  • 在我的主要活动中,我附加了两个片段并使用tablayout。每当我把光变暗或者把暗变亮,我都会得到这个错误,在这里输入图像描述 错误显示在super的onCreate()中。onCreate(savedInstanceState)main活动。

  • 我一直收到同样的撞车报告,扔了一个Android。所容纳之物res.Resources$NotFoundException错误,抱怨缺少资源ID。 谁能解释一下错误是什么吗?我看到一些帖子谈到导航视图(NavigationView)是个问题。其他人提到了v21可绘制资源,但我的应用程序中没有任何v21可绘制资源。 如果你看到过回答这个问题的帖子,请告诉我。否则,我们将不胜感激! 下面是其中一个崩溃

  • 问题内容: 我正在尝试创建一个简单的手电筒应用程序,以学习android开发。我正在尝试获取它,以便当您单击灯光ImageView对象时,它会更改图像。但是现在,当调试器进入light.setImageResource()时,它崩溃。 它抛出的错误是 问题答案: 崩溃: 正如您的堆栈跟踪所说:“ java.lang。OutOfMemoryError : 未能分配51840012字节分配,其中包含4

  • 应用程序由于stacktrace的StackOverflow错误而不时崩溃(见下文)。 该错误意外地出现在各种方案中。我们无法模拟它或预测它的发生。 提前谢谢你。 Stacktrace错误(缩短版):

  • 我开发了一个React Native应用程序,当应用程序处于活动状态时,每次收到来自OneSignal的消息推送时都会崩溃。 错误是。 如果我在应用程序处于后台时收到通知,则没有问题。 这是我的身材。gradle文件: 还有我的应用/构建。gradle文件: 你知道问题来自哪里吗?