Resources$NotFoundException 无法找到 Drawable 的资源 ID #0x7f080043

Seb*_*n B 9 android android-appcompat apk

我的应用程序的用户在 Crashlytics 中遇到错误: Caused by android.content.res.Resources$NotFoundException Unable to find resource ID #0x7f080043 for a Drawable。我在我的 APK 中检查了它(在调试下),发现它与可绘制的“abc_spinner_mtrl_am_alpha”相关。我在微调器的后台使用这个可绘制对象。我不是自己创建这个可绘制对象,它来自库 appcompat-1.4.1。但在这个库中,它以多种密度等存在。有没有人遇到过类似的问题并知道它的解决方案/根本原因?

可绘制ID

Caused by android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f080043
       at android.content.res.ResourcesImpl.getResourceName(ResourcesImpl.java:253)
       at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:760)
       at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:630)
       at android.content.res.Resources.loadDrawable(Resources.java:886)
       at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:953)
       at android.content.res.TypedArray.getDrawable(TypedArray.java:928)
       at android.content.res.XResources$XTypedArray.getDrawable(XResources.java:1363)
       at android.view.View.<init>(View.java:4768)
       at android.widget.TextView.<init>(TextView.java:826)
       at android.widget.TextView.<init>(TextView.java:820)
       at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:108)
       at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
       at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:201)
       at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:121)
       at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1566)
       at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1617)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
       at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:416)
       at android.widget.ArrayAdapter.getView(ArrayAdapter.java:407)
       at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:204)
       at android.widget.Spinner.onMeasure(Spinner.java:602)
       at androidx.appcompat.widget.AppCompatSpinner.onMeasure(AppCompatSpinner.java:438)
       at android.view.View.measure(View.java:22071)
       at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:372)
       at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
       at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
       at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:496)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
       at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
       at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at com.android.internal.policy.DecorView.onMeasure(DecorView.java:724)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2422)
       at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1504)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1761)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
       at android.view.Choreographer.doCallbacks(Choreographer.java:723)
       at android.view.Choreographer.doFrame(Choreographer.java:658)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
       at android.os.Handler.handleCallback(Handler.java:790)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6494)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
Run Code Online (Sandbox Code Playgroud)

Cri*_*ert 11

这可能是由于资源在默认文件夹中没有文件(仅在 xxhdpi 和 ldrtl-xxhdpi 文件夹中)。应用程序崩溃的手机可能具有不同的密度,并且该应用程序作为 Android 应用程序包 (.aab) 进行部署/安装,这使得 google play 能够删除它认为不必要的资源(例如此资源不需要该设备具有不同的密度)以减小捆绑尺寸。

解决方法是将该资源复制到您的项目中(最好使用不同的名称以防止其他问题)并将其直接放置在 resources/drawables 文件夹下或根据其尺寸(如果有)放置在所有drawables 文件夹中。这应该确保它存在于所有应用程序包中,无论其目标屏幕密度如何。


回复评论:

是的,这确实是一个错误,尽管 android gradle 插件可能在构建日志中记录了有关未为所有密度提供相关可绘制对象的错误/警告。规则/建议是在drawables文件夹中有一个drawable,或者在每个mdpi、hdpi、xhdpi、xxhdpi文件夹中有副本(按比例大小)。在此支持库的情况下,它仅提供 xxhdpi 版本,并且可能在运行时该库仅在 xxhdpi 设备上使用可绘制对象。这是一个 9 补丁图像,因此可以安全地将其复制到绘图,而不会损失质量。

理想情况下,大多数图形将由矢量可绘制对象组成,这些矢量可绘制对象可以/应该放置在可绘制对象中,而不必担心设备密度。请注意矢量可绘制对象的宽度和高度属性,因为这些属性将决定它将在屏幕上显示的大小,如果缺少这些属性,则将从视图的大小推断出来(wrap_content 可能会导致可绘制对象不可见)。使用 aab 格式部署应用程序时,请务必小心地为​​所有设备配置(密度、屏幕方向等)提供资源,因为设备下载的最终存档可能仅包含其密度和/或默认配置的资源(绘图、值)。在过去(使用 apk 格式),当没有适合其密度的可绘制对象和默认的可绘制对象时,Android 运行时会尝试缩小更高密度的可绘制对象。现在(使用 aab)更高密度的可绘制对象被排除在捆绑包之外,这不再可能。

我还认为不直接使用第三方库中的资源(例如从布局中引用它们)是一个很好的做法,因为它们可以轻松重命名、移动或删除(尤其是动态 gradle 依赖项)以及复杂/不确定的 android在发布的应用程序在用户设备上崩溃之前,它可能不会变得明显。如果您确实需要库中的某些资源,最好将其复制到您的项目中。一般来说,尽可能少地依赖您无法控制的事情会更安全。