Avoiding java.lang.OutOfMemoryError - android

Hi all I am developing live wallpapers, and I am using lot of bitmaps. I have tested my new live wallpaper for aboute a week, and it was up and runing perfectly, but as soon as I have uploaded it to a market I keep getting this kind of exceptions : java.lang.OutOfMemoryError for both android.graphics.Bitmap.nativeCreate and android.graphics.BitmapFactory.nativeDecodeAsset. I use this kind of lifecycle of an bitmap:
I create a reference like:
Bitmap dark = null;
Bitmap cave = null;
at onCreateEngine I init them like :
cave = BitmapFactory.decodeResource(getResources(), R.drawable.cave);
dark = BitmapFactory.decodeResource(getResources(), R.drawable.dark);
here is where it trows the exception. for these images: . and after all I draw them to an canvas like this:
canvas.save();
canvas.drawBitmap(bg, new Matrix(), new Paint());
canvas.drawBitmap(dark, new Matrix(), new Paint());
canvas.restore();
What Should I do? It is better to load the dark image just one picture and draw it to the canvas width*height times? Or Are there any methods to do? I think recycle or calling onDestroy. But I do not know when to call them because the exceptions are thrown at onCreate.Are the images too big? And why it is working smoothly on my device, and on the other devices it is throwing exceptions? The bitmaps are 1484*1484 dimension big and the clouds are 250*172 dimensional big, should they be in 2^x * 2^x dimension?

Just try to use Memory Optimizer and see where are you creating Memory Leaks. You can use Eclipse Memory Analyzer(MAT) for this. Its a very common problem with using bitmaps. By using BitMaps you need to be extra careful for memory leaks.

Related

Android out of memory error while rotate a bitmap

I am currently working on a project in which one I would like to rotate a bitmap.
The first time, I create my bitmap with the following code :
myBitmap = BitmapFactory.decodeResource(getResources(), drawableResource);
Then I rotate the bitmap using the following code :
final Matrix matrix = new Matrix();
matrix.postRotate(currentRotate);
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, directionBitmap.getWidth(), directionBitmap.getHeight(), matrix, true);
I works, but after several times, the memory increases and I have the following exception :
java.lang.OutOfMemoryError: Failed to allocate a 119071756 byte
allocation with 16775968 free bytes and 96MB until OOM
It seems that the old bitmaps are still in memory. How to delete/recycle them in order to save the memory ?
Thank your for your help.
I can suggest you to use Glide library from Github.
This library works in background threads. Anyway you can perform your rotation on Background like this:
runOnUiThread(new Runnable(final Matrix matrix = new Matrix();
matrix.postRotate(currentRotate);
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, directionBitmap.getWidth(), directionBitmap.getHeight(), matrix, true);
)
In my case, the problem was with the size of the bitmaps I was using. The bitmaps I was using were of very high pixels for the given device. In such case, Android system has to descale them to lower pixel density i.e. the one that will suit your device. When you rotate the bitmap, Android system takes up a lot of memory to descale it to lower pixels. Also, Android gets busy and in some cases results in UI thread blocking.
Also, increase the heap size in your manifest file.

Out Of Memory Error in Android Studio

I'm trying to create my first android app, so I'm really new to android development. I'm trying to make a nice background image for my app. I made an image that is the exact dimensions of the device, but when I try to load it, i get the error "Failed to allocate a 218748 byte allocation with 217220 free bytes and 212KB until OOM" Here's my code:
#Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas);
protected void drawBackground(Canvas canvas) {
Bitmap background = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background2));
canvas.drawBitmap(background, 0, 0, null);
I've tried scaling it down, which works, but then it doesn't fill the entire screen. How do I resolve this issue?
You should recycle bitmap after canvas.drawBitmap(background, 0, 0, null);, or create bitmap once, in the constructor, and then use it, it is very costly to create bitmap each time in the onDraw method, it even costly to create simple objects in the onDraw, you shuold avoid from it, android:largeHeap="true" and System.gc() can't help in this case. Read this
Custom Drawing
Creating objects ahead of time is an important optimization. Views are redrawn very frequently, and many drawing objects require expensive initialization. Creating drawing objects within your onDraw() method significantly reduces performance and can make your UI appear sluggish.
There is blog that will help you to detect and prevent Out of memory issue. I wrote this based on a real problem I faced and here is the link
If you got stuck anywhere in the tutorial please let me know we can discuss and if you want to add something please suggest.

Android: Rotating large image crashes without throwing an error

I have searched and found simple code to rotate an image. I am pulling the image out of an ImageView object into a bitmap, rotating it then putting it back. I realize this is not the most effective method but I don't think it should crash without giving an error message in the CATCH block.
Here is my code. The only value passed in is "r" or "l" depending on which direction I want to rotate. Smaler images (1500x1500 or smaller) work just fine. Things go bad around the 2500x2500 size.
public void rotate(String dir)
{
try
{
float angle = (dir.equals("r") ? 90 : -90);
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Matrix matrix = new Matrix();
matrix.reset();
matrix.postRotate(angle);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
imageView.setImageBitmap(bitmap);
}
catch(Exception e)
{
Utilities.logError(e.toString());
}
}
Any clue as to why it is crashing and why it doesn't thow an exception? I just get a message "Unfortuantly process .... has stopped" and I get kicked back to the welcome screen of my app.
Oh, for kicks I set the angle to ZERO (hard coded) and it didn't crash. I suspect that it is just taking too long to rotate and Android is having a fit. But I am not sure how to confirm that as the problem or how to tell Android to wait a little longer.
Even if I reduce the preview image for the rotation, when I go to save I will have to rotate the full size image at least once and will hit this same issue. Won't I?
I can more or less guarantee without looking at the logs that you're getting an Out Of Memory Exception.
You need to use smaller images, or use a different method to rotate that doesn't use up so much memory (you're allocating 2 2500x2500 bitmaps at the same time here! that's tons!).
Try using a RotateAnimation to get your effect instead.
Hope this helps :)

When (if at all) should I use Bitmap.recycle()?

According to Android Developers site, the Bitmap.recycle() method definition is:
Free the native object associated with this bitmap, and clear the reference to the pixel data
I've developed some applications which are creating / decoding a lot of bitmaps, and put the result bitmap objects to ImageViews. Sometimes I've got the famous exceptions such as:
bitmap size excceded vm budget
and
out of memory error
Also I'm sure I don't have any memory leaks that can cause that.
After a lot of searches, I discoverd the "recycle" method, and used it to free the bitmap's native memory when no longer needed. It seems like it helped a lot.
I'm asking if that's something I'm supposed to do on this situation, because
I know the system is doing this anyway without calling it explicitly (is it? maybe I'm wrong).
Should I use this method in situations like this?
In what situations should I use this method?
Should I use this method at all?
thanks in advance.
UPDATE:
google posted this guide recently, which says:
On Android 2.3.3 (API level 10) and lower, using recycle() is recommended. If you're displaying large amounts of bitmap data in your app, you're likely to run into OutOfMemoryError errors. The recycle() method allows an app to reclaim memory as soon as possible.
in what situations should I use this method?
The Bitmaps are GC'ed by GC whenever it decides.But in some situations it may get delayed.
And always remember thumb rule in java (Maybe it applies to othe P.L also).The speed of recycling objects by GC may not be same as speed of creating objects.So sometimes the GC is slow to in recycling.
so recycle() means If you want to free memory ASAP you should call recycle()
should I use this method at all??
This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.But if you are facing the issues like bitmap size exceeded vm budget or out of memory error then you need to use this.
I do use it in operations where i know that bitmap is not going to be used anymore.
public static Bitmap getMaskedContactImage (Context context, Bitmap contactImageBitmap, int maskToBeApplied) {
Bitmap mask = BitmapFactory.decodeResource(context.getResources(), maskToBeApplied);
Bitmap output = Bitmap.createBitmap(mask.getWidth(),mask.getHeight(), Config.ARGB_8888);
final Rect finalRect = new Rect(0, 0, contactImageBitmap.getWidth(), contactImageBitmap.getHeight());
final Rect originRect = new Rect(0, 0, mask.getWidth(), mask.getHeight());
Canvas canvas = new Canvas(output);
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.BLACK);
xferPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawBitmap(contactImageBitmap, finalRect, originRect, null);
canvas.drawBitmap(mask, originRect, originRect, xferPaint);
contactImageBitmap.recycle();
mask.recycle();
return output;
}
In places like that one, im sure im not going to use the mask or the contactImage.
I found a really good resource for Bitmap processing that can be helpfull Displaying bitmaps.
Regards,
Alex

android - rendering bitmaps from native code - nativeCreate bitmaps are not cleanedup from memory

I am streaming a video in android and I decode frames in native code and then copy the pixels to a bitmap, then display the bitmap in Java using canvas.unlockandpost with a while loop for all the bitmaps.
Everything is fine, but the streaming of bitmaps is very slow and causes a crash. I only see a message on logcat saying that "low memory no more background processes".
I see on the allocation table from eclipse, that the bitmaps that I created are not getting deleted from memory, even though, I am overwritng the pixels everytime. Is there any way I can clean up the memory it is keeping.
My code is as follows.
C Code :
AndroidBitmapInfo info;
void* pixels;
int ret;
if ((ret =AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
}
memcpy(pixels, pictureRGB, 480*320);
AndroidBitmap_unlockPixels(env, bitmap);
Java Code
Bitmap mBitmap = Bitmap.createBitmap(480, 320, Bitmap.Config.RGB_565);
renderbitmap(mBitmap, 0);
canvas.drawBitmap(mBitmap, 0, 0, null);
The code shown in your question is missing some critical parts to fully understand your problem, but it sounds like you're creating a new bitmap for every frame. Since Android only allows for about 16MB of allocations for each Java VM, your app will get killed after about 52 frames. You can create a bitmap once and re-use it many times. To be more precise, you are creating a bitmap (Bitmap.CreateBitmap), but not destroying it (Bitmap.recycle). That would solve your memory leak, but still would not be the best way to handle it. Since the bitmap size doesn't change, create it once when your activity starts and re-use it throughout the life of your activity.

Categories

Resources