Android VM won't let us allocate xx bytes

I am working on a game in Android. The problem starts when I try to use 3 images for the background. Images of 1280x720px and 100kb are large. Images aren't really that big, so I'm a little confused about why they should cause memory problems.

Note. The screen resolution is 800x400, so I can not resize the image by a factor of 2, since this is the proposed Android developer . Note. I use the HTC phone (an accident appears here), I also tried it on the Samsung Galaxy S1, and on Samsung it works fine.

I analyzed the memory in DDMS, and, strangely, I found that Heap has only 3.5 MB. If I check rt.MaxMemory (), it says that I have about 25 mb of application space.

What comes to my mind is that the heap does not β€œupdate” fast enough to adapt to large photos / applications, so it crashes before loading images, even though they are so small. Is there a way to manually size the heap, or at least say to increase?

Here is the code where I upload the images:

Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1); floorFront = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true); floorFront = Bitmap.createBitmap(floorFront, 0, host.realHeight/2, host.realWidth, host.realHeight/2); host.addInstance(new Background(0,host.realHeight/2,host,floorFront,1)); Bitmap floorBack = BitmapFactory.decodeResource(host.getResources(), R.drawable.sand); floorBack = Bitmap.createScaledBitmap(floorBack,host.realWidth,host.realHeight, true); floorBack = Bitmap.createBitmap(floorBack, 0, host.realHeight/2, host.realWidth, host.realHeight/2); host.addInstance(new Background(0,host.realHeight/2,host,floorBack,4)); Bitmap floorRock = BitmapFactory.decodeResource(host.getResources(), R.drawable.foreground); floorRock = Bitmap.createScaledBitmap(floorRock,host.realWidth,host.realHeight, true); floorRock = Bitmap.createBitmap(floorRock, 0, host.realHeight/2, host.realWidth, host.realHeight/2); host.addInstance(new Background(0,host.realHeight/2,host,floorRock,0)); 

Here is the exact error from LogCat:

  maxMemory:25165824 memoryClass:24 6144000-byte external allocation too large for tgis process. Out of memory: Heap Size=4739KB, Allocated=2399KB, Bitmap Size=18668KB VM won't let use allocate 6144000bytes 

EDIT: Now that you said it makes sense that bitmaps use the "raw" size of the image, not the compressed one. And after some research, it seems that on bitmaps android 2.2 and 2.3 are not stored in the heap, so the heap does not increase after the image is loaded.

I've got one more question. We use these 3 images for the background. Now we will resize them a little in the vertical direction, but in the horizontal we still need them as they are. Thus, the image will still be about 100x720 pixels. The problem is that we need 3 images, so we can draw them separately and get a layer effect (we can draw something between two images). What would be the best way to implement this in order to get the desired effect while using as little memory as possible?

Background: background Middle: middle foreground foreground

Note. These are only static backgrounds, the animation takes place around and between them.

+8
android memory
source share
1 answer

I'm not sure where you get that the 1280 x 720 bitmap is 100 KB. These are indeed a few megabytes. In bytes, this is 1280 * 720 * however, many bytes per pixel, usually 4 for images with transparency, or 2 for images without. This is a huge amount of data to download a cell phone. Perhaps you indicate the size of the version of the compressed image format, such as PNG.

Some tips for troubleshooting memory usage issues:

Use the input format Bitmap.Config.RGB_565 in your factory if you do not have transparency. This saves space compared to ARGB_8888.

Set largeHeap to true in the application element in your AndroidManifest.xml.

Make sure your bitmaps are not scaled automatically based on device density class. For example, put them in drawable-nodpi or disable automatic scaling programmatically or create a different bitmap for each density class in several available folders. If your bitmap is only in the drawable folder, it will get scaled 2x on XHDPI devices.

Restore raster images that you are not using, for example:

 Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1); Bitmap floorFrontScaled = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true); floorFront.recycle(); floorFront = null; Bitmap floorFrontCropped = Bitmap.createBitmap(floorFrontScaled, 0, host.realHeight/2, host.realWidth, host.realHeight/2); host.addInstance(new Background(0,host.realHeight/2,host,floorFrontCropped,1)); 

You can also manually run System.gc () from time to time. The system is supposed to do this in front of you before returning an OutOfMemoryError, but this is not with bitmaps in Android, because they have memory allocated outside of Java.

Note that when you read in a bitmap, you can check to see if you need the size you need it to be - this is an integer divisor of a number smaller than its size, and then specify that the factory should skip pixels when loading. This can help lower resolution devices that have correspondingly lower memory limits.

If you do not move these background images separately, then draw them all on one bitmap and use this instead of three at the same time.

+4
source share

All Articles