App sometimes crashes with Resources$NotFoundException after switching to android app bundle distribution(切换到 Android 应用程序包分发后,应用程序有时会因 Resources$NotFoundException 而崩溃)
问题描述
应用每月有超过 20000 名活跃用户.它已经在 google play 上发布了几个月.在我最近从使用 .apk 的分发切换到使用 .aab 的分发后,我开始在 crashlytics 和 google play store 上收到随机崩溃.在引入崩溃的构建中没有进行其他重大更改.
App has over 20000 monthly active users. It's been available on google play for months. After I've recently switched from distribution with .apk to distribution with .aab, I've started receiving random crashes on crashlytics and google play store. No other significant changes were made in the build that introduced the crashes.
崩溃发生在应用程序的第一个屏幕上,同时扩展了 xml 布局.有问题的 xml 布局是一个简单的初始屏幕,仅包含一个图像视图和一个文本视图.imageview 是 android.widget.ImageView,不是兼容版本,它显示 png 图像,而不是矢量图像.该图像存在于所有可绘制文件夹变体中:drawable、drawable-mdpi、...、drawable-xxxhdpi.
The crash happens on the very first screen of the app, while inflating xml layout. The xml layout in question is a simple splash screen that only contains one image view and one textview. The imageview is android.widget.ImageView, not compat version, and it displays png image, not a vector image. The image is present in all drawable folder variations: drawable, drawable-mdpi, ..., drawable-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文件:
Part of xml file that causes the crash:
<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.
The crash happens on all android versions, from 4.1.2 up to 9.0.
除了其他设备外,我还收到了来自 Google Pixel 和 Nexus 5X 的崩溃,这两个设备均未获得 root 权限.我碰巧拥有这两种设备.我尝试通过 google play 和侧载服务(如 pureapk)在它们上安装我的应用,但我无法重现崩溃.
Aside from other devices, I've also received crashes from Google Pixel and Nexus 5X, both non-rooted. I happen to own both devices. I've tried installing my app on them from google play and from sideloading services such as pureapk, but I wasn't able to reproduce the crash.
问题类似于Android AppBundle 引入了 Resource Not found crash in Android app ,但是在那个问题中,作者能够通过使用矢量 drawable compat 解决他的问题.这不是我的情况.
The question is similar to Android App Bundle introduces Resource Not found crash in Android app , but in that question, author was able to solve his problems by using vector drawable compat. This is not my case.
似乎 apk 中缺少整个资源文件夹,尽管很难测试这个假设.我无法重现该问题,因此我将重新发布该应用程序并等待几天看看崩溃发生了什么变化,我宁愿不对实时用户进行测试.
It appears that the entire resource folder is missing from the apk somehow, although testing this assumption is hard. I cannot reproduce the issue so I'll have o re-destribute the app and wait for a couple of days to see how the crash has changed, and I'd rather not do testing on live users.
当此错误发生时,通常会在同一设备上连续多次发生,这使我相信遇到此错误的用户永远无法启动该应用程序.另外,我知道一些以前使用该应用程序的用户不能再使用它了.
When this bug happens, it usually happens several times in the row for the same devices, which leads me to believe that users who get this bug cannot ever launch the app. Also, I know that some of the users who previously used the app cannot use it anymore.
所以,总结一下:
1. 在google play上切换到android应用程序包分发后立即开始出现崩溃
2. 应用程序在首次尝试恢复可绘制资源时崩溃 - 一个简单的 png 图像
3.崩溃不是android-version特定的;它发生在有根和无根设备上
4.如果用户遇到这个bug,他可能会永远卡住
So, to sum this up:
1. Crash started to appear right after switching to android application bundle distribution on google play
2. App crashes on its first attempt to recover drawable resource - a simple png image
3. The crash is not android-version specific; it happens on both rooted and non-rooted devices
4. If the user gets this bug, he's probably stuck forever
是什么导致了这个崩溃?有解决办法吗?
What is causing this crash? Is there a workaround?
===========
==========
更新:阅读下面的答案后,我得出的结论是,唯一的解决方法是检测侧载安装,然后在没有任何可绘制资源或样式的情况下打开活动,并带有指向 Google Play 和带有旧的官方网站的链接-学校 apk 文件.然后用户可以从其他来源重新下载应用程序.
Update: After reading the answer below I've concluded that the only workaround is to detect sideload installation and then open activity without any drawable resources or styles with links to Google Play and official site with old-school apk file. The user can then re-download app from another source.
这是我用来检测应用程序是否被侧载的代码(如果您的应用程序中没有本机库,您可能需要删除 nativeLibrariesPresent
部分):
This is the code I use to detect if app was sideloaded (you might need to remove nativeLibrariesPresent
part if there are no native libraries in your app):
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
}
在您在主要活动中执行任何操作之前,您需要开始替代活动:
You'll want to start alternative activity before you do anything inside your main activity:
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 }
)它可以使用字符串资源,但它不能使用任何可绘制资源.
InvalidInstallationActivity can use xml layout and it can use string resources if you don't split your aab by language (language { enableSplit = false }
), but it cannot use any drawable resources.
推荐答案
这几乎可以肯定是用户通过 P2P 共享程序共享应用程序,或者将 APK 上传到网络,然后其他用户从网络下载和安装.
This is almost certainly users sharing the app, either via P2P sharing programs, or uploading the APK to the web then other users downloading and installing from the web.
人们习惯于处理非 Android App Bundle 应用程序只是转移和共享主 APK.但是您的 App bundle 应用程序有很多用于资源之类的拆分 APK",这就是节省大小的方式.您可以在帮助页面上阅读有关此过程的所有信息.如果用户在安装主 APK 时未安装正确的拆分 APK,则应用第一次尝试加载资源时会发生找不到资源"崩溃.
People used to dealing with non Android App Bundle apps just transfer and share the main APK. But your App bundle app has lots of "split APKs" for things like the resources, that is how the size saving happens. You can read all about this process on the help page. If a user installs the main APK without installing the right split APKs, then a "Resources Not found" crash will occur the first time the app tries to load a resource.
如果您想支持用户侧载您的应用和仅主 APK,您可以尝试检测这种情况并向用户显示一条消息(不使用任何资源),上面写着请从 Google Play 安装".或者您可以决定不支持以这种方式共享 APK 的用户.
If you want to support users sideloading your app and just the main APK you could try to detect this situation and display a message to the user (without using any resources) that says "Please install from Google Play". Or you could just decide you aren't going to support users who share APKs in this way.
我怀疑从长远来看,网站和 P2P 共享程序会更好地正确共享此类 APK,所以我不会花太长时间担心它.
I suspect in the long run the websites and P2P sharing programs will get better at sharing such APKs properly, so I wouldn't spend too long worrying about it.
这篇关于切换到 Android 应用程序包分发后,应用程序有时会因 Resources$NotFoundException 而崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:切换到 Android 应用程序包分发后,应用程序有时会因 Resources$NotFoundException 而崩溃
基础教程推荐
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01