Android app with many diagrams - memory issue - android

I have an Android app with several activities and within those activities are around 16 diagrams (JPEGs approx 1200px x 800px, around 300kb each). There are a maximum of 3 diagrams per activity.
I am using BitmapFactory to load the images and scale them accordingly and it's all working fine on devices of all sizes (including devices with small memory).
My question is, I am wanting to add more activities, and another 16 diagrams (again, no more than 3 per activity). Will this make a difference to the memory management for my app? I realise my overall app install size will be larger, but in terms of the amount of RAM the app uses, will it stay the same?
My thinking is that the RAM only loads the diagrams in the activity that is currently being viewed so really it's only 3 that are being loaded at once? So in theory would another 16 images make a difference to my app performance?
Thanks!

The amount of RAM usage will increase with the increase of number of processes and images in the activity. You can monitor use application and each activity using android monitor which may highlight the RAM usage for your application w.r.t activities.

I created a second version of my app with 50% less activities and diagrams and tested this and the average RAM was about the same so this pretty much answers my own question, that the RAM use would not increase by increasing the activities and number of images.

Related

Is there a limit for TextureAtlas size?

I am new in game development and want to develop a phone game. I am trying to make a complex animation in libgdx, which consists of nearly 300 images (655 × 1160 each, together in size of 42MB). Is there a limit in how big textureAtlas image can be or how many pictures it takes? Will there be a problem if I render 7 animations at once, while 2 of them are as complex as this one (activated skill), but others are just simple character movements?
The atlas can be as big as you have RAM for. The more RAM you have, the bigger atlases you can load.
On Android, you may have problems loading 42 MB big images as it's a lot of allocation at once. There have been multiple posts on Stack Overflow about just that problem. You just have to try loading it and see what happens. If the game crashes with an OutOfMemoryException, you have to make it smaller.
Because Android is a platform with a lot of variation in hardware (some devices have 512 MB total ram while others have 6 GB) there's no "hard limit" to what you can load in on a platform basis. It depends on what device and how much RAM is available (free RAM)Disclaimer: this answer is old and doesn't represent a realistic RAM distribution anymore. With certain phones having as much as 16 gigs of RAM and most flagships boasting at least 4 GB, 42 MB shouldn't (realistically) be a problem anymore. Android RAM allocation is still one of the weirdest systems in existence, and sufficiently large bitmaps may throw an exception separately. Bitmaps in this case do mean through the Bitmap class in "regular" android, and not directly OpenGL and/or LibGDX.
What the TextureAtlas actually contains (complex animations of 30 images vs 2 massive images) doesn't matter. As long as you load it (and manage to get it into memory without the game crashing) there's not going to be a problem rendering it. The framerate may drop though (depending on hardware and how much you actually render) but unless you render thousands of images at once it shouldn't be a problem
Adding android:largeHeap="true" in the manifest is also helpful.

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.

Issues Switching to Android in Unity

I have developed an Augmented Relity app for iOS in Unity. It has a good performance.
The app has several scenes but one of them is much much larger than the others (about 60 targets).
The app size in iOS (uncompressed) is massive (1.9Gb) becouse it has a lot of media (images, videos, textures and 3D content).
Now I'm switching the platform to Android and I'm having a lot of trouble:
-The loading time to the principal scene is very very high (10 or more minutes) rather than 20 seconds in iOS (iPhone 4).
-The textures of the 3D content turns in black.
Is there a limitation size for a scene in Android?
Maximum memory available on android might differ per device.
Most only have 256 MB of memory available for a single application.
As for texture memory (again different per device), you might want to look at the compression used. Using the android standard ETC Unity page on Android should improve loading times. Removing Mip Maps would lower memory use and loading but also potentially decrease FPS (depending on wethere they are used or not).
With Android there is also the option to profile through ADB connection within the Unity Profiler, which could help with narrowing down to a more exact cause of the problem.

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.

Seemingly inconsistent OutOfMemory crashes on different Android devices

I am making a game which has to load all bitmaps at start because in the in-built game editor the user can put any of the sprites into the level. Also levels use various sprites without any system which would allow to load groups of sprites dynamically for each level.
After a while the are now already 250+ png images in the game with total size of 3.5MB.
The game loads most sprites (about 200) using BitmapFactory.decodeStream without any options set, and also there are about 50 other which are referenced in xml layouts of activities.
When I test on various devices, the game sometimes runs out of memory, but i can't find a pattern and even decide by HOW MUCH i have to, e.g. reduce the size of images or their number.
The phone on which i developed, HTC desire with Android 2.2 24MB VM heap size never runs OOM.
Dell Streak with Android 2.2 and 40MB VM heap size never runs OOM, too.
Motorola Milestone with Android 2.1 and 24MB VM heap size successfully loads all sprites but chokes on the few last images used in ImageView's when starting one of the activities (start menu). If I comment a few of such ImageViews out, it loads ok, but may choke on one of the other activities later. It's also not stable, probably because fragmentation happens differently in different launches.
HTC hero with 2.2 of my buddy (dunno the heap size, is it 16MB?) crashes as well.
What's most confusing is that Motorola has 24MB, the same as HTC desire. Is 2.1 implementing memory management less efficiently? (e.g. leads to more fragmentation?) Or is memory management worse by all Motorola phones? Then why does HTC hero with 2.2 crash? What's bigger in HTC desire than HTC hero?
Looks like OOM happens on older phones, but that's the only thing I've figured out so far.
If OOM only happens on older phones which are, say, 5% of the market, I can just exclude 2.1 or a more specific list from the supported devices by just gathering crash reports and excluding all that crashed from the list of supported. Otherwise I'd now need to scale down all my images by some constant factor (e.g. 1.6), which would mean resizing all the 45 levels which took days and days of designing and testing, repositioning GUI elements etc. Even after that, I'd still not be sure, on which devices the reduction of total size of bitmaps by a factor of e.g. 2 is enough to avoid OOMs.
Any advice on this?
Should I set any specific options for BitmapFactory? btw, most images have transparent bg pixels which, as far as i understand, doesn't allow getting them in 565 format.
I spent 2 days browsing here and in other places but am still at a loss.
Thank you.
I've had to deal with a simpler version of your problem - we had 3 2Mpix layers on top of each other, which, unsurprisingly, sometimes caused OOM.
In my case, instead of using 3 ImageViews on top of each other, keeping all 6 MPix in memory at all times, I manually blended the layers, thus keeping at most 4 Mpix in memory at any one time (and only 2 MPix at "rest" - the layers changed in our application).
This is a classic time-space trade-off - sacrifice efficiency (time) to gain memory (space). It was somewhat slow because you had to recycle() each Bitmap after you were done with it to ensure the memory was freed.
As for the inconsistent OOMs, it probably has to do with garbage collection. You can assume that the garbage collector is non-deterministic and thus any memory pressure becomes non-deterministic as well (depending on when the GC last kicked in).
The short summary is, you have to be very, very careful with your memory usage and there's no way around it. *
* In theory, you could allocate memory outside the Dalvik heap by using the NDK and allocating straight from the OS. It's a huge hack and the bridge between Dalvik and your allocator will be rather ugly.
First you need to find what exactly is using all of your memory. Check this out. Maybe you could be recycling bitmaps, for instance.

Categories

Resources