Out of Memory Error while loading bitmaps - android

i have an android app with 3 acitivtys:
A1 --starts--> A2 --starts--> A3 --when finished his process: starts--> A1
(so i don't "finish();" an app. i start the next activitys with "startActivity(..);" the whole time after userinteraction)
so there is a loop in these 3 activitys.
On each Activity, i display 3-9 pictures, located on the SD-card, which i load with my following function:
try
{
Uri selectedImageURI = Uri.parse(strImagePath);
File imgFile = new File(getRealPathFromURI(selectedImageURI, c));
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ivTmp.setImageBitmap(myBitmap);
}catch (Exception e)
{
return null;
}
This all works.
But sometimes (after looping a few times through my activitys), my app crashes..
Logcat tells me:
01-16 13:42:15.863: DEBUG/dalvikvm(23161): GC_BEFORE_OOM freed 10K, 9% free 59019K/64400K, paused 29ms, total 30ms
01-16 13:42:15.863: ERROR/dalvikvm-heap(23161): Out of memory on a 8018704-byte allocation.
01-16 13:42:15.863: ERROR/AndroidRuntime(23161): FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1965)
at android.content.res.Resources.getDrawable(Resources.java:660)
at android.widget.ImageView.resolveUri(ImageView.java:616)
at android.widget.ImageView.setImageResource(ImageView.java:349)
at <MyApp>.MyActivity$6.run(MyActivity.java:143)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Someone can give my some tips how to handle the crashes?
Maybe its because my activitys are set to state "paused" instead of closing them correctly?

for quick fix you can add
android:largeHeap="true" in your manifest application tag
link here:
I face OOM problem for my table in kindle and nook
Heap size (large)
android:largeHeap="true"
there specification is mentioned to use larger heap link here:
edit: use Caching Bitmaps technique link here

I had the similar problem while displaying high resolution images. I have searched and applied all the android bitmap solutions given in http://developer.android.com/training/displaying-bitmaps/index.html and the following caches mekanism in the link. but none of them work. not any right solution anywhere. Then I figured out that the problem is : I couldnt use the drawable folder structure right. I was keeping high resolution images in mdpi and hdpi folders . this cause android scale up the images to the ultra sizes. 100 kb image was causing 20 mb increase in memory thanks to the android monitor / memory section.
so I have added these ultra resolution images to xxhdpi folder , then It was FIXED suddenly. then my image slider work flawlessly

Yeah android doesnt immediately destroy activities when they are not visible to the user, but there are a number of lifecycle methods that are called depending on the current state. Check out http://developer.android.com/guide/components/activities.html#Lifecycle
You could try finishing the activities in onStop() or onDestroy() as these will be called when the activity is not visible and when the system runs low on memory respectively. :-)

This is due to the high resolution of image you have to scaling the bitmap use the following code
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap photoBitMap = Bitmap.createScaledBitmap(myBitmap,h, w, true);
ivTmp.setImageBitmap(photoBitMap);

Related

Android throwing out of memory error when trying to load 1 megabyte image

The relevant code:
runOnUiThread(new Runnable() {
#Override
public void run() {
ImageButton btn = (ImageButton) findViewById(R.id.info_image);
btn.setImageResource(currentID[currentIDPos]);
}
});
It's saying that the run method is making a 400-some megabyte allocation. My jpgs are no more than a megabyte in size. The run() method is called on a timer every 3-4 seconds or so and on click, but that shouldn't matter because from what I can tell using printlns the run() is only called once before the crash.
Edit: Here's the exception. Had to run it again to get this, it's a different amount of memory this time but still very large.
FATAL EXCEPTION: main
Process: com.grey.handsaver, PID: 32531
java.lang.OutOfMemoryError: Failed to allocate a 215151564 byte allocation with 33554400 free bytes and 100MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:988)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2580)
at android.content.res.Resources.loadDrawable(Resources.java:2487)
at android.content.res.Resources.getDrawable(Resources.java:814)
at android.content.res.XResources.getDrawable(XResources.java:572)
at android.content.Context.getDrawable(Context.java:403)
at android.widget.ImageView.resolveUri(ImageView.java:747)
at android.widget.ImageView.setImageResource(ImageView.java:398)
at com.grey.handsaver.ExerciseInfoActivity$3.run(ExerciseInfoActivity.java:128)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5430)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:913)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:706)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
Try to use picasso library for loading large image.it's having inbuilt cache functionality.
Step 1:
First write follow code in gradle.build and sync gradle.
compile 'com.squareup.picasso:picasso:2.5.2'
Step 2:
Picasso.with(context).load("YOUR IMAGE PATH").into(btn);
and write above code where we load the image.in this code you must need to provide image path and make sure image path is valid.if you really want to learn something more about this Library than please Visit this.
I hope your are clear with my Idea.
Best of Luck
Most likely the issue is that you are not clearing up the previously allocated space. Are you sure that the fragment/activity that loads these pictures is also removed from backstack? Or maybe the images themselves are not being garbage collected?
Re-do the same steps that are causing the OutofMemory Exception but make sure to switch to Memory Monitor Tab in Android Studio and check where the Memory is increasing drastically but not being freed when it should be. This should give you a head start to see where the memory leak might be.
Also possible that there is no leak, rather your pictures themselves are huge (although doesnt seems to be). In this case you should do lazy loading, cache implementation etc. or just use some third party library like Picasso which handle this for you
Alright, I figured it out. I'm using an lg g4, which uses xxxhdpi, and my images were in the drawable folder, not the drawable-xxxhdpi folder. This solved my problem without using picasso or the other methods.

Bitmap OutOfMemoryError even using recycle()

I have an app that shows a lot of activities, each one showing a bitmap that fits the 100% of the width of the screen and normally more than the 100% of the height.
When you touch the screen, a new activity is created, and in the previous activity is being called finish and recycle for the bitmap:
public void clean() {
if(this.myBitmap != null){
Log.d(DEBUG_TAG, " Cleaning "+this);
this.myBitmap.recycle();
this.myBitmap=null;
System.gc();
}
}
the problem is that the memory required is growing and growing and when i am launching more than 12-13 activities these messages are being showed at logcat:
05-05 16:03:02.909: I/dalvikvm-heap(24794): Clamp target GC heap from 65.790MB to 64.000MB
05-05 16:03:02.969: D/dalvikvm(24794): GC_EXPLICIT freed 71K, 5% free 59008K/61680K, paused 2ms+13ms, total 55ms
05-05 16:03:03.559: I/dalvikvm-heap(24794): Clamp target GC heap from 67.197MB to 64.000MB
05-05 16:03:03.569: D/dalvikvm(24794): GC_EXPLICIT freed 418K, 2% free 60521K/61680K, paused 3ms+28ms, total 109ms
after a few activities more i got this crash:
05-05 16:03:05.049: E/AndroidRuntime(24794): java.lang.OutOfMemoryError
05-05 16:03:05.049: E/AndroidRuntime(24794): at android.graphics.Bitmap.nativeCreate(Native Method)
05-05 16:03:05.049: E/AndroidRuntime(24794): at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
05-05 16:03:05.049: E/AndroidRuntime(24794): at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
05-05 16:03:05.049: E/AndroidRuntime(24794): at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
I dont know what is going wrong here, i am doing recycle() of the bitmap and also i tryed with and without System.gc(), in both cases i got the crash
Its a known bug, its not because of large files. Since Android Caches the Drawables, its going out of memory after using few images. But i found alternate way for it, by skipping the android default cache system.
Soultion:
Create a drawable folder in Assets and move the images to "drawable" folder in assets and use the following function to get BitmapDrawable
public static Drawable getAssetImage(Context context, String filename) throws IOException {
AssetManager assets = context.getResources().getAssets();
InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
Bitmap bitmap = BitmapFactory.decodeStream(buffer);
return new BitmapDrawable(context.getResources(), bitmap);
}
Refrence : https://stackoverflow.com/posts/6116316/revisions
Also that add the line below in your manifest file
android:largeHeap="true"
Use DDMS to grab a heap dump and do some analysis on the dump using Eclipse Memory Analyzer (built into Eclipse ADT or can run stand-alone). What your looking for is objects that you allocated but are not being freed. One possibility is that you are leaking activities. You say the OOM error occurs after launching 12-13 activities. Only one of the activities should be visible at a time so you can free memory from the paused activities in the onPause() or onStop() method. Again, analyzing the heap dump will give you a good idea of what is eating up the heap memory.
FYI - Bitmap#recycle() is only really necessary on Gingerbread and lower devices. On newer version of the OS bitmaps are stored on the heap and are garbage collected like other objects. See, the "Manage Memory on Android 2.3.3 and Lower" section of this document: https://developer.android.com/training/displaying-bitmaps/manage-memory.html

PhoneGap: Application crash taking portrait picture

I am using jQuery Mobile and PhoneGap to create an app that allows users to take a picture, view it on screen, and then upload it to a server application that will ultimately post it on a website.
This works well if I take the photo in Landscape mode, but crashes the application when I take a Portrait photo. As you can see from the code snippet below I am using the correctOrientation parameter to attempt to orient the photo after it is taken. Without this parameter the application doesn't crash, however the photo is in the wrong orientation when it gets displayed.
Right now I'm testing this on Sony XPERIA android phone.
Here is the code responsible for the work.
function onPhotoFail(message) {
alert('Failed because: ' + message);
}
function onPhotoSuccess(imageURI) {
var $image = $("img#upload-image");
$image.attr("src", imageURI);
}
function capturePhoto() {
navigator.camera.getPicture(onPhotoSuccess, onPhotoFail, { quality: 50, destinationType: Camera.DestinationType.FILE_URI , correctOrientation: true });
}
Here's the stack trace:
E/AndroidRuntime(31760): FATAL EXCEPTION: main
E/AndroidRuntime(31760): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
E/AndroidRuntime(31760): at android.graphics.Bitmap.nativeCreate(Native Method)
E/AndroidRuntime(31760): at android.graphics.Bitmap.createBitmap(Bitmap.java:477)
E/AndroidRuntime(31760): at android.graphics.Bitmap.createBitmap(Bitmap.java:444)
E/AndroidRuntime(31760): at org.apache.cordova.CameraLauncher.getRotatedBitmap(CameraLauncher.java:483)
E/AndroidRuntime(31760): at org.apache.cordova.CameraLauncher.onActivityResult(CameraLauncher.java:326)
E/AndroidRuntime(31760): at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:823)
E/AndroidRuntime(31760): at android.app.Activity.dispatchActivityResult(Activity.java:3908)
E/AndroidRuntime(31760): at android.app.ActivityThread.deliverResults(ActivityThread.java:2549)
E/AndroidRuntime(31760): at android.app.ActivityThread.handleSendResult(ActivityThread.java:2595)
E/AndroidRuntime(31760): at android.app.ActivityThread.access$2000(ActivityThread.java:121)
E/AndroidRuntime(31760): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:973)
E/AndroidRuntime(31760): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(31760): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime(31760): at android.app.ActivityThread.main(ActivityThread.java:3701)
E/AndroidRuntime(31760): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(31760): at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(31760): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
E/AndroidRuntime(31760): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
E/AndroidRuntime(31760): at dalvik.system.NativeStart.main(Native Method)
I've done some searching around, and I don't see anybody having this exact problem. Any help is appreciated
I would have to see your stack trace to be sure but it is probably an OutOfMemoryException. Android handles image manipulation very badly. It basically needs to load the entire image into memory where each pixel is 4 bytes, that means up to 40 megabytes for a lot of modern phone cameras.
My only suggestion right now is to try to switch the quality to 100. I know it sounds counter-intuitive but it make keep there from being as much processing in the background.
You can read my blog post talking about some of the problems with the Camera:
http://simonmacdonald.blogspot.ca/2012/07/change-to-camera-code-in-phonegap-190.html
Also, if I can see the stack trace it would help.
this thread might be a little old but the issue is still out there. I've been looking more deeply into the phonegap plugins code and noticed that the problem is, as Simon said, with Android class not handling the image operations -> loading a big bitmap via Bitmapfactory.decodeStream method. However, if you dont need to resize the image (while taking it from gallery -> you can do it later, on serverside for example) and you want to preserve the 100 quality AND you don't need to use correctOrientation option AND your destination type is FILE_URI.. simply, you just need the images URI to upload it somewhere, for example, then you need to include 3 options: targetWidth set to -1, targetHeight set to -1 and correctOrientation set to false:
navigator.camera.getPicture(cameraSuccess, cameraError, { quality: 100, targetWidth: -1,
targetHeight: -1, correctOrientation: false,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.SAVEDPHOTOALBUM});
You can find info on that in plugins code (comment on line 394, cordova 2.8.0). Dont know why its not in documentation though ;)

How to work with a lot of bitmaps and avoid the error: "bitmap size exceeds VM budget"? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Android: Strange out of memory issue
I'm trying to work with four bitmaps of 1024 x 1024, I need to have four in memory because I am creating a gallery that must show four zoomable bitmaps in landscape mode.
It is working on Motorola Droid 2.2.3, but it is failing on galaxy spica (2.1). This is the exception that i get on spica:
02-28 15:45:25.963: ERROR/dalvikvm-heap(17109): 4194304-byte external allocation too large for this process.
02-28 15:45:25.968: ERROR/(17109): VM won't let us allocate 4194304 bytes
02-28 15:45:25.973: DEBUG/AndroidRuntime(17109): Shutting down VM
02-28 15:45:25.973: WARN/dalvikvm(17109): threadid=3: thread exiting with uncaught exception (group=0x4001b180)
02-28 15:45:25.973: ERROR/AndroidRuntime(17109): Uncaught handler: thread main exiting due to uncaught exception
02-28 15:45:25.988: ERROR/AndroidRuntime(17109): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
how to solve this?
thanks
There is no easy way to solve that - single application has very low memory budget, so there is no way to keep 16MB in memory. You can use OpenGL (textures are not included into that budget), of just use one bitmap at time (or use smaller bitmaps).
You can cut the size in half by using RGB_565 versus the default ARGB_8888.
ARGB_8888 requires 4 bytes per pixel: 4*1024*1024 = 4194304 (4mb)
RGB_565 require 2 bytes per pixel: 2*1024*1024 = 2097152 (2mb)
You can set this with options to the BitmapFactory. See inPreferredConfig
However even with this you'll still have difficulty. Why not cut the size of the images down as well? I doubt you're able to show a 1024x1024 image anyway.

Android Heap Memory size doesn't looks correct

i have an Android app that displays alot of images, it works, the images are gatherd from an url, added to a que and gathered by 4 threads,stored in a cache and then displayed in a listview view 4 images for row, there are abot six rows at each time on the screen. There is a total of usually 90 images.
The rows(and imageviews) are always recycled, so the amount of items is always the same and i'm not initializing anything.
This seems to work quite fine, i have always an average used heap size of 13MB.
The problem i have is that at the beginning mi max heap size is quite small and i get GC messages like:
01-20 16:48:39.191: D/dalvikvm(9743): GC_FOR_ALLOC freed <1K, 31% free 12048K/17351K, paused 25ms
but the more i scroll up down the view the heap size grows more and more untile i get things like
01-20 17:02:05.339: D/dalvikvm(11730): GC_FOR_ALLOC freed 544K, 72% free 13871K/49159K, paused 35ms
as you see even if the used is the same the maximum is increased even if i never got to that limit. and the true problem is that at this point i start to get outofmemory errors.
Can someone explain me what's wrong?
Thanks!
What version of Android are you using? If you're testing on pre 3.0 (ie 2.x), the byte arrays that store most of the information in Bitmaps are allocated and stored in native memory. This means that in heap dumps and in the GC notifications, you only see the small amount of memory used for pointers in Bitmaps, rather than the actual size.
For more information check out this google IO talk on memory management and detecting memory leaks: http://www.youtube.com/watch?v=_CruQY55HOk
Also I've worked on several apps doing similar things. My guess is that either your cache size is way too large, or (more likely) the images you're displaying and storing in the cache are much larger than the size you actually want. If you display a bitmap in an image view, the imageview will store the original bitmap in memory, even if it is significantly larger than what would actually fit in the view. Try resizing the images from disk to at least closer to the appropriate size before trying to display them: How do I scale a streaming bitmap in-place without reading the whole image first?
To cache my Images I use Map<String, Drawable> drawableMap. On a OutOfMemoryError I call this function:
private void cacheLeeren()
{
int size = drawableMap.size();
int del = (int) (size * 0.3);
Set<String> s = drawableMap.keySet();
for (String t : s)
{
if (del >= 0)
{
drawableMap.put(t, null);
del--;
}
}
}
I think it's not the best way...but it works ;-)
My guess is that your app reaches a very high peak of memory usage for a short time. It's true that on average you only use 13MB but if your heap grows to as much as 50MB, it means that momentarily you've consumed much more memory than you're thinking.
Let's try to figure out where this is happening. You've mentioned that you're using an LRU cache. This cache frees memory as soon as it fills up. My guess is that you're starting to free memory too late, and this memory isn't freed immediately - since it depends on the system GC. Whenever you're freeing some items from the cache, try to call System.gc() manually.
You've also mentioned that you're calling Bitmap.recycle(). To the best of my knowledge this is useless on Android 3+ because the native heap is no longer used for bitmaps. Since all bitmaps are on the dalvik heap, they will be freed by the GC.. You can't rush this like before unless you call System.GC() yourself.
Another idea for your source of problems is heap fragmentation. See my previous SO answer to a similar issue in this question.

Categories

Resources