【问题标题】:App crash on devices with ldpi screens带有 ldpi 屏幕的设备上的应用程序崩溃
【发布时间】:2013-10-20 00:09:06
【问题描述】:

我创建了一个带有图像的应用程序,并通过Android Icon Set 向导添加了它们。该向导为图像创建了 3 个版本 - mdpi、hdpi、xhdpi。

我在 google play 上发布了我的应用程序,我收到了来自具有 ldpi 屏幕的用户的崩溃报告。例外是Caused by: android.content.res.Resources$NotFoundException: File from drawable resource ID #0x7f02007f。 drawable 存在于 mdpi、hdpi 和 xhdpi 中,并且该应用程序适用于其余用户。

所以我猜问题在于它的 ldpi 版本中不存在可绘制剂量。

所以我的问题是:
1) 有什么方法可以让应用自动缩放 mdpi 可绘制对象而不是崩溃?
2) 对于支持 ldpi 屏幕,我必须将图像编辑为 ldpi 大小吗?

谢谢。

【问题讨论】:

  • 当您可能已经为一种屏幕尺寸定义了布局而错过了为 ldpi 定义它时,您会发现资源未找到

标签: android dpi android-screen-support


【解决方案1】:

这是不同密度管理的常见错误,所以这些是您问题的答案。

1.- 不,以您的资产存储方式,但是是的,“仅当您的资产位于当前密度的较低层次结构中时”,例如:如果您有可绘制的资产(默认非特定密度)和可绘制的资产-ldpi 并且您在中等密度设备中运行应用程序,操作系统将尝试将您的图像大小从 -ldpi 调整为您的密度(如果在图像中使用 dps 但会消耗内存)。操作系统处理资产的方式如下:

假设你有:

res-
    -drawable
        -icon.png
    -drawable-ldpi
        -icon.png
    -drawable-mdpi
       -icon.png

如果您在 HIGH Density 设备中运行应用程序,操作系统首先会尝试在 drawable-hdpi 中查找您的资源,但由于它不存在,它将开始沿着层次结构向下移动,直到找到它,所以在此如果它不会在 drawable-hdpi 中找到它,但会在 drawable-mdpi 中找到它并使用它来填充,一切都会好起来的,但会在内存中消耗资产中的密度差异。

现在,当操作系统向下资产文件夹层次结构并一直运行到最后并且找不到任何东西时,您会遇到确切的错误:

假设你有:

res-
    -drawable-hdpi
        -icon.png

如果您运行此应用程序,在 HIGH Desnity Device 中它将完美运行,因为会在第一次尝试中找到资产并且永远不会向下层级排序,对于 Extra High Density Device 也是如此,因为如果它在 drawable 中找不到它-xhdpi 它将在下一步中找到它,当它沿着层次结构向下移动到 drawable-hdpi 并且工作得很好,但是对于 MEDIUM Density,首先它会尝试在 drawable-mdpi 中找到它,因为它不存在,会去下来并尝试在drawable-ldpi中找到它也没有运气,所以它会进入“默认(可绘制)”,这是一个很好的做法,以包含平均大小的所有资产,至少使应用程序看起来模糊而不是崩溃,由于操作系统不会找到资产 BOOOM 没有找到资源,所以你有例外,这种机制几乎适用于 Android 中的任何资源

2.- 是的,您必须在 ldpi 中创建资源并将它们存储在 drawable-ldpi 或 drawable(默认 - 无密度)中以使其看起来不错。

所有这些信息都来自一本书,如果您仍有疑问,请在 Eclipse 中创建一个空的 Android 项目,并注意 SDK 如何在每个密度中创建一个具有特定大小的 icon_launcher.png img 来准确处理此问题.根据我的经验,我发现始终处理所有密度很有用,但更重要的是让我的所有资产在默认文件夹中具有平均密度/质量,以避免这个确切的问题,以防你忘记一个密度发展,是一种模糊的资产,而不是崩溃。

希望对您有所帮助。

问候!

【讨论】:

  • 您不需要所有 DPI 大小的可绘制对象。如果您只有一个可绘制对象,Android 会简单地放大或缩小它们。
  • 哈哈哈,这是最糟糕的做法之一,如果你不相信我,试试看,但要监控 HEAP,因为 android 会尝试调整这些图像的大小,这将消耗大量内存, OutOfMemoryErrors 会到处抛出。我在这里根据经验说话,几年前刚开始使用Android时,我曾经按照您所说的那样做,这让我看起来很糟糕:P
  • 使用可绘制文件夹的#1 目的是存储应用程序图标和其他小图像。如果由于 Android 对这些图像的(有效)缩放而出现 OutOfMemory 错误,那么您做错了。简单地提供可绘制对象的 xhdpi 版本并让系统进行缩放绝对没有错。如果您需要完美像素,您应该始终自己进行缩放,并可能在较低 DPI 的设备上进行更改,但除此之外没有任何意义。是的,我也有这方面的经验,伙计,这里没有 OutOfMemory 错误。
  • 我开始怀疑你怎么能称自己为 Android 开发者。这显然是一个需要的功能,因为它允许开发人员为不同的分辨率创建不同的位图资源——如果你想避免图像中可能的缩放伪影,这会带来很大的好处——但除此之外,绝对没有必要提供各种尺寸的drawables。这是浪费空间。 Android 的扩展开销很小。如有疑问,请查看 BitmapFactory.Options 并学习。
  • @MartinCazares:首先,res/drawable/ 相当于位图的res/drawable-mdpi/,因此两者兼有是一种浪费。其次,正如您后来在 cmets 中承认的那样,“由于操作系统不会找到资产,因此 BOOOM 没有找到资源”是不正确的。第三,“注意 SDK 如何在每个密度中创建一个具有特定大小的 icon_launcher.png img 来处理这个问题”是不正确的,因为 Eclipse 特别不打扰res/drawable-ldpi/ic_launcher.png
【解决方案2】:

有没有办法让应用自动缩放 mdpi 可绘制对象而不是崩溃?

这会自动发生,除非固件制造商(设备制造商或 ROM 模组制造商)搞砸了。

为了支持 ldpi 屏幕,我必须将图像编辑为 ldpi 大小吗?

没有。

我会在与您的生产代码库关联的R.java 中查找7f02007f,并确保它是您认为的那样。请记住,这些数字会在每次编译时重新生成。也许这是一个根本没有这个数字的可绘制资源的情况,在任何密度下,因为R.java 与实际的资源打包不同步。为避免此问题,请在制作生产 APK 的过程中进行干净构建(例如,在 Eclipse 中进行项目 > 清洁)。

【讨论】:

  • 代码存在于 R.java 中,但应用程序在 ldpi 屏幕中崩溃。它发生在非原始ROM上吗?我能用它做什么?
  • @nrofis:“它发生在非原始 ROM 上吗?” - 我不知道哪些设备会为您崩溃,所以我无法回答。 “我能用它做什么?” -- 要么提供-ldpi drawables,要么在清单中使用<compatible-screens> 来阻止分发到-ldpi 设备,或者尝试确定这个问题是否影响所有-ldpi 设备,或者只影响那些运行某些特定ROM 模块的设备.
  • 这应该是公认的答案。如果你有这样的错误,那不是因为你没有提供你的 drawable 的 ldpi 版本,这几乎肯定是因为你的 R.java 文件有问题。正如 CommonsWare 建议的那样,清理项目应该可以修复它。
猜你喜欢
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 2015-05-21
  • 2011-04-08
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 2017-05-08
相关资源
最近更新 更多