If I create a blank new project and run it, it uses 23MB of memory.
If I add one 540x960 png image to the background of the layout, it uses 47MB of memory.
If I add an image button with a background image on it, it uses 64MB of memory.
This continues to go on if I add things, and this is way too much. On the app I am currently working on, I have memory used at between 180-210MB of memory. I figured there was something wrong I was doing with loading the images, so I ended up putting them all on imgur, and loading them in with Glide. This reduced the memory by a small amount, and also doesn't explain why a new blank project would use 23MB.
I thought there might be some kind of setting, but I re-installed with default settings and am still getting the problem.
I experienced a similar issue when I put the drawable in the wrong resolution folder, especially the standard "drawable" folder is a pitfall since it is assumed to contain the image in "mdpi" resolution, so the image gets upscaled like crazy on xxhdpi devices.
Here's a simple test to figure it out, move the images into a folder called "drawable-nodpi" and check for the memory consumption.
Then make sure to provide the image in the right resolution in their dedicated folders, and avoid the "drawable" folder for images, just use it for xml drawables.
What basically happens is if you put your "540x960" image in to the standard drawable folder, it is assumed to be mdpi, if you view it on a relatively modern "xxhdpi" devices the image gets upscaled by a factor of 3 e.g it will be "1620x2880" and therefore consume much more memory.
http://developer.android.com/guide/practices/screens_support.html
Related
I am about to publish an android application which uses several images with different resolutions. I have found the hard way (with a crash) that putting all images in drawable folder causes a OutOfMemory Exception because images are scaled up. By putting all images in a high dpi folder like drawable-xxhdpi the problem goes away.
My question is : should I arrange images according to their resolution to the respective folders ? Will that make any difference ? Will android scale-down an image found in drawable-xxhdpi even if it is a low resolution one ?
You may want to use Glide for rendering drawable in your app. Glide provides you mean to auto scale the images according to your image holder size. This also caches the images for faster access (if you were to use network images). Read the doc and see if it helps you.
I have moved all my images from the folder mipmap to drawable because here it was said that the mipmap folder is only for app icons to lanch the app Mipmaps vs. drawable folders (the answer got 841 likes). However, when I now want to start my app I get an error message
FATAL EXCEPTION: main
Process: com.example.td.barapp, PID: 4331
java.lang.RuntimeException: Canvas: trying to draw too large(188394348bytes) bitmap.
at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:260)
In several realted questions people tell to store the pictures in different drawable folders (see Android : Understanding drawable folder) like drawable-xxhdpi or drawable-xxxhdpi.
Update: I was told by someone in this post (who later deleted his answers) to store the image (which has a size of 1,7 MB) in the folder drawable-anydpi. I did as he said but the outcome on the Emulator looks quite bad for an imageview (see screenshot):
Then I moved the same file back into the folder mipmap-xxxhdpi and now it looks good again. So my question now is, whether it is also okay to have the image in the mipmap-xxxhdpi folder instead of the drawable folder? I'd be happy for every advice because I am quite confused now.
java.lang.RuntimeException: Canvas: trying to draw too
large(188394348bytes) bitmap
This exception mainly because you are trying to display a big image ~ 188MB which will have a high resolution, and android puts limitation on that, This also reported here.
One of the reasons is to save device resources; for instance you might get java.lang.OutOfMemory, so the system save device memory from that.
1, 2, 3 may guide you thoroughly on that.
Normally you can use a few mega bytes image in your app ~0-3MBs.
Third party libraries like Glide & Picasso offer disk, network, & memory management techniques while displaying images on your ImageViews.
One of the options you may consider is to resize images before loading them, so can have look on this question.
Keep in mind that android puts limitaion on your apk file on the app store, so you need to minimize images for that reason, or load them from a back-end server.
As you mentioned, you can only put app icons in res\mipmap. And if you decide to put the images on your app, it's efficient to create them in different densities (hdpi, xhdpi, xxhdpi, xxxhdpi...), so they can match all the variety of device resolutions, and lets you avoid distorted images or high processing by android OS to match your image to the device resolution before displaying them.
I am using some png images for the backgrounds of activities in my application. These png files are mostly very small sized images. For example, I am using one with the size of 768x1024 which is actually 29.6KB on disk. When I run the application on my Samsung Note 1, I realized that the image actually consumes approx. 3MB of memory. So, Android seems to decompress the PNG file into a full ARGB bitmap (768x1024x4 bytes). I thought that this may be the result of the need of Android to resample/resize the image and placed the PNG file into the drawable-nodpi folder but this resulted in the same amount of memory consumption.
So, what should I do in this case, can I prevent this decompression behavior somehow? I have to put many different images for numerous activities in this project, so it seems that at a point this will cause out of memory errors. I am a beginner in Android and I don't know exactly how the system handles image resources, so I may miss something here.
Try adding these 2 lines to the in to the application tag in the manifest
android:hardwareAccelerated="false"
android:largeHeap="true"
But these are not recommended if you are building a memory efficient App,
But this really works.
I'm quite new to Android development. My understanding is that you can create several versions of the same image with different sizes and put them into the folders drawable-ldpi, drawable-mdpi, drawable-hdpi.
It seems obvious to me that you can handle this problem "the lazy way" by just resizing one image depending on the device's pixel density. For this I programmatically find out what density the device has, like ldpi. The implementation itself is not the problem. I'm just afraid of any drawbacks (that prevent me later from running the app on different devices).
So, are there any (major) drawbacks of scaling images automatically ?
In which of the three folders do I put the image so that the compiler can find it?
You would put the image in your regular drawable folder. That way any phone can find it.
While you can programatically shrink images, shrinking usually has the effect of reducing image detail and causing jaggies.
Adding in smaller assets will also reduce memory usage on smaller phones. Keep in mind that some Android phones are notoriously bad with memory (see: HTC Status), so any and all savings help.
I would recommend just photoshop scaling images down large images yourself. For smaller images, it is not as big a deal.
Android does auto-scale and it works fine in some cases, but it doesn't work for many, notably small images with important details like text. Scaling a larger image down blurs those details. Scaling a smaller image up is worse. This is why icons files have been multi-resolution since the very early days of GUIs. To wit, text scaling is hugely complicated. Ask any font designer, and note Adobe built a company on algorithms to do it automatically.
it's on mdpi folder. It'll change the size automatically. But is not recommended since the image quality drops.
I've been through this post (and others) as well as through the documentation about supporting different screen resolutions in Android, but I couldn't find a clear answer to a (simple) question:
Is it ok to just use "res/drawable" for images in an android app?
Background: The only images that are needed in this specific app are the app icon itself and an icon for a notification, there won't be any images in any layout.So in my understanding, if no "hdpi"-, "mdpi"- and "ldpi"-folders are found, Android will use "res/drawable" as the fallback.As the only pitfall with different screen-resolution seems to be that Android will scale images for a specific resolution if no special one is found, this should only be a problem when UPscaling, because the image will get blurry. But if I provide all "hdpi"-images in "res/drawable" (instead of 3 different ones), won't Android just DOWNscale those images if the size is too big?If that's true, I could save some APK-space by just a third of the images.
Follow-Up question: I read that for API-level 3 a dir by the name "drawable-v3" is required. Is that true or is "drawable" the fallback for this API-level also?
Any hint is appreciated.
The images in the drawables folder are assumed to be at mdpi resolution, so they will get scaled up/down if you don't provide the others.
Scaled up images will be low-resolution and look fuzzy. Scaled down images will have pixels missing and look jaggy.
So your app will "work" with only one set of default images, but will look awful on many devices. I strongly advise that you create the images in different sizes, so it looks great on all devices - it's a bit boring, but not hard to do.
It won't be long before we have xhdpi devices, so while you're at it you may want to create those too.
I assume you've read this
Not a complete answer, but: highly downscaled images can and usually do look just as bad as upscaled images (but in a different way), because graphics libraries almost exclusively use interpolation methods for resizing, and interpolation methods are limited in terms of how much they can shrink an image before serious information loss (to about 50% for linear methods and down to about 25% for bicubic methods). This is why most platforms have evolved conventions (like hdpi, mdpi etc.) that let you embed images that are best for each screen size.
I use drawable/ all the time, and then I go to BestBuy and all the local wireless stores and test my apps on small/large/huge(tablet) devices and they look just fine.
Unless you have some reason to target pre-Donut devices (now only 4% of the devices according to http://developer.android.com/resources/dashboard/platform-versions.html), then you should put your bitmaps in one of the -Xdpi directories. The generic "drawable" directory is a synonym of "drawable-mdpi" for compatibility reasons, but a modern well-written app should be putting its drawables in a directory matching the density they are designed for.
res/drawable is the fallback
the caveat is that scaling not only degrades the image but takes processing time too.
I have not even read the API-Level 3 docs yet, sorry for 1/2 an answer
For what it is worth I found the image handling of Android to be tedious and unreliable. The concept of including different size images for different screens will result in large application files bloated with images. There are already screens that don't fit in the standard resolution ranges. I have found it is best not to let android handle the scaling, it seems to create a base image for the smallest screen you target and then scale it up resulting in ordinary looking images on large screens. This happens even if you made the image specifically for the large screen.
My solution that seems to work on everything from a 2" samsung phone to a Sony Tablet is to create images at high resolution and use Bitmap.createScaledBitmap() to get the size I need.
caveat: I am new to Android and have lots to learn.