I have a lot of "out of memory" reports in an application from Galaxy S4 users.
The app is working with Bitmap . It has a graphical UI. It works good on all devices but on S4 it crashes.
Do you know if we need any special memory management for S4?
I don’t believe that S4 introduces something out of the ordinary with Memory management or Images. I guess looking at the memory usage of the app will be helpful.. Follow this guide to look at possible leaks and memory consumption of your app.
http://developer.android.com/tools/debugging/debugging-memory.html
Since you said that you deal with images in your apps... In my apps I have had memory problems with bitmaps. A good tip is to use LRUCache to cache and manage bitmaps. Follow the link below to understand LruCache.
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Hope this helps!
In order to solve this, you need to understand how images use memory.
Imagine an image, 800x800 pixels. Without any scaling, this will require approximately 2.5MB of memory. Width x height x 4 bytes.
All loaded images are stored on the heap which is limited in size (there are many discussions on here about heap size).
Now load that image into an ImageView which is displayed on a 1024x768 screen, the size of the ImageView being 800x800 - the same size as the image. You are using DIP as recommended so that your UI scales.
Your 1024x768 display has 786,432 pixels. The S4 has 1920x1080 = 2,073,600 pixels. Approximately 2.6 times as many as the 1024x768 device.
If you do not do anything to scale that image and you do not use the density and resolution "bucket" resource folders, then that same image now needs 2.5x2.6MB = 6.6MB.
The key point is that unless you control it, your image will use
different amounts of heap memory (which is limited, it doesn't matter
how much RAM the device has) on different devices.
I suspect that your app would have problems on Nexus devices too.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
http://developer.android.com/guide/practices/screens_support.html
Related
Apologies in advance for such a basic question, but this is my first app and I can't quite find a clear answer for my situation. All the images in my app are stored in the drawable folder, I'm NOT downloading any images from the internet. All the information I come across when it comes to multiple image sizes seems to refer to the occasion when the app is fetching images from the internet.
So currently most the images in my app are one size, customized for the largest size - xxxhdpi. However, I understand the app is doing some work to "shrink down" those images for the xxhdpi size screens.
I'm having second thoughts about this one size fits all approach. I'm thinking that perhaps the app doing the work to shrink the image down might take up extra memory and negatively impact performance. I've been looking at the Android Studio Profiler and I've been trying to understand the Graphics Process when I look at the Memory Graph.
More generally speaking, is there a benefit to having the smallest size images possible, even for the xxxhdpi? For example, does it hurt (memory wise or in some other aspect) to use a .png image when I could use a lower quality jpg? Again, just to super clear, this is just in the scenario when the app has all of its images in the drawable folder. My app has options where players can change the game background and other images so I want to be sure I'm optimizing how the images for best performance. Thanks.
Memory. If you load a bitmap of x by y pixels, in memory that takes 4*x*y bytes. For a full screen image, you can expext that to be 4000*1000*4 or 16 MB. That's a good chunk of memory to a small device, which also tends to have less RAM. If instead it needed one at half the resolution, you would have 2000*500*4, or 4 MB.
Obviously this scales with size. The smaller your images, the less memory wasted. I wouldn't argue that you need to provide every size, but if you're using large images I'd provide more than one. Also, for anything that isn't incredibly complex (like icons) I'd consider vector images instead (although that's a CPU time vs memory tradeoff).
You mentioned png vs jpg. There's two things to consider there: apk size and image quality. JPG is smaller, so it will lead to a smaller apk size. PNG is lossless, so it will have higher quality (although whether that matters requires a human visual check- it matters less than you'd think on a lot of things). Interestingly it doesn't effect the amount of memory used at runtime, because both are held in the Bitmap object uncompressed.
I'm building an application with very big sized images.
Almost all of my UI components are made of ImageViews.
I only have to show 12 images(ui components) on my first activity, but it consumes 80mb on startup.
The images are divided into each drawable directories using Android Drawable Importer.
By doing this I was able to reduce the runtime memory(which I can see on the Android studio's device monitor) to half, but it is still consuming 80~120mb of memories, which I believe is too much.
The first question is, isn't 80~120mb too much for a four screen(two activities, three fragments) application?
The second is, if it's too much then, what and how can I do to reduce memory usage?
When working with images keep in mind that there is a HUGE difference between compressed format (jpg, png..) and Bitmap. Computing the size of a Bitmap is pretty easy, it's width * height * 4 bytes (assuming that the bitmap has the default configuration argb888). So a full hd image that compressed is xy kb, when decompressed will occupy 8294400 bytes (~8mb). So my advice to reduce memory consumption is... scale down your images. You're asking if 80-120 mb is too much, well it seems like a lot but it really depends on what you're doing. What happen if you force garbage collection (there should be an icon in the device monitor)?Another thing to take into account is how to decompress the images, refer to this and use a library (Picasso, Glide..).
Hi I have asked before question relating memory management. Since then I have allowed larger heap size, and i have created all the images in right resolution, but still i have an issue that the application is using from 150 to 230 MB of RAM on Samsung Galaxy S5, and the same app and the same build is using just 10-20 MB of RAM on Lenovo A319. What am I missing? Please explain me it. I am clearing the memory and recycling the images to, it was not an issue with the app earlier.
The reason is the resolution difference in these two devices. when you set an image to a ImageView and assume it's full screen.
S5 scales it to 1080p so when the image convert to BitMap it would take 8.2944 Mb
In A319 (400X800) would use only 1.28Mb to show same image in full screen.
Devices which has high resolution comes with higher RAM's so if your app does not cause OutOfMemoryException's you don't have to worry about this
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'm having severe memory issues in my application [1]. In order to investigate this, I took heapdumps of my app at different states. I saw that some bitmaps were taking huge amounts of memory. I wrote a small tool [2] that decodes the byte arrays to Windows bitmap files (.bmp), so that I can see the bitmaps and compare them to the files I have in my res/drawable folder.
What I discovered is that all my files are upsampled twice.
I first checked with the biggest one had: a byte array buffer of more than 9MB in the heap, which was decoded to be a nice 1920x1280 picture, while the original one was a 960x640 png file.
I tried with the second biggest, over 3MB, which once decoded showed a nice 754x1200 picture, the original size was... guess what? A nice 377x600 jpg file.
What gives?
I have enabled HW acceleration in my Android Manifest file (though I'm not sure I really need it, I'm just using some basic views and activities).
I'm running stock Android 4.0.2 on a GSM Galaxy Nexus (yakju). I'm receiving feedback from my testers that the issue is present on their 4.0.3 Nexus S, though I couldn't check their heap dumps yet.
I'm trying to save memory here, if Android doubles everything, no wonder the app crashes quickly because the heap usage gets too high (around 64MB in my case). I hope there's a reason and a way around it.
References:
OutOfMemoryError when loading activities
How to actually see a Bitmap taken from an Android heap dump
When you put images in res/drawable, Android will assume they have a dpi of 160, i.e. it is the same as putting them in res/drawable-mdpi. Galaxy Nexus is an xhdpi device, i.e. it has a (generalized) dpi of 320. To compensate for the high resolution display, Android will upsample the images with 200%.
The solution is simple, just put the images in res/drawable-xhdpi instead. Then the declared dpi of the images will match the display you run on, and Android will not perform any scaling of the images.
Please refer to http://developer.android.com/guide/practices/screens_support.html for more info.