Out of Memory Error with tablets

alfcen

Well-Known Member
Licensed User
Longtime User
Occasionaly I am seeing error reports from users in Google Play which I often fail to decipher.
They are mostly related to large bitmaps such as used for a compass, like these two samples from
users using Nexus and Transformer tablets. I cannot replicate the errors on my phone/tablet.
Looks like not all tablets perform the same memory management.
I can't buy all tablets out there for testing.
Is there any rule I need to obey? Sorry for bothering.


java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:599)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize2(CanvasWrapper.java:498)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:491)
at anywheresoftware.b4a.keywords.Common.LoadBitmap(Common.java:1027)
at requio.com_scope.companion.imaging._labobj_click(imaging.java:634)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:165)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:153)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:149)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:55)
at android.view.View.performClick(View.java:4084)
at android.view.View$PerformClick.run(View.java:16966)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
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:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)



java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize2(CanvasWrapper.java:493)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:486)
at requio.com_nz177jp.scope_timer_plus.main._changemodes(main.java:584)
at requio.com_nz177jp.scope_timer_plus.main._activity_create(main.java:327)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:105)
at requio.com_nz177jp.scope_timer_plus.main.afterFirstLayout(main.java:84)
at requio.com_nz177jp.scope_timer_plus.main.access$100(main.java:16)
at requio.com_nz177jp.scope_timer_plus.main$WaitForLayout.run(main.java:72)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3806)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
 

thedesolatesoul

Expert
Licensed User
Longtime User
I have some of these too. I dont understand what I am missing, because theoretically I dont see myself going over memory.
My only thought was when I use a canvas on a panel, the canvas bitmap is larger on the tablet than the phone.
You first one is on LoadBitmap, what is the second one due to?
 
Upvote 0

alfcen

Well-Known Member
Licensed User
Longtime User
Hi,
Well, in this very case, 2 bitmaps (compass rose and needle) in portrait mode. 640 pixels square on the phone, 800 pixels square on the tablet.
It should not make such a big difference, also considering that a tablet has more working memory.
I am aware, though, that a 20KB 800x800 transparent PNG (compass needle) is most probably occupying memory that of the size of an equivalent bitmap (BMP).
The problem could be related to how or when or in which sequence a Canvas is initialized and drawn on.
What irritates me, too, is that a small phone (256KB memory) never complains, while tablets blessed with 1GB or so, fail.
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
An 800 square bitmap will take 800x800x4bytes=2.4MB
So two of those take up 4.8 MB
I think most devices have a heap size of 32MB so these bitmaps should hardly be a problem?
The canvas will always create a bitmap of the size of the view it is initialized on. Maybe that is the problem. Or you have multiple canvases?

What I do not however know is to how to deal with dynamic cases of OOM. For e.g. on a list of views or something.
 
Upvote 0

rmoore

Member
Licensed User
Longtime User
Don't know if this might be relevant to your problem, but I was getting Out Of Memory errors related to my use of bitmaps. I could make mine happen consistently by restarting my app a few times (rotating the display a few times would do it).

I found this solution on this forum. I call this routine from Activity_Pause. You need to use A Graham's Reflection library.



Sub RecycleCanvasBitmap ' code by agraham
Dim Obj1 As Reflector
Obj1.Target = cvs
Obj1.Target = Obj1.GetField("bw")
Obj1.Target = Obj1.RunMethod("getObject")
Obj1.RunMethod("recycle")
End Sub

Ron
 
Upvote 0

Inman

Well-Known Member
Licensed User
Longtime User
You can increase the available heap size by setting android:largeHeap="true" in Manifest file. That solved most out of memory issues for me.

With Manifest Editor, that would be SetApplicationAttribute(android:largeHeap,"true")
 
Upvote 0

alfcen

Well-Known Member
Licensed User
Longtime User
Hello Ron and Inman,
Thanks a lot for your contributions.
I tried both methods before, however, with limited success.
Anyway, both ways appear to help reduce the error frequency.
 
Upvote 0

kanaida

Active Member
Licensed User
Longtime User
I'd try LoadBitmapSample() and load a sample the size of the view you want to stick it onto. That's saved me tons of memory and improved scrolling speed. Although I do agree it's a bit strange
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
You can increase the available heap size by setting android:largeHeap="true" in Manifest file. That solved most out of memory issues for me.

With Manifest Editor, that would be SetApplicationAttribute(android:largeHeap,"true")

On a Nexus 7, this setting allocates 33% of the total memory to your program (more than 300 MB). That's a lot and probably too much. Imagine if everybody does this for his/her own app...
Most of the Out of Memory exceptions are due to bad programming, bad resource allocation, bad understanding of how the memory works, etc. This forum is full of good advices and explanations about these things. Use LargeHeap only when you're sure you've exhausted all other solutions.
And don't forget that LargeHeap does not work with Android versions < 3.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
I tried that, but got:

No resource identifier found for attribute 'largeHeap' in package 'android'
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
In the IDE open the Tools menu then Configure Paths > android.jar.

It sounds like you're compiling with a version of the Android SDK that was released before the manifest largeHeap attriibute was introduced.
So with that version of the Android SDK largeHeap does not exist.

You need to set the path to the android.jar of an SDK version that supports largeHeap - that's Honeycomb and later i think?

Martin.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I think that devices running versions of Android prior to version 3.0 will simply ignore the largeHeap manifest attribute.

I've had a quick Google but found nothing that confirms that, so unless anyone else can confirm what older versions will do with the largeHeap attribute you'll have to research it yourself.

Martin.
 
Upvote 0
Top