Search code examples
androidandroid-imageviewout-of-memorybitmapfactory

Displaying images from byte array from server in Android


My Android application connects to a service to request a file from our server. At request time, the file type is unknown but the server replies will a Hashmap that contains the file extension and a byte array of the file data.

My mobile app then takes this data, and if it is a jpg, png, txt, or html file it will display the file on the screen. If it is a different file type, a file is created and the system is prompted to attempt to open the file in an external application.

The text, html, and external files are all working with no problem. Images are working fine for the first image I load, but if I make a second call to the server to load the next image in the list I often get this error:

   E/AndroidRuntime(390): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

I'm using the same server call, and storing the new information over the old information. Here is my code of where I am actually loading the image data:

  imageView.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.length));

Is there a way to handle the memory issue so my application doesn't crash? I have already tried scaling down the images from the server side to make them much smaller and more manageable (but this seems like a bandaid instead of a proper fix.) Currently I am just using the raw bytes and the BitmapFactory to load the imageView, but if there is another way, I could always create a temp file with the actual png or jpg if that would help in any way.

Can someone offer some advice on the best way to handle this?


Solution

  • Images use a lot of the few megabytes RAM your app has. 1Megapixel = 4Megabyte raw imagedata (RGBA_8888 mode at least) that the app needs to hold in memory. Multiple large images will crash on any device.

    • download images to filesystem, use them from there and decode them with a sample size > 1 if they are bigger than you need them / you have memory.
    • immediately recyle() images if you don't need them. Their native buffer does not play well with GC.