I'm writing a program about letters for babies and I'm using 28 images. It's a flashcard program, and was running ok until I reached 20 images.
It force-closes before opening. I'm still in my early stage in the program. I put my images in the drawable-mdpi. After working on this error for 2 days, I discovered that when I split the images between drawable-mdpi and drawable-hdpi it works well, but the images that are in the hdpi folder are smaller, although they are of the same size.
I want to know, why does it work when splitting the images? Is there a limit to the number of images per folder? And also, why do images that are in the hdpi folder get smaller in the app?
There is no limit of the number of images per folder. I have an application with more than 360 pictures in the folder drawable-mdpi (really) for a total size of 32Mb and it works well.
If you test your application on a mdpi screen (160dpi), and you had hdpi images (for 240dpi), then the application automatically reduces them at run time by multiplying their size by a factor 160/240 = 0.66, which explains why they appear smaller.
See Multiple screen support for Android for more information.
The dpi are the "Dots Per Inch", Android allows a simple way to ensure that the Device running the application will load the best available resources, for its "bucket", the category of dpi it uses.
You can disable this behavior, by creating another drawable folder (such as res\drawable-nodpi), and place your bitmaps there, and then loading then, and doing any mutation as needed.
Related
Until now, I did not pay too much attention to how to store drawable resources.
I usually generate multiple versions of an icon and store them under the drawable-mdpi, drawable-hdpi, drawable-xhdpi, ... folders.
For other images for which I don't have multiple versions, I inconsistently store them under drawable-nodpi or drawable.
However, I recently encountered an issue related that bring all my attention to that. I stored a 100KB image under the drawable folder. However, my app was regularly crashing, stating it could not allocate 18MB!
After some searches, the reason was that the image was scaled to fit the screen resolution and it resulted in a way heavier image. The fix was to move it under the drawable-nodpi folder which prevents that scaling.
So now, I am trying to better understand where I should locate my images and how this scaling effect works to optimize my app on that part.
I have done plenty of searches, but resources are limited or unclear on that subject and the official documentation kinda really sucks.
I am aware of the official explanation for the drawable or drawable-nodpi, but it does not clarify everything.
Typically:
How does the scaling work? Let's say I have res/drawable-mdpi/image.png. Does that mean the image is scaled if I have a screen different from mdpi, or will it also be scaled on mdpi screens resulting in possibly heavier image size on every device?
Following previous question, if the image is not scaled for mdpi screens but scaled for any others, then does that mean that if I provide a version of this image for every screen density, the scale will never happen? Or at the opposite, if the image is scaled also on mdpi devices, then having different version of the same image for each screen density will still scale the image, but using the version of the image matching the screen density of the device?
How to deal with icons for which I do not have multiple versions? I am afraid that if I put this single version in mdpi, it just scales it and uses so much more memory than necessary. In such case, should I put any icon for which I do not have different versions under nodpi?
On the other hand, if whenever you put an image in mdpi, hdpi, ... it scales it even on devices matching the density, then should I just move everything under nodpi or some high resolution like xxxhdpi where it can only be downscaled?
Thanks
Let's say I have res/drawable-mdpi/image.png. Does that mean the image is scaled if I have a screen different from mdpi
Yes.
or will it also be scaled on mdpi screens resulting in possibly heavier image size on every device?
No.
if I provide a version of this image for every screen density, the scale will never happen?
Yes. Your APK will be larger, due to the 7 copies of the drawable.
How to deal with icons for which I do not have multiple versions?
Option #1: Decide what density that particular version belongs in, and put it there. Android will upsample or downsample the image for devices operating at other densities.
Option #2: Put it in -anydpi or -nodpi, in which case Android will not upsample or downsample it. However, in this case, you need to be controlling the size of the image yourself (e.g., in the ImageView).
Option #3: Replace the icon with one that either you have all relevant densities or one that is an SVG that works as a vector drawable when imported using the Vector Asset Wizard in Android Studio.
The decision-making needs to be based both on memory consumption and what the result looks like. A low-memory solution that looks awful is unlikely to be a good choice.
should I just move everything under nodpi
Probably not.
or some high resolution like xxxhdpi where it can only be downscaled?
Probably not. It is unlikely that a massively downscaled version of your icon will look very good.
I've read "Supporting Multiple Screens" on the official docs.
I have around 15 activities. I currently have 4 background images. I've randomly assigned a background image to each of the screens in simple XML.
All these images are around 400X800 in the drawable hdpi folder.
Now the problem:
My app looks bad on tablets. The low resolution images are stretched out.. making them very blurry. So, I'm thinking about adding some higher res images.
The question:
So, now I have 4 images in the hdpi folder. (read slowly) ... If I add the same images of higher resolution in the xhdpi folder .... Will a device with screen of hdpi resolution also have to save the other res pics ?
I know that was confusing, below I explain with an example:
Okay, so I have three devices..
One small,
One medium,
One Tablet.
Now I have 3 sets of images in the mdpi, hdpi and xxhdpi.... for each of these.
Now, will the small device's apk file also contain the bigger images which are not used in it? ... I mean, can android choose which images it wants to download (changing the app size for different devices) ...?
Or does it simply download everything (increasing the app size)... and choose later on while running ?
The thing is, my app is like 800kb .... and adding 3-4 background images for large phones or tablets will drive up the app size to 5-6 mb... That's what I don't want.
So, are all the things stuffed in the apk downloaded equally on all phone sizes ? or are the pics downloaded selectively?
Do small phones unnecessarily download the big images too ?(vice-versa for tablets ?)
(I asked this question, because in many android apps , their size says "Variable for different devices" or something like that... and there's no mention of this whatsover, anywhere on the internet. Trust me, I googled for an hour.)
Yes. Your project size will increases whatever images added in all folders. If you are designing for 4 different screen your apk size will increase automatically. If you want any images common for all screens, then you can create a drawable folder and place the image in it. So it will pick automatically. Both apk size and your project quality are important. So you should consider image size when adding to the project. By using padding and other xml factors you can adjust screen size by same image also.
The whole apk is downloaded together with all images for all resolutions. As you usually upload only one file to Google Play, the same file is downloaded by everyone.
There is an option do distribute different apk files based on device onfiguration but it is not very convenient to manage.
You can read about publishing multiple apk in here: http://developer.android.com/google/play/publishing/multiple-apks.html
On my android project I have 5 kind ok drawable: xxhpdi, xhpid, hpdi, mpdi et lpdi
But I don't realy understand in witch file set my images
I had a look to this link: http://developer.android.com/guide/practices/screens_support.html
I need to class my pictures by size and by px/in
I have ic_launcher in my folders:
xxhpdi => 144*144px
xhpdi => 96*96px
hpdi => 72*72px
mpdi => 48*48px
lpdi => vide
But they are all in 72*72 px/in
I'd like to know how to set my pictures in res folders, why not just have a xxhpdi image ?
and did we always need to have 5 image, it weighed the application.
Thanks
Resolutions were explained in other answers. Regarding the question about weight of the app, You could provide different apks for different devices via Android Market, so particular apk would include only images for particular screen.
Moreover, the same time You don't need to do simultaneous development of many branches etc. just because of images differences, just follow Android documentation on support multiple screens and produce separate builds using aapt -c key which would allow You to have only necessary configuration included in every build..
The Android system will choose the closest 'density bucket' (drawable folder) to the current device, and use that for some final resizing to the devices exact size.
Its a guideline to provide an image for every density bucket to ensure the best result, but in practice often an image will look just fine by only adding it in 1 or 2 folders.
If you have a problem with having some big images that make your app huge, cause you have to add them 5 times, you could try around with adding those only in 1 or 2 folders.
Per example, xxhdpi is only nexus 10 at the moment, are you even really supporting that? ldpi is also not very common anymore. You could try adding it only in xhdpi, and scaling will probably look fine.
For the rest your images shouldn't be much more than some simple icons, which shouldn't take up a lot of space.
tl;dr: Yes if you want to follow guidelines for best result, but you can probably cut on app size without people actually noticing.
Android comes different screen resolutions, each resolution depends on screen width/height.For mobiles you place the corresponding sized images in res folder. During run time device itself find the resolution and re size the resolution it needs. For some cases you may get issues like image squeeze etc. At these time you place the corresponding image sizes with their corresponding res folder with same names.
I wrote a little toole for this.(BitmapCat) It scaled png-, bmp-, and jpg images for Android apps in:
ldpi(low-density)
mdpi(medium-density)
hdpi(high-density)
xhdpi(extra-high-density)
xxhdpi(extra-extra-high-density)
Here you can download it: http://blog.axxg.de/bitmapcat-en/
A lot of blogs and best practices for Android Development says
"You don't need to supply bitmaps for every possible density, Android will scale your bitmaps (typically when they are loaded) to match the current density."
Reference Link : https://plus.google.com/105051985738280261832/posts/6eWwQvFGLV8
I tried it works well.
But i couldn't understand one thing.
For instance i created a sample app with 5 full screen images of around 1.5 MB each in a view pager.
I created heavy images for 7 inch MDPI devices like Galaxy Tab 2 and put them in "drawable-large-mdpi" folder. It was bit jerky but didn't crash and let me scroll through all the images.
Now i tried to use the app on my Nexus 7 which is almost a large HDPI device. The app crashed with "OOM error" while decoding the bitmap.
*If i move the images from large MDPI to large HDPI, it works well on both the devices with out any crash. *
So i have two questions.
Does this result incline towards, we can only put the graphics assets in the highest density drawable folder and let it scale down automatically in its range ?
What happens internally why it crashed for the first time ?
That would be one way to do it so long as the drawables look fine when scaled. Scaling down in size usually is better than scaling up. That said, there is this line:
Even so, when bitmaps are scaled to a density there isn't a design
for, you may get artifacts such as softening of the edges.
The reason scaling from HDPI to TVDPI works fine is because the two densities are so close. Problems with some images will start showing up between the major densities. For example, jumping from HDPI to LDPI will sure result in many artifacts as the image was simply not designed for low-resolutions.
It's most likely crashing with an OOM in the Nexus 7 because it's taking your large images that the device thinks are MDPI images and scaling them up to TVDPI settings. This would result in an even bigger image.
When you put them in the HDPI folder, you're telling it to scale down to TVDPI so the resulting image is a less memory footprint.
There's also the overhead that comes in to play in the actual scaling.
The same thing will probably happen when you scale up to an XHDPI device.
No, you can put graphic assets into any drawable folder. If you only put resource in one density folder, the system will scale up and down to the target device densities.
You wanted to use a lot of memory with using those large images at the same time. Even if you use compressed image formats, when the system draws it on the screen, it will be in the memory as a bitmap. So if you keep 4-5 1200x800 pixel image in the memory at the same time it will use up that amount of memory in bitmap. That crashed your app because it ran out of the granted memory (which is very low by default android only ensure 16 mb which is usually broadened by manufacturers).
When you put the images in the hdpi, system scaled down the images, thats why there could be (not guaranteed) enough memory for the smaller images.
Solution: don't use that big images as backgrounds. Try nicely scalable images, and check out the 9-patch format: link
I have a android application, that uses many images. and application is to be used on different resolutions. I am using only one set of images and images are saved in "drawable-mdpi".
So "The images gets blur when I run it on a high resolution".
So probably the solution of this is to save different images of different resolution in drawable-hdpi,ldpi etc.
Is doing this is enough or do I have to change the images by code? or phone automatically adjust the perfact image into the drawables.
can anybody provide a example??
If you put the images in the ldpi,mdpi,hdpi or xhdpi folders Android chooses the images according to the current device dpi.
If you only add mdpi ressources and load them on a hdpi device Android will enlarge the images with a factor of 1.5 if you open them on a ldpi device they will be shrunk with a factor of 0.75.
The scaling is applied so that the images have (almost) the same physical size all displays with any dpi.
You should add different images for each dpi if those images will be blurry (or loose details when shrinked) after this autoscaling. If you have simple images that look well after scaling you only need to add one image to any dpi folder.
EDIT:
On Android there is no default way for automatically selecting images depending on the screen resolution. As the docs says:
When adding support for multiple screens, applications do not work directly with resolution; applications should be concerned only with screen size and density, as specified by the generalized size and density groups.
(see Supporting multiple screens).
This is enough. This is the reason for having different folders in the drawable directory, but note that Android 1.5 supports only 1 folder called drawable with no subdirectories (but there are no phones on 1.5 with resolution higher than mdpi)
One of the best ways of making sure your images are always properly scaled is to use 9 Patch drawables. Android will scale these according to the screen size automatically. They are best used for things that usually change size (Buttons, EditTexts, Spinners, etc), but can be applied properly in the right setting.
One advantage using 9 Patch images gives us is space-saving; having three different versions of images built into our applications can get quite large after awhile, but with 9 Patches you only need one copy.
See here for more details:
http://developer.android.com/guide/developing/tools/draw9patch.html