cain
cain

Reputation: 1048

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?

Upvotes: 1

Views: 1712

Answers (2)

Renard
Renard

Reputation: 6929

Firstly make sure to decode and scale the Bitmap in such a way that it fits the screen. Also recycle the bitmap from the imageView before setting a new bitmap. You either need to keep a reference to the decoded bitmap around or you access the old bitmap like this.

    Drawable d = imageView.getDrawable();
    if (d!=null && d instanceof BitmapDrawable){
        BitmapDrawable bd = (BitmapDrawable)d;
        bd.getBitmap().recycle();
    }

Upvotes: 0

zapl
zapl

Reputation: 63955

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.

Upvotes: 3

Related Questions