views:

35

answers:

2

Can someone please tell me where I'm going wrong with this piece of code? Basically I want the app to download a .png file, display it to the user and also save it to the sd card for future reference. It seems to be all going fine until the while ((len = webstream.read(buffer)) > 0) part; as the debugger doesn't reach the breakpoint I've put in here, and I have a directory of empty .png files. I have the WRITE_EXTERNAL_STORAGE permission declared in my Manifest.

protected class DownloadTask extends AsyncTask<String, Integer, Bitmap> {

    @Override
    protected Bitmap doInBackground(String... string) {

        Bitmap d = null;

        try {

            DefaultHttpClient dhc = new DefaultHttpClient();
            HttpGet request = new HttpGet(HTTP_BASE + string[0] + ".png");
            HttpResponse response = dhc.execute(request);
            BufferedInputStream webstream = new BufferedInputStream(response.getEntity().getContent());
            d = BitmapFactory.decodeStream(webstream);
            writeToSd(string[0], webstream, d);

        }
        catch (Exception ex) { ex.printStackTrace(); }

        return d;

    }

    private void writeToSd(String string, BufferedInputStream webstream, Bitmap d) {

        try {

            webstream.mark(3);
            webstream.reset();
            File f = new File(Environment.getExternalStorageDirectory() + SD_DIR);
            f.mkdirs();
            File f2 = new File(f, string + ".png");
            f2.createNewFile();
            BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(f2));

            int len;
            byte[] buffer = new byte[1024];
            while ((len = webstream.read(buffer)) > 0) {

                fos.write(buffer, 0, len);

            }

            webstream.close();
            //fos.flush();
            fos.close();

        }
        catch (Exception ex) {

            ex.printStackTrace();

        }


    }

    protected void onPostExecute(Bitmap result) {

        if (result != null) {
            iv.setImageBitmap(result);
            vs.setDisplayedChild(1);
        }

    }

};
+1  A: 

I don't know for sure, but it seems likely that there is something wrong with the re-reading of the InputStream, even though it's buffered. An image is quite a bit of data to hold in memory. Rather than doing

Fetch Image, Display Image, Store Image

you could try to

Fetch Image, Store Image, Display Image

This way you can write a full-sized image to disk (without having to buffer the stream and consume a lot of memory). Then, you can simply load the image from the sd card at the lowest sampling rate that works for your application, thus saving having a full-sized image ever in memory. Also, doing it this way would likely eliminate any issues you may or may not be having with the bufferedInputStream - I find them to be pretty finicky.

Hamy
Yup, tried this and it worked brilliantly, thanks!
Espiandev
+1  A: 

Unless you want the original stream bytes, you can write the bitmap out to disk using Bitmap.compress(format, quality, stream).

However, Hamy's answer is probably best from a memory conservation point of view.

spong