High resolution UI on android issues - android

I got primarily 2 issues.
In fact: I made an app which uses neat ui elements. Because of their detail they have to have a fitting resolution for every screen so i do big pictures in drawable-xhdpi, smaller ones in drawable-hdpi, etc...
The problem is: Using such high resolution UI elements slows down the whole app. It's not yet the worst-case but I am really stressed with the fact that I cannot make a "perfect" app which is beautiful and does not lag.
The second issue is: The app really becomes big when considering tablets also (xhdpi images are bigger). Out of compatibility reasons I dont want to make an extra tablet app...
Somebody got some information for high-res problems?

When using large images on android i found the available heap can be a constraint.
As the lower-res images are scaled up the simple drawing-performance itself should not be any problem.
But every image you need to keep in the heap is reducing available memory for everything else you can do without getting onLowMemory callbacks.
There is an option within the Android Manifest to allow more heap on newer devices
android:largeHeap="true"
This will not give you any more heap on most devices but if you try it on a modern device you can see if it makes a difference to decide if memory might be a problem.
It also can help to enable hardware acceleration.
<application android:hardwareAccelerated="true" ...>
Another option is to improve performance on images which you need often.
The BitmapFactory.Options have an inPurgeable which control if the Bitmap is freed when memory is low.
But ... even if memory is a problem it is morelikely that the views have a too complicated layout.

Related

Android memory management: Screen density, requested image sizes and available heap

Guess what, another Android-Bitmap-OOM question!
Background
Whilst stress testing our application it has been noted that it is possible to max-out the app's process memory allocation after sustained, heavy usage (monkey runner like) with OutOfMemory exceptions being recorded within the ensuing stacktrace. The app downloads images (around 3 at a time) when a page under a ViewPager is selected. There can be 280+ images available for download when the length and breath of the app is exercised. The application uses Picasso by Square for it's image downloading abstraction. Notably, at no point in our application's code are we manipulating Bitmaps directly...we trust that the very talented Square Inc. employees are doing it better than we can.
Here is a picture
The below plot shows the heap allocations over time recorded under the dalvikvm-heap log message. The red dots indicates a user bringing a fresh set of articles into the application in order to bolster the amount of work outstanding and stress the app...
DALVIKVM heap allocations http://snag.gy/FgsiN.jpg
Figure 1: Nexus One heap allocations; OOMs occur at 80MB+
Investigation to-date
Against a Nexus S, Nexus 4, Wildfire, HTC Incredible and a myriad of further test devices, anecdotal testing has shown the memory management to be sufficient with the DVM GC 'keeping up' with the heavy lifting work being completed by the app. However, on high end devices such as the Galaxy S II, III, IV and HTC One the OOM are prevalent. In fact given enough work to do, I would imagine all of our devices would eventually exhibit the failure.
The question
There is clearly a relationship between screen density (our requested image sizes are based off the size of the ImageView), the process memory allocation and the number of images at a given size that would result in the app exceeding it's heap limits. I am about to embark on quantifying this relationship but would like the SO community to cast their eyes over this problem and (a) agree or disagree that the relationship is worth making and (b) provide literature indicating how best to draw up this relationship.
It is important to note that if we destroy the image quality our OOM all disappear but alas the UX is poorer which is why we are wanting to be dicing with the most effective use of the available heap.
Side note: Here is the portion of code responsible for loading these images into the views that have been laid out;
picassoInstance.load(entry.getKey())
.resize(imageView.getMeasuredWidth(),
imageView.getMeasuredHeight())
.centerCrop()
.into(imageView);
The 'dashing of image quality' mentioned above is simply dividing the imageView.getMeasured... by a number like '4'.
First you need to manage the memories allocation ,its a big issue in android as bitmaps takes lots of memories ,for that memory allocation can be reduce by following ways
put all those images which are huge in size to assets folder instead of putting them in drawabable folder . because drawable resources takes memory for caching them .if you load from asset folder the image will not cache .and will takes less memory .
study Lrucache which use for efficient memory management .
put resources in tiny formats for that check TinyPNG
if your images are too large in resolution , then try to use SVG files for images and load SVG file instead of image . check this SVG FOR ANDROID
finally i am not very good in English hope it may helps you.
This post is a little old but I also had this issue recently. Maybe this will help someone else.
General Overview of this massive thread/What helped me.
-Make sure you are using a Singleton Instance of Picasso
-Use fit()
-For large Images or many Images or when used in a FragmentPager/StatePager you should probably use skipmemorycache() and/or largeHeap declaration
Read the thread for more tips. At the time this question was posted nobody had posted this issue on picassos github.
https://github.com/square/picasso/issues/305

Determining available memory for bitmaps

I'm working on a graphical app for which I want to keep an array of bitmaps that are used for Undo operations. The bitmaps are quite large at around 9M each, so I realise I can only keep a few in memory at any given time.
I'd like some way of working out in advance how many I can have.
I've tried various ways of querying available memory, and am being careful to recycle bitmaps once they are not needed, but despite that the app seems to crash with EOutOfMemory.
I don't want to scale down the bitmap, or use RGB565. I just want a reasonably reliable way to figure out how many undo steps I can allow for.
Thanks
EDIT #1
I've continued to try various ways of determining available memory, including those linked to in the comments, but still am having problems.
The strange thing is that my old Samsung I9000 phone doesn't have too many problems creating and accessing lots of bitmaps each 9MB in size, but my newer Samsung Tab 3 dies allocating the 3rd one.
It should have plenty of memory available. I did read something about there being differences in where memory is allocated for bitmaps on Android 3 and above, but don't fully understand it. Could this be what is causing my Tab to die with EOutOfMemory?
EDIT #2
In desperation I decided to turn on largeHeap in the manifest. I know it's not recommended, but it has made the Tab 3 behave more predictably, and it possibly demonstrates something about the underlying problem.
This reminds me of a very common mistake , of putting the image files into the "res/drawable" folder.
Such a thing causes the bitmaps to take much more memory the higher the screen density is.
for example, for a 100x100 image, it would take only 100*100*4 = 40,000 bytes on an mdpi device, but it will take (2*100)*(2*100)*4 = 160,000 bytes on an xhdpi device (4 times more).
however, since the galaxy tab 3 doesn't seem to have a high density screen, i think that you get OOM because the heap size is small for holding all the bitmaps.
check out my post here for some memory and bitmaps tips.
It seems that getting available memory is a bit quirky in Android, but it turned out that my main problem was that on newer versions of Android the memory allocation for bitmaps has changed, and they now easily blow the limit of the heap.
Setting largeHeap in the manifest got me around that problem, but I'm still not sure it's ideal.

Android Fatal Signal 11 from XML

I am creating an Android app and I have yet to run out of memory until just now. The part that is confusing is it was not a way I would expect to run out of memory.
I simply added a new Linear Layout to a layout xml file. It had a background of an image that was 40kb large. The other images that were loaded were approximately 12kb with the background being much larger at 120kb. When this image was loaded I would receive a Fatal Signal 11 on runtime. If I removed the background from the layout it would work fine. I then changed the image to be much smaller, it was (2000x600) before so now it is 14kb. It now works fine. It is clear that the extra 26kb was causing a problem...
What kind of precautions should I take to ensure this doesn't happen again. Obviously I would like quality images and the 2000x600 might be excessive as it's an app for a phone but what guidelines should I follow?
Is there a memory usage cap that can be extended or that I should look to stay under? Also, if I loaded many images on a scrollview will this cause the app to crash? I have had many images loaded at once but have never had it crash before, I'm just confused as to the error being caused by very little memory usage. (In todays terms at least.)
Regards,
Jake
Images do not consume the same amount of memory in RAM as they do on disk. You can get the RAM usage by:
width*height*4 (for images with an alpha channel)
and
width*height*3 (for images without an alpha channel)
An Android app is allotted a definite amount of heap space in the RAM, which will always be the same on a particular device and ROM version on that device. The minimum is 16 MB, though these days most devices give you a more comfortable 32 MB or 64 MB. It really depends on the device.
You get Out of Memory Exceptions (OOMs) when your app exceeds this heap space. The simple fix is: Don't exceed this heap space.
The best way to get quality images in your app is to use the density buckets and provide different sizes from which Android can choose. LDPI screens cannot make use of high res images anyways, so you should only supply a low res on in LDPI. On the other hand, HDPI devices can make use of better resolution, and if you supply one Android can use it. It is almost a given that the higher the resolution of the device, the more heap space you will be allotted for the running of your app.
Another way to manage memory is to only load what you need, by implementing lazy loading. This is especially helpful with listviews and scrollviews and other adapter based View systems.
On Android 3.0 and above, you can request a bigger heap by using android:largeHeap="true". However, this should be avoided as the user will notice other apps of theirs being removed from memory whenever your app is launched, and it is not guaranteed that you will receive a larger heap in any case.

How can I gracefully degrade my performance, given limited memory?

I've spent the last few days trying to remove memory leaks in my game, resulting in many out of memory errors. I'm on the verge of adding a significant amount of graphics, that while not hugely complicated, will add significantly to the processing requirements of my system, and I'm a bit worried about my memory usage, and I was hoping someone might have some tips for me. I don't want to go below Android 2.1, so please tailor any answers to that end.
First of all, my game consists of:
2 activities, 13 XML files (Some relating to a small part of a layout, some dialogs, and 2 directly related to activities.
A number of drawables, made in Adobe Illustrator and converted to PNG. These are probably large, but not unusually large, and for the most part, only small amounts of them are in memory at any given time.
Quite a few dialogs.
Targeted towards Android 1.6 and above.
I used the newest Admob, and as a result, I have to build against 3.2.
My default heap size for my emulators is around 24 MB.
A few sample images from my game:
What I have learned:
Despite my total app size being only around 500K, I somehow am taking up 24 Megs, as calculated by adb shell procrank.
I have done considerable optimization, but am not seeing large increases in memory.
Using tools to find what is in the Heap typically only show around 7 MB avaliable, with around 3 MB being used. Sometimes, when opening new dialogs and the like, I see an increase, but I can't say that I see it being all that large...
MAT shows that none of my classes are using an unusually large amount of memory.
So, given all of this, my questions.
Is 24 Mb an actual requirement to develop to (1.6+ android)?
Assuming it is, how can I both allow for nicer graphics for systems which can handle it, but not crash and burn for older systems?
What are some common gotchas that I can use to improve my memory usage?
Without seeing your actual code, I can't say if the following will be relevant to you or not. However, it is worth a shot.
If you are not already doing so, you can consider using something called an LruCache. http://developer.android.com/reference/android/util/LruCache.html
Using this tool, you can determine at what point your cached objects (such as Bitmaps) will become eligible for garbage collection. So, if you want to set it at 4mb (for example) the OS will deal with it should it try to grow beyond it. (See docs for implementation details and a good example).
The only downside is that that little gem only came along with 3.2, so you would have to make that your min SDK in the AndroidManifest, or do a check programatically at run time for the api level to determine if you can use it. Pre 3.2 I would say you need to call recycle() on any Bitmaps you are using, but if you have optimized already I would think the chances are good you are already doing this.
This is a nice little snippet about the difference between the heap and native memory. http://code-gotcha.blogspot.com/2011/09/android-bitmap-heap.html It may (depending on what you are doing) help you to understand why you are not seeing the drop in memory you are expecting.
And finally this post from SO should help when dealing with heap size as well:
Detect application heap size in Android
Hope that helps.

largeHeap to exceed Android machine-specific max heap size

I'm currently building an Android project that I believe will use quite a lot of RAM, much more than the default max heap size set by devices.
The app will be the only one that runs on our Android machines (they're single-purpose), so I'm not worried about slowing down other processes. I want all the resources possible to go to this one program.
I know that I can use
android:largeHeap="true"
to give myself more room. However, in another post, a commenter suggested that this setting does not override the machine-specific max heap size. Is this true? And if so, is there another way to exceed this limit?
As an aside, I saw some posts that show how to do this natively. Unfortunately, I'm a mere Java programmer and so I have to work within the constraints of Dalvik.
This option is only for Honeycomp tablets ATM.For API levels below Honeycomp the only thing you can do is increase the heap size of all applications (Rooted phone) I haven't actually used is but check this video from Google IO at 06:00. It said that expands the heap size. So probably he is correct and not the commenter you mentioned :D

Categories

Resources