Question

I know it's a duplicate, but I could not solve the problem.
In my Android application, I download an image from an url and it crashes with an out of memory exception.
I get the error at the Bitmap.createScaledBitmap line ofthe download function.

Everything is in doInBackground.

    private Bitmap downloadImage(String url) {
        Bitmap bitmap = null;
        InputStream stream = null;
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inSampleSize = 1;

        try {
            stream = getHttpConnection(url);
            bitmap = BitmapFactory.decodeStream(stream, null, bmOptions);

//          add on 12/02/2014
            bitmap = Bitmap.createScaledBitmap( // Out of memory exception
                    bitmap, (int) (bitmap.getWidth() * 0.8),
                    (int) (bitmap.getHeight() * 0.8), true);

//          Adding given image bitmap to byte array for edit spot.
            ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream1);
            byte[] array = stream1.toByteArray();
            AddNewSpotValues.comm_2_picture_path = array;           

            stream.close();
        } catch (IOException e1) {
            Log.e("image download problem IO", e1.getMessage());
            e1.printStackTrace();
        }
        return bitmap;
    }




// Makes HttpURLConnection and returns InputStream
private InputStream getHttpConnection(String urlString)
        throws IOException {
    InputStream stream = null;
    URL url = new URL(urlString);
    URLConnection connection = url.openConnection();

    try {
        HttpURLConnection httpConnection = (HttpURLConnection) connection;
        httpConnection.setRequestMethod("GET");
        httpConnection.connect();

        if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            stream = httpConnection.getInputStream();
        }
    } catch (Exception ex) {
        Log.e("image download problem", ex.getMessage());
        ex.printStackTrace();
    }
    return stream;
}

Logcat

at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
at android.graphics.Bitmap.createBitmap(Bitmap.java:695)
at android.graphics.Bitmap.createBitmap(Bitmap.java:628)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:508)
at com.fssd.spot.setting.MyAccount_MySpot.downloadImage(MyAccount_MySpot.java:353)
at com.fssd.spot.setting.MyAccount_MySpot.access$6(MyAccount_MySpot.java:336)
at com.fssd.spot.setting.MyAccount_MySpot$GetDetailOfSelectedSPOT.doInBackground(MyAccount_MySpot.java:315)
at com.fssd.spot.setting.MyAccount_MySpot$GetDetailOfSelectedSPOT.doInBackground(MyAccount_MySpot.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
... 4 more

Please, help me.

Was it helpful?

Solution

You should use ImageLoader class

In this you can access your image url by

imageLoader.displayImage(imageurl, imageView, options);

OTHER TIPS

you should consider downsampling the image , as shown here and here.

also, instead of directly decoding the bitmap from the internet, you should consider downloading it to a file first.

you need to remember that android runs on a lot of types of devices, so not all of them can handle large images.

the bare minimal of MB per app is still 16MB (written about here), and so if an image is of size WIDTH*HEIGHT, after it gets decoded it will usually take 4*WIDTH*HEIGHT bytes . you can make it smaller by setting the type of the bitmap or making the resolution of the image smaller.

one good approach is to downsample the image to the size of the screen, since devices should always be able to show a full screen image. if the image doesn't have transparent pixels and you don't care much about quality, you can use RGB_565 config instead of the default ARGB_8888 config , which will make bitmaps use only 2*WIDTH*HEIGHT bytes.

btw, using createScaledBitmap will create a new bitmap in addition to the one you already have, so you should use it only when you don't have a choice. if you wish to change the size of an already decoded bitmap, you can use my tiny library that does it using NDK&JNI, here .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top