When loading bitmap with "BitmapFactory.decodeResource" app crashes - android

I'm developing a game for little children, which contains different educative exercises.
In one of them I need a picture background, so I'm loading it and scale it with Matrix to fill screen. But sometimes loading picture causes crash.
public DrawThread(SurfaceHolder surfaceHolder, Resources resources, float screen_x_max, float screen_y_max){
this.surfaceHolder = surfaceHolder;
screenWidth=screen_x_max;
screenHeight=screen_y_max;
// picture for bg
picture = BitmapFactory.decodeResource(resources, R.drawable.background);
...
}
At the end of this thread I recycle it and null.
if (this.picture!=null)
{
this.picture.recycle();
this.picture=null;
}
But app still crases. There is error log:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:494)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:370)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:393)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:419)
at lexu.me.childstudy_lite.DrawThreadFindAnimals2.<init>(findAnimals2.java:271)
at lexu.me.childstudy_lite.findanimals2_view.surfaceCreated(findAnimals2.java:186)
at android.view.SurfaceView.updateWindow(SurfaceView.java:548)
at android.view.SurfaceView.dispatchDraw(SurfaceView.java:353)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
Thanks.

This is a classic problem on Android.
This should provide you with plenty of tips and approaches :
Lazy load of images in ListView

You are getting an Out Of Memory Exception. To avoid this, have a look at this link:
android how to handle out of memory exception
There is a ton of information on the web that will help you with this problem.
I hope this helps.

By down sampling bitmap, you can avoid OME. Have a look at following link. Hope it helps.
Android:Issue Image resolution
Edit: In that link, its taking images from Asset folder. You can modify it according to your need.

Related

how to relase /free / destroy AnimationDrawable because I got OutOfMemory issue?

I am using AnimationDrawable in my all five Activities. I am getting outofMemory error after some time.
problem is related to Virtual Heap Memory and I am finding a way to remove all the earlier/pervious animation when I tap on the new Activity.
I tried some way to :
1) Runtime.getRuntime().gc();
2) activity_name.finish();
3) startGirlBlinking.stop();
iView_cow.setBackgroundDrawable(null);
Logcat :
E/AndroidRuntime(11449): java.lang.OutOfMemoryError
E/AndroidRuntime(11449): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
E/AndroidRuntime(11449): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:577)
E/AndroidRuntime(11449): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:445)
Got help to reslove the Application crash but not for long. I need a valueable solution for this.
How to resove this thing. Plase give me the way to do this.
Extends your AnimationDrawable with this:
public void Recycle() {
for (int i = 0; i < getNumberOfFrames(); ++i){
Drawable frame = getFrame(i);
if (frame instanceof BitmapDrawable) {
((BitmapDrawable)frame).getBitmap().recycle();
}
frame.setCallback(null);
}
setCallback(null);
}
Can you Please Try Like This:
((AnimationDrawable)(someButton.getBackground())).stop();
someButton.setBackgroundDrawable(null);
someButton.setBackgroundResource(R.drawable.animation);
I suppose the problem is that the size of resource you decoded is too big. You should use public static Bitmap decodeResourceStream (Resources res, TypedValue value, InputStream is, Rect pad, BitmapFactory.Options opts) to scale down the resource.
It looks like the bitmap is too big for the device you're running it on. I would suggest doing the following:
Read the documentation here on good practice for handling bitmap - specifically loading large bitmaps efficiently and managing bitmap memory - http://developer.android.com/training/displaying-bitmaps/index.html
Use a graphics program to scale down the bitmap and place it in the according folders - xhdpi/hdpi/mdpi, etc
Look at changing the Bitmap.Config (options.inPreferredConfig) value when decoding the bitmap - http://developer.android.com/reference/android/graphics/Bitmap.Config.html

Avoiding java.lang.OutOfMemoryError

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.

OutOfMemoryError: bitmap size exceeds VM budget on loading DICOM images

I have the following code which i took from another application
public static Bitmap createBitMap(DicomObject dcmObj) {
short[] image = dcmObj.getShorts(Integer.parseInt("7FE00010", 16));
float wc = dcmObj.getFloat(Integer.parseInt("00281050", 16));
float ww = dcmObj.getFloat(Integer.parseInt("00281051", 16));
Bitmap bitMap = Bitmap.createBitmap(dcmObj.getInt(Tag.Columns), dcmObj
.getInt(Tag.Rows), Bitmap.Config.ARGB_8888);
bitMap.copyPixelsFromBuffer(LocalImport.makeBuffer((localImport
.applyWindowing(image, wc, ww)), dcmObj.getInt(Tag.Columns),
dcmObj.getInt(Tag.Rows)));
return bitMap;
}
What I am trying to do is load few Dicom images from the SD Card read the attributes and display them in a grid.
The above function works fine with the application but when i integrate the same code to my application it crashes.
I tried debugging, but the values of the variables are the same.
Until changes are made to Android, the only way to allocate buffers larger than the VM limit is to allocate them in native code. In native code you can allocate as much memory as is physically available to the linux system underneath Android. I've tested this with my own applications and have allocated bitmaps larger than 150MB. Managing bitmaps in native code will then necessitate writing code which renders "views" of the bitmap into a display-sized image that is managed by Java.
the crash was because the animations in the main ui was taking up lots of memory.
the Sample application i had copied the code dint have any animations.
guess increasing the size of the memory allocated in the emulator can solve the issue(dint try it out yet).
But atleast i know its not because of any deallocations i hadnt done or logical errors..
Thanks all for the help :)

Android Development: Bitmaps on surfaceview leak Memory or too big?

My game uses surfaceview(I know I should use GL).
I draw alot of bitmaps to my game character world controll so on. And i run into this when I opened my LogDog:
08-05 10:17:29.151: ERROR/dalvikvm(24048): Out of memory: Heap Size=5379KB, Allocated=2735KB, Bitmap Size=20576KB, Limit=32768KB
I dont know if it is leak or what.
My Allocation Tracker shows:
like 30:
138 96 char[] 9 android.content.res.AssetManager getCookieName
Then
Tons of:
32 80 android.graphics.BitmapFactory$Options 9 android.graphics.BitmapFactory decodeResource
And last:
Like 30:
141 56 android.graphics.Bitmap 9 android.graphics.BitmapFactory nativeDecodeAsset
And also some more of simular ones.
Here is some code that I think drains my memory:
player = BitmapFactory.decodeResource(getResources(), R.raw.ghostright);
world = BitmapFactory.decodeResource(getResources(), R.raw.lvl2);
thumb = BitmapFactory.decodeResource(getResources(), R.raw.thumb);
resized = Bitmap.createScaledBitmap(player, width/10, width/6, false);
player = resized;
resized = Bitmap.createScaledBitmap(world, height*10, height, false);
world = resized;
resized = Bitmap.createScaledBitmap(thumb, height/6, height/6, false);
thumb = resized;
I heard that I should use resycle but I dont know where because I always use the bitmaps
//Simon
PS: I really need help -.-
I use a lot of bitmaps on SurfaceView too and don't have this problem.
When it comes to animated sprites, you can use a sprite sheet rather than load them individually frame by frame.
You don't need to use the reference "resized" you can just say:
player = Bitmap.createScaledBitmap(player, width/10, width/6, true);
the old bitmap will lose its reference and be collected by GC. Note that I placed TRUE for bitmap filtering when rescaling to make a better quality.
On some devices onSizeChanged can happen two times which may resize bitmaps twice, if that is where you are doing your scaling.
The format of loaded bitmaps does metter whether it is ARGB_4444 or ARGB_8888 etc So you may need to explore this option and if you can use a format which requires less memory yet it has a good enough quality for your game. Of course the rule is not to load images into memory bigger than they are needed and when they are needed.
It dosen't have to be a memory leak, it could just be that you have so large bitmaps that they want to allocate to much memory. Here's a good method to determine how much memory a bitmap is going to take: W*H*8. So if you have a bitmap that's 300*300 px it's 300*300*8 = 720 kb.
Figure out how much allocated heap you have at any given time and see if it increases with time even though you know that you're not allocating new bitmaps. If so, then yes, you have a memory leak. If, however, your app crashes right on startup, then you are probably just exceeding heap limit.

Bitmap size exceeds VM budget, not understanding why

I've looked all over for "Bitmap size exceeds VM budget" problems, but none of the solutions seem applicable for me. I am not understanding why my program sometimes throws this error because they way I'm using it doesn't seem to cause any possible memory leaks. My stack traces are pointing to the BitmapFactory.decodeResource() method. I've got a background image that I'm using to draw on a Canvas and this is how I've been initializing it:
Bitmap backgroundImage = BitmapFactory.decodeResource(getResources(),
R.drawable.background);
backgroundImage = resizeImage(backgroundImage, w, h);
This is how I've been using it:
canvas.drawBitmap(backgroundImage, 0, 0, paint);
I thought that putting backgroundImage = null in the onDestroy method would help, but that did nothing. There is not other reference to the background image resource in my program except in an XML file, but I don't think that affects it. Could someone explain to me why this is happening and how to fix it?
By the way, there is not screen orientation changes involved in this app.
You need to free the bitmap pixels when you're done with it. You mentioned that you set its value to null, but that only makes it eligible for GC, it does not explicitly tell the VM that you're done with those pixels, and that now is a good time to free them.
Before you set it to null, simply call Bitmap#recycle() on the Bitmap:
protected void onDestroy() {
if (this.backgroundImage != null) {
this.backgroundImage.recycle();
this.backgroundImage = null;
}
}
Additionally, you may be wasting resources in your resizeImage() method, which you did not provide code for. It's much more efficient to do proper down-sampling of the Bitmap at decode-time, rather than loading the full-size Bitmap, and then scaling it down from there.
The general technique is to use the 3-argument version of BitmapFactory.decodeResource(), with BitmapFactory.Options#inJustDecodeBounds for a first-time-pass in order to get the width/height of the Bitmap (although in your case, since it comes from the app's resources, there's no reason you should even have to do that.. but I'll explain it anyway); then determine a proper samplesize based on the target size, and decode the bitmap a second time. That usually results in much less memory usage, especially for very large images (e.g., with inSampleSize set to 2, it decodes the full-size Bitmap, but only allocates enough memory for a Bitmap of half the original size, downscaling the Bitmap in the process).

Categories

Resources