0

I created an app with images, and I added them via Android Icon Set wizard. The wizard created 3 versions for the images - mdpi, hdpi, xhdpi.

I published my app on google play, and I got a crash reports from users that have ldpi screen. The exception was Caused by: android.content.res.Resources$NotFoundException: File from drawable resource ID #0x7f02007f. The drawable was exists in mdpi, hdpi and xhdpi and the app worked to the rest of the users.

So I guess that the problem was that the drawable dose not exists in its ldpi version.

So my questions are:
1) Is there any way to say to the app to auto scale the mdpi drawables instead of crashing?
2) For support ldpi screens, must I edit the images to ldpi size?

Thanks.

nrofis
  • 8,975
  • 14
  • 58
  • 113

2 Answers2

1

This is a common error of different densities management, so these are the answers to your questions.

1.- No, in the way your assets are stored but Yes, "ONLY if your asset is in a lower hierarchy of your current density" for example: If you have assets in drawable(default non specific density) and drawable-ldpi AND you run the app in a Medium Density Device, the OS will try to resize your Images from -ldpi to your density (if using dps in the Image but will cost memory). The way the OS handles the Assets is the following:

Lets say you have:

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

If you are running an app in a HIGH Density device the OS first will try to find your asset in drawable-hdpi, but since it doesn't exist it will start going down the hierarchy until it finds it, so in this case it will not find it in drawable-hdpi but will find it in drawable-mdpi and will use that one to populate, everything will be fine but will cost in memory the difference of densities in the assets.

Now the exact error you have comes to play when the OS goes down the assets folder hierarchy and goes until the end and do not find anything for example:

Lets say you have:

res-
    -drawable-hdpi
        -icon.png

If you run this app, in HIGH Desnity Device it will run perfect, because will find the asset in the first try and will never go down the hierarchy, same case for Extra High Density Device because if it doesnt find it in drawable-xhdpi it will find it in the next step when going down the hierarchy to drawable-hdpi and will work just fine, but for MEDIUM Density, however, first it will try to find it in drawable-mdpi since its not there, will go down and try to find it in drawable-ldpi no luck either so it will go to the "default (drawable)" which is a good practice to contain all the assets in an average size to at least make the app look blurry than crashing, since the OS will not find the Asset either BOOOM no resource found, there you have your exception, this mechanism applies for pretty much any resource in Android

2.- YES, you must create your assets in ldpi and store them either in drawable-ldpi or drawable(default - no density) in order to make it look good.

All this information has been taken out of a book and if you still have doubts, create an empty Android Project in Eclipse and notice how the SDK creates one icon_launcher.png img in each density with a specific size to handle exactly this issue. As a recommendation in my experience I've found useful to always take care of all the densities, but more important having all my assets with an average density/quality in the default folder to avoid this exact issue in case you could forget one density during development, is better a blurry asset than a crash.

Hope this Helps.

Regards!

Martin Cazares
  • 13,637
  • 10
  • 47
  • 54
  • 1
    You do NOT need drawables in sizes for all DPIs. Android will simply up- or downscale them, if you've only got a single drawable. – Michell Bak Oct 19 '13 at 15:46
  • hahaha, that's one of the worse practices, if you don't belive me, give it a try but monitor the HEAP, since android will try to resize those images it will cost a stupid amount of memory, OutOfMemoryErrors will be thrown all over the place. I'm talking by experience here, I used to do what your saying couple of years back when just started in Android, made me look really bad :P – Martin Cazares Oct 19 '13 at 15:47
  • 1
    The #1 purpose for using the drawable folders is to store application icons and other small images. If you're getting OutOfMemory errors due to Android's (effective) scaling of those images, you're doing it wrong. There's absolutely nothing wrong in simply providing a xhdpi version of your drawables, and let the system do the scaling. If you need pixel perfection, you should always do the scaling yourself and possibly make changes on lower DPI devices, but other than that there's no point in doing it. And yeah, I've got experience with that as well, buddy, and no OutOfMemory errors here. – Michell Bak Oct 19 '13 at 15:50
  • I beginning to wonder how you can call yourself an Android developer. It is OBVIOUSLY a needed feature, as it allows developers to create different bitmap resources for different resolutions - and there can be great benefit to this, if you want to avoid possible scaling artefacts in the images - but other than that, there's absolutely no need to supply drawables in all sizes. It's a waste of space. Android's scaling overhead is minimal. If you have any doubts, check out BitmapFactory.Options and learn. – Michell Bak Oct 19 '13 at 15:58
  • @MartinCazares: First, `res/drawable/` is equivalent to `res/drawable-mdpi/` for bitmaps, so having both is a waste. Second, "since the OS will not find the Asset either BOOOM no resource found" is incorrect, as you later admitted in your comments. Third, "notice how the SDK creates one icon_launcher.png img in each density with a specific size to handle exactly this issue" is incorrect, as Eclipse specifically does not bother with `res/drawable-ldpi/ic_launcher.png`. – CommonsWare Oct 19 '13 at 16:13
  • I'm afraid I have to disagree with res/drawable is equivalent to res/drawable-mdpi, if you run an app in a ldpi device and just set the asset in res/drawable-mdpi, the app will crash, if you set it in res/drawable it works fine, is actually the catch all folder, and related to eclipse just did it, and it creates the asset in all the densities except for the (drawable)default since it doesn't need it because you are taking care of all the possible scenarios... – Martin Cazares Oct 19 '13 at 16:20
  • And don't get me wrong I'm always willing to learn, but this is the way the OS is working, and I did it / proved it... – Martin Cazares Oct 19 '13 at 16:23
-1

Is there any way to say to the app to auto scale the mdpi drawables instead of crashing?

This happens automatically, unless the maker of the firmware (device manufacturer or ROM modder) screwed it up.

For support ldpi screens, must I edit the images to ldpi size?

No.

I would look up 7f02007f in the R.java associated with your production code base and make sure that it is what you think it is. Bear in mind that these numbers get regenerated on every compile. Perhaps this is a case where there simply is no drawable resource for this number, in any density, because R.java was out of sync with the actual resource packaging. To avoid this problem, do a clean build (e.g., Project > Clean inside of Eclipse) as part of making the production APK.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • The code exists in the R.java but the app crash in ldpi screens. Is it happens on not original ROM? What can I do with it? – nrofis Oct 19 '13 at 13:52
  • @nrofis: "Is it happens on not original ROM?" -- I have no idea what devices are crashing for you, so I cannot answer that. "What can I do with it?" -- either provide `-ldpi` drawables, or use `` in the manifest to block distribution to `-ldpi` devices, or try to figure out if this problem is affecting all `-ldpi` devices, or only those running some particular ROM mod. – CommonsWare Oct 19 '13 at 14:26
  • This ought to be the accepted answer. If you've got such an error, it's not because you haven't supplied a ldpi-version of your drawable, it's almost definitely because of an issue with your R.java file. Cleaning the project should fix it, as CommonsWare suggests. – Michell Bak Oct 19 '13 at 16:03