Wednesday 8 August 2012

Memory Management in Android Application

If you are doing any work on Android that involves large bitmaps, then you have probably run into this error. It is nothing you did. Rather, it is an underlying bug in the Android OS. In this article, we will look at why the error occurs and how to fix it.
WHY?
The Dalvik VM limits the amount of memory that any Android application can use to either 16 or 24 MB. There is no way to change this allocation programmatically. In fact, the only way to get around it is to alter the Android OS code and recompile this. That might work on an individual device, but it obviously cannot be done for applications you are selling on the market.
Now 16 MB is actually more than enough to run even complicated games or handle large images, so why does the VM run out of memory? The answer is in the OS. There is a bug in the Android system that prevents it from properly releasing bitmaps stored in memory once the program is through with them. The only way the OS will release this memory is when the application ends, and even then it takes some time. There are three basic fixes to get around this problem and which one you use will depend on the type of application you are writing.

SOLUTION 1

The first solution can be found at this website:
http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue
Basically, the solution involves scaling the bitmap and reducing the amount of memory it uses. This does not solve the problem, it simply minimizes its impact. This solution will work if you are only using a few bitmaps and other memory demands are low.

SOLUTION 2

The next solution deals with clearing the bitmaps from memory. It is not just a solution to this problem, but probably a good practice for any programming application. Basically, you are clearing the bitmap when you are finished with it and thus helping to ensure that the garbage collection process takes care of it sooner rather than later.
Bitmap.recycle(); will immediately mark a bitmap for garbage collection. This code should be used for each bitmap, to set it to explicitly be cleared when it is no longer needed. This will take care of most of the VM memory issues related to bitmaps. In some cases, however, it will be necessary to also include the following.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;
One or both of these lines of code may be necessary to ensure that resources are being cleared when they are no longer used. In the first line, the array is being limited in size and, more importantly, is be allocated to temporary storage. This helps to ensure it will be cleared as soon as possible.
In the second line, the resources are being set as purgeable, something similar to temporary storage. This also marks them for garbage collection at the earliest possible opportunity.

SOLUTION 3

The above solutions work in the majority of cases. However, I have found instances where the VM simply will not let go of the resources without completely ending the application. This is, of course, hugely inconvenient and incredibly frustrating. In this case, the solution I have found to work is this:
System.exit(0);
This causes the VM to stop running and will force the current activity to exit. All objects are marked for finalization by this line, making them all immediately available for garbage collection. In order to implement this line in a given application, you want to call it on activity that can be ended and then will force the application to return to an underlying activity, such as a menu screen or launch screen. This may require that you change the way your program works, but it will release the memory resources and clear the bitmaps. This solution is not the most elegant, but it is guaranteed to work when nothing else does.
So there you have it, three ways to fix the VM OOM Error on Android devices. The problem was supposed to have been fixed in the 2.2 release of Android, but I find that it still happens. So, until Android gets the problem solved, one of these three solutions will have to do. If you learn of or discover another way of dealing with the problem, I'd love to hear about it in the comments. Happy programming.