resources limit

Monkey Targets Forums/Android/resources limit

dave.h(Posted 2011) [#1]
is there a limit to how many resources we can use.Including sounds and spritesheets i load 18 resources into my game.if i try to load 19 then the game always force closes.it may be that ive not enough memory on my phone but i thought id check if anyone new about any limits that may be set


dave.h(Posted 2011) [#2]
never mind i just tried it on my galaxy tab and it ran fine so by process of elimination its probably not enough memory on my phone.


therevills(Posted 2011) [#3]
What was the 19th resource? (sound or image - what size in pixels/memory)

Did you run it thru the debugger (DDMS) and if so what was the error?

What phone are you using?

With Pirates I am loading the following on startup:

* 4 bitmap fonts
* 18 sounds
* 31 images


dave.h(Posted 2011) [#4]
this is what ddms says but i dont understand it


06-12 03:08:51.373: WARN/dalvikvm(11194): threadid=21: thread exiting with uncaught exception (group=0x4001b160)
06-12 03:08:51.373: ERROR/AndroidRuntime(11194): Uncaught handler: thread GLThread 11 exiting due to uncaught exception
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): java.lang.NullPointerException
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): at com.monkey.gxtkApp.Die(MonkeyGame.java:443)
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): at com.monkey.gxtkApp.InvokeOnRender(MonkeyGame.java:527)
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): at com.monkey.gxtkApp.onDrawFrame(MonkeyGame.java:452)
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
06-12 03:08:51.383: ERROR/AndroidRuntime(11194): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
06-12 03:08:51.383: ERROR/SemcCheckin(11194): Get crash dump level : java.io.FileNotFoundException: /data/semc-checkin/crashdump
06-12 03:08:51.393: WARN/ActivityManager(1138): Unable to start service Intent { act=com.sonyericsson.android.jcrashcatcher.action.BUGREPORT_AUTO cmp=com.sonyericsson.android.jcrashcatcher/.JCrashCatcherService (has extras) }: not found


i have 8 sounds
11 png images
1 bitmap font

the above will run but if i try to add another png image the phone wont take it and it has 256 meg ram which is easily enough.it will however run on my galaxy tab.Its really got me confused because it cant be a memory issue.
The size of the image i try to load is only 3.64kb
my phone is an experia x 10

any help on this would be greatly appreciated


therevills(Posted 2011) [#5]
This one? http://www.gsmarena.com/sony_ericsson_xperia_x10-2964.php

Android is throwing a null pointer exception when trying to draw the image.

Can you post your code and images? If not can you show us how you are loading the images and the exact filenames (uppercase/lowercase etc).


dave.h(Posted 2011) [#6]
I will post the code tommorrow but the thing is i never actually try to draw thoses images all i did was attempt to load them into memory and its weird that it works on my galaxy tab.that is the right phone as well.ok its 4am here i need some kip thanks for your help


dave.h(Posted 2011) [#7]
ok i delclare them like so

Global menu_pic :Image
Global exp_sprites :Image
Global main_sprites :Image
Global back :Image
Global text :Image

Global main_background:Image
Global main_background1:Image
Global main_background2:Image
Global main_background3:Image
Global main_background4:Image

'Global main_background5:Image
'Global main_background6:Image


And i load them in oncreate like so

Method OnCreate:Int()
SetFont(LoadImage("font_16.png",16,16,64))
play_sound=False
SCREEN_WIDTH = DeviceWidth()
SCREEN_HEIGHT = DeviceHeight()

#If TARGET="android"
shoot=LoadSound( "grenade.ogg" )
beep=LoadSound( "beep1.ogg" )
plasma_shoot=LoadSound( "plasma_shoot.ogg" )
laser=LoadSound( "flak_laser.ogg" )
spark=LoadSound( "spark.ogg" )
fire=LoadSound( "Fire.ogg" )

#Else
shoot=LoadSound( "grenade.wav" )
beep=LoadSound( "beep1.wav" )
plasma_shoot=LoadSound( "plasma_shoot.wav" )
laser=LoadSound( "flak_laser.wav" )
spark=LoadSound( "spark.wav" )
fire=LoadSound( "Fire.wav" )

#Endif

main_sprites=LoadImage("sprites.png")
back=LoadImage("back2.png")
text=LoadImage("text.png")
exp_sprites=LoadImage("sprites_2.png")
menu_pic=LoadImage("nebula.png")
main_background=LoadImage("lev1.png")
main_background1=LoadImage("lev2.png")
main_background2=LoadImage("lev4.png")
main_background3=LoadImage("level5.png")
main_background4=LoadImage("lev6.png")


' main_background5=LoadImage("lev7.png")
' main_background6=LoadImage("up_lev2.png")
' maps=LoadImage("maps.png")

create_array()
SetUpdateRate 25
PlayMusic("thunder.ogg",1)

Return 0
End



if i remove the remark and try to load the images at

' main_background5=LoadImage("lev7.png")
' main_background6=LoadImage("up_lev2.png")
' maps=LoadImage("maps.png")

it always force closes on the phone yet it will run on a galaxy tab and it also runs in HTML5


Dima(Posted 2011) [#8]
Hard to say without rest of code. I don't see maps:Image or the sounds defined anywhere. Maybe try adding manual checks after loading each resource to see if they load properly? For instance level5 filename is different from the rest. Maybe try not loading any sounds while testing the graphics problem.


therevills(Posted 2011) [#9]
Nothing looks too wrong there - logically anyway ;)

I thought it was only one image that was causing your issue?

Anyway how big are your lev*.pngs?

Does it even get to the rendering stage?


dave.h(Posted 2011) [#10]
no its not one specifically it just wont load any more than the ones already loaded.The sounds are defined but i didnt paste that as it appears only the images are causing the problem. my lev pngs vary from about 4kb to 40 kb.Also it doesnt get to the rendering stage on the android phone but works fine in html5 and galaxy tab and glfw but not flash.

I can do a workaround for this which is to display the maps using a 2d tile array like so

For Local k=0 to 110
DrawImageRect( main_sprites, pathx[k]*32, pathy[k]*32, 643, 345, 32, 32, 0 )
Next

The only problem with this is that there is a very noticable difference in framerate on android which is the target im aiming at.

the largest pngs are

sprites 814x428 = 201kb
sprites_2 1025x454 =491 kb
text 804x553 =188kb
nebula 640x480 =443 kb
back2 640x480 =269 kb

all the level pngs are 640X480 and vary between 4 and 40 kb
i dont know if this info helps any

i will try turning off some of the sounds and see if that helps .


dave.h(Posted 2011) [#11]
ok just done a test and for every sound that i turn off i can load an extra level.png.arrrgghhh :(


Dima(Posted 2011) [#12]
Try manual checking after each image load : If Not img. or something like that to see if some image doesnt load proper. I also recall that using power 2 images was recommended mayby try resizing all backgrounds to 512:512 and draw stretched to full screen, otherwise a 640:480 image may get sized to 1024:1024 internally (not sure here). Also you could probably load one background per level instead of preloading all levels.


dave.h(Posted 2011) [#13]
i will try the power 2 method and stretching but ive already tried loading the background per level and it didnt work maybe i wasnt using discard in the right place but will look into it again. i could also put 3 levs onto one larger png and use DrawImageRect but this doesnt solve the real prob rather than put it off till later.thanks for the suggestions though.


therevills(Posted 2011) [#14]
Also you could probably load one background per level instead of preloading all levels.


This is what I did for Pirates (only for the background images).

Could you write a small project which reproduces the issue using mockup images and sounds?


dave.h(Posted 2011) [#15]
ok ive managed to reproduce the error heres my code

Import mojo

Global shoot:Sound
Global beep:Sound
Global plasma_shoot:Sound
Global laser:Sound
Global spark:Sound
Global fire:Sound

Global menu_pic :Image
Global exp_sprites :Image
Global main_sprites :Image
Global back :Image
Global text :Image
Global main_background:Image
Global main_background1:Image
Global main_background2:Image
Global main_background3:Image
Global main_background4:Image
Global main_background5:Image
Global main_background6:Image

Class MyGame Extends App
Method OnCreate()

shoot=LoadSound( "grenade.ogg" )
beep=LoadSound( "beep1.ogg" )
plasma_shoot=LoadSound( "plasma_shoot.ogg" )
laser=LoadSound( "flak_laser.ogg" )
spark=LoadSound( "spark.ogg" )
fire=LoadSound( "Fire.ogg" )

main_sprites=LoadImage("sprites.png")
back=LoadImage("back2.png")
text=LoadImage("text.png")
exp_sprites=LoadImage("sprites_2.png")
menu_pic=LoadImage("nebula.png")
main_background=LoadImage("lev1.png")
main_background1=LoadImage("lev2.png")
main_background2=LoadImage("lev4.png")
main_background3=LoadImage("level5.png")
main_background4=LoadImage("lev6.png")
main_background5=LoadImage("alllevels.png")
'IF I TRY TO LOAD THIS FILE I GET A FORCE STOP ERROR THIS FILE IS JUST A COPY OF ALLLEVELS.PNG
' main_background6=LoadImage("alllevels2.png")

'IF I TRY TO LOAD THIS FILE IT WILL WORK
' main_background6=LoadImage("lev7.png")

SetUpdateRate 25
Return 0
End

Method OnUpdate:Int()
Return 0
End

Method OnRender:Int()
Cls 0,0,0
DrawText("THIS IS JUST A TEST",50,50)
Return 0
End
End

Function Main:Int()
New MyGame
Return 0
End


this works on html5 perfectly im really beggining to think its got something to do with file sizes as i can load a few more into memory when
my background images are smaller.The thing is i have plenty of spare ram on my phone.


Jesse(Posted 2011) [#16]
I am not sure if for android also but Mark mentioned this for GLFW:
http://www.monkeycoder.co.nz/Community/post.php?topic=188&post=1227
is the image bigger than that in width or height?
it might be the cause of the problem.
he didn't modified it as there was already an alternative solution for the problem.


dave.h(Posted 2011) [#17]
no its not but i have come up with an alternate fix. i resize 12 of the levels to 320 x240 then save them in one png file which is 963x722.I then use drawimagerect as scale them by 2.It works but there is a slight loss in resolution.


dave.h(Posted 2011) [#18]
hmm ive now discovered that this error only seems to happen when i compile in debug mode.Ive just recompiled my program to android with more levels in release mode and it works fine.Wish i'd tried that first :(


therevills(Posted 2011) [#19]
Maybe raise a bug... the code should work in both versions, although I never run debug in Android, its really really slow!


dave.h(Posted 2011) [#20]
ha what a noob i am ive been running it in debug all the time and really struggling to improve my framerates.


Loofadawg(Posted 2011) [#21]
Trying to improve your framerates,

Guess what... you just did! ;^)


FlameDuck(Posted 2011) [#22]
If it was a memory issue, the JVM would throw an OutOfMemoryError, not a NullPointerException. Could you provide a zip that reproduces the issue?


dave.h(Posted 2011) [#23]
hi flameduck thanks for the reply and to my prob and with it not working on my mates phone but it does seem to be because i compiled it in debug mode rather than release as i dont get these errors now and it works fine on my mates phone.The above code i posted causes this error in debug mode but varies slightly depending on the size of the files i loaded. for example if the files were smaller i may have been able to load a couple more before it force crashed.


Xaron(Posted 2011) [#24]
I have the same issue now on a Nexus phone. It works on my Desire HD but NOT on a Nexus where I get:

10-04 12:37:00.777 E/AndroidRuntime(8991): FATAL EXCEPTION: main
10-04 12:37:00.777 E/AndroidRuntime(8991): android.view.InflateException: Binary XML file line #77: Error inflating class android.widget.ScrollView
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.createView(LayoutInflater.java:518)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:568)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.android.internal.app.AlertController.installContent(AlertController.java:205)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.app.AlertDialog.onCreate(AlertDialog.java:251)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.app.Dialog.dispatchOnCreate(Dialog.java:307)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.app.Dialog.show(Dialog.java:225)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.app.AlertDialog$Builder.show(AlertDialog.java:802)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.splash.gxtkAlert.run(MonkeyGame.java:518)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.os.Handler.handleCallback(Handler.java:587)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.os.Handler.dispatchMessage(Handler.java:92)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.os.Looper.loop(Looper.java:130)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.app.ActivityThread.main(ActivityThread.java:3683)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at java.lang.reflect.Method.invoke(Method.java:507)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at dalvik.system.NativeStart.main(Native Method)
10-04 12:37:00.777 E/AndroidRuntime(8991): Caused by: java.lang.reflect.InvocationTargetException
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at java.lang.reflect.Constructor.constructNative(Native Method)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.LayoutInflater.createView(LayoutInflater.java:505)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	... 23 more
10-04 12:37:00.777 E/AndroidRuntime(8991): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.content.res.Resources.loadDrawable(Resources.java:1709)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.content.res.Resources.getDrawable(Resources.java:581)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.widget.ScrollView.setOverScrollMode(ScrollView.java:1396)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.View.<init>(View.java:1879)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.View.<init>(View.java:1921)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.view.ViewGroup.<init>(ViewGroup.java:292)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.widget.FrameLayout.<init>(FrameLayout.java:88)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.widget.ScrollView.<init>(ScrollView.java:145)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	at android.widget.ScrollView.<init>(ScrollView.java:141)
10-04 12:37:00.777 E/AndroidRuntime(8991): 	... 26 more
10-04 12:37:00.804 W/ActivityManager(106):   Force finishing activity com.splash/.MonkeyGame


All textures/images are <1024 but I precache everything. Will take a deeper look about these limits.


Xaron(Posted 2011) [#25]
So here's the highlighted line:

Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget


FlameDuck(Posted 2011) [#26]
I have the same issue now on a Nexus phone.
I think maybe you can provoke it on the Desire HD as well if you change the screen orientation a lot? Anyhoo the LayoutInflator is invoked whenever you Create or Destroy an Activity (for instance when pressing the home menu, and starting your program again, or changing orientation). If the old Activity isn't cleaning up it's references for some reason (like the one explained here), you will get this error.

If you feel like it, you can trudge through mojo.java and see if this applies to your error. If it does, it's a bug, and BRL should probably fix it. :)


Xaron(Posted 2011) [#27]
Thanks I will nail that down. Actually I have the same issue with the emulator where I get a monkey runtime exception (out of memory for bitmaps).


Xaron(Posted 2011) [#28]
Further investigation has shown that this is obviously some kind of limited heap space. I have currently the following textures in use:

1024x1024: 2
512x1024: 7
512x512: 6
512x128: 1
256x128: 4
128x128: 6
512x64: 6

This leads to 26,6MB uncompressed graphics space for 32 bit RGBA png images. Will use some more 24 bit stuff...


Xaron(Posted 2011) [#29]
Ok, still have this problem. And as I'm not the only one I searched around and I think I've found a definite solution.

The problem on my side was that it worked for the first time, but after discarding and reloading an image (usually going from the game back to the menu and vice versa) I sometimes got an out of memory error.

So THIS IS THE SOLUTION!

In MonkeyGame.java look for:

return BitmapFactory.decodeStream( getAssets().open( path ) );


and replace it with:

BitmapFactory.Options opts = new BitmapFactory.Options(); 
opts.inPurgeable = true; 
return BitmapFactory.decodeStream( getAssets().open( path ), null, opts );


So what does it do?

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inPurgeable

Mark, maybe it's a good idea to add this as default?


dave.h(Posted 2011) [#30]
yes thats the error i was getting but my my programming skills werent good enough to do what you have researched.Thanks for this it should be very usefull.


ziggy(Posted 2011) [#31]
Maybe moving this to bug reports will make it easier for Mark to notice this thread?


Xaron(Posted 2011) [#32]
ziggy, I already did.