PlayN Android 2.3.x OutOfMemory - android

In our app we have a lot of images. When they needed we get them in
such way: PlayN.assets().getImage("imageURL");
In android 2.3 there is limit for 24mb of bitmap resources. So, while
showing images on Screen2(let's say Game) i must hide (unload) images
from Screen1(lets say Intro).
I have reference to image from Screen1 and i can call clear() method:
CanvaseImage referenceToImage - i need to unload,
referenceToImage.canvas().clear();
BUT, - this way do not unload image from android memory in 2.3.x -
( Android: Bitmap recycle() how does it work?...
this post tell that i should call recycle() on bitmap, since bitmaps
are stored in non-management memory and cant be shrinked from there by
GC.)
and i have such stackTrace for android if images from Screen1 are not
unloaded from memory:
06-11 09:16:45.197: E/AndroidRuntime(23621): FATAL EXCEPTION: GLThread
10
06-11 09:16:45.197: E/AndroidRuntime(23621):
java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap
Size=9479KB, Allocated=6032KB, Bitmap Size=23347KB)
06-11 09:16:45.197: E/AndroidRuntime(23621): at
android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
06-11 09:16:45.197: E/AndroidRuntime(23621): at
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:694)
06-11 09:16:45.197: E/AndroidRuntime(23621): at
playn.android.AndroidAssets.decodeBitmap(AndroidAssets.java:158)
06-11 09:16:45.197: E/AndroidRuntime(23621): at
playn.android.AndroidAssets.doGetImage(AndroidAssets.java:79)
06-11 09:16:45.197: E/AndroidRuntime(23621): at
playn.core.AbstractAssets.getImage(AbstractAssets.java:39)
Is there some way to call playN 's magic for recycling bitmaps in
Android 2.3.x memory model?

Have you already taken a look at the Google article about memory managment? They really give a fairly in depth explanation of how to deal with that bitmap issue.

why don't you use LruCache for caching bitmaps? see article here

Related

Using Fresco for caching leads to OOM on some devices

INTRODUCTION:
I work on an android app which has a lot of images. These images are displayed within several recycler views and view pagers. For caching the images I use Fresco which is initialised like this in Application class:
Fresco.initialize(this, ImagePipelineConfig
.newBuilder(getApplicationContext())
.setBitmapMemoryCacheParamsSupplier(new BitmapMemoryCacheParamsSupplier(getApplicationContext()))
.setDownsampleEnabled(true)
.build());
When images are displayed within RecyclerView I use SimpleDraweeView and are loaded like this:
val imageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse(imageUrl))
.setResizeOptions(ResizeOptions(50, 10))
.build()
(itemView as SimpleDraweeView).setImageRequest(imageRequest)
Should also be noted that for each request in order to avoid memory caching the images the following line is called
Fresco.getImagePipeline().evictFromMemoryCache(Uri.parse(imageUrl))
I also load images within view pagers where I use ZoomableDraweeView need also for zooming in, for those cases images are loaded like this:
val view = ZoomableDraweeView(container.context)
view.setAllowTouchInterceptionWhileZoomed(true)
view.controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageUrls[position]))
.setResizeOptions(ResizeOptions(50, 20)).build()).build()
Also for these requests I avoid using the memory caching and I use
Fresco.getImagePipeline().evictFromMemoryCache(Uri.parse(imageUrls[position]))
As well should be noted that each time the user leaves these Activities that contain images I have this:
#Override
protected void onStop() {
super.onStop();
Fresco.getImagePipeline().clearMemoryCaches();
}
THE PROBLEM:
The issue is that on some devices at some point while scrolling through these images my app crashes with Out Of Memory
QUESTION
Is there any way I could improve the Fresco setup, or is there anything I'm missing that could help me get rid of OOM ?
UPADTE WITH CRASH LOG:
java.lang.OutOfMemoryError: Failed to allocate a 2833932 byte allocation with 1972896 free bytes and 1926KB until OOM
E at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
E at android.graphics.Bitmap.nativeCreate(Native Method)
E at android.graphics.Bitmap.createBitmap(Bitmap.java:975)
E at android.graphics.Bitmap.createBitmap(Bitmap.java:946)
E at android.graphics.Bitmap.createBitmap(Bitmap.java:913)
E at android.graphics.drawable.VectorDrawable$VectorDrawableState.createCachedBitmapIfNeeded(VectorDrawable.java:834)
E at android.graphics.drawable.VectorDrawable.draw(VectorDrawable.java:318)
E at android.graphics.drawable.LayerDrawable.draw(LayerDrawable.java:916)
E at com.facebook.drawee.drawable.ForwardingDrawable.draw(ForwardingDrawable.java:185)
E at com.facebook.drawee.drawable.ScaleTypeDrawable.draw(ScaleTypeDrawable.java:123)
E at com.facebook.drawee.drawable.FadeDrawable.drawDrawableWithAlpha(FadeDrawable.java:302)
E at com.facebook.drawee.drawable.FadeDrawable.draw(FadeDrawable.java:289)
E at com.facebook.drawee.drawable.ForwardingDrawable.draw(ForwardingDrawable.java:185)
E at com.facebook.drawee.generic.RootDrawable.draw(RootDrawable.java:81)

why android asks for a huge memory allocation for a small photo?

I am trying to load a jpeg photo with a size of 965KB on my android phone. The code is below. When I run the code, the app crashes.
Button _btn = (Button) findViewById(R.id.btn1);
_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Drawable _draw = getResources().getDrawable(R.drawable.sea, null);
}
});
This is the crash log.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.a3sumatch.multipart, PID: 29240
java.lang.OutOfMemoryError: Failed to allocate a 362797068 byte
allocation with 8388608 free bytes and 254MB 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:1080)
at
android.content.res.Resources.loadDrawableForCookie(Resources.java:2761)
at android.content.res.Resources.loadDrawable(Resources.java:2654)
at android.content.res.Resources.getDrawable(Resources.java:833)
at
com.a3sumatch.multipart.MainActivity$1.onClick(MainActivity.java:40)
at android.view.View.performClick(View.java:5205)
at android.view.View$PerformClick.run(View.java:21176)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:5611)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
I am trying to load a jpeg photo with a size of 965KB on my android phone
That is an absolutely massive photo. JPEG, like PNG and WebP, is a compressed file format. To put that in perspective, a 3229x2480 photo of my balding head is 829.3KB in a JPEG. I would expect yours to be a bit larger in each dimension. That resolution is higher than the resolution of any Android device screen that I know of.
Your OutOfMemoryError is for a 362797068-byte allocation. A Bitmap is an uncompressed version of the image. 362797068 bytes is equivalent to about a 9524x9524 square image (and 4 bytes/pixel).
So, you need to do two things:
If you have this image in res/drawable/, move it to res/drawable-nodpi/
Reduce the resolution of this image by at least a factor of four along each dimension

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.

Out of Memory Error while loading bitmaps

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);

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.

Categories

Resources