views:

35

answers:

1

Hi everyone,

My app downloads .png files to the sd card for later use. I kept getting OutOfMemoryErrors (if anyone could explain this too, that'd be great!) and so I took a look at the sizes of the images saved to the sd card, and they seem to be roughly double what they are on the server. Why is this, and how can I make them smaller?

public void onCreate(Bundle saved) {

    setContentView(R.layout.namedrxnscreen);
    TextView t1 = (TextView)findViewById(R.id.rxn_text1);
    TextView t2 = (TextView)findViewById(R.id.rxn_text2);
    TextView t3 = (TextView)findViewById(R.id.rxn_text3);
    TextView t4 = (TextView)findViewById(R.id.rxn_text4);
    iv = (ImageView) findViewById(R.id.rxn_image);
    pb = (ProgressBar) findViewById(R.id.rxn_loading);
    vs = (ViewSwitcher) findViewById(R.id.rxn_switch);

    try {

        super.onCreate(saved);
        [ boring stuff here ]

        BitmapDrawable image = getImage(c.getString(5));
        if (image != null) {
            iv.setImageDrawable(getImage(c.getString(5)));
            iv.setBackgroundColor(Color.WHITE);
            vs.setDisplayedChild(1);
        }
        else {
            new DownloadTask().execute(c.getString(5));
        }

    }
    catch (ArrayIndexOutOfBoundsException ea) {
        error = "bah!";
        showDialog(1);
    }
    catch (Exception ex) {
        error = ex.getMessage();
        showDialog(1);
    }
}

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 = writeToSd(string[0], webstream, d);

        }
        catch (Exception ex) { errorCatch(ex.getMessage()); }

        return d;

    }

    private Bitmap 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();

            FileInputStream fis = new FileInputStream(new File(f, string + ".png"));
            d = BitmapFactory.decodeStream(fis);
            return d;

        }
        catch (Exception ex) {

            errorCatch(ex.getMessage());
            return null;

        }


    }

    protected void onPostExecute(Bitmap result) {

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

    }

}

protected BitmapDrawable getImage(String name) {

    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

        try {

            //Gets the SD card file, whacks it in a stream
            File f = new File(Environment.getExternalStorageDirectory() + SD_DIR, name + ".png");

            if (f.exists()) {

                InputStream s = new FileInputStream(f);

                try {

                    //Return the decoded bitmap
                    BitmapDrawable d = new BitmapDrawable(getResources(), 
                            BitmapFactory.decodeStream(s)); //gives an OutOfMemoryError if png > ~30KB
                    return d;

                } catch (OutOfMemoryError ex) {

                    Toast.makeText(this, "An OutOfMemoryError occured and" +
                            " the image was loaded at a lower quality.", Toast.LENGTH_SHORT).show();
                    BitmapFactory.Options mOptions = new BitmapFactory.Options();
                    mOptions.inSampleSize = 4;
                    BitmapDrawable d = new BitmapDrawable(getResources(), 
                            BitmapFactory.decodeStream(s, null, mOptions));
                    return d;

                }

            }
            else return null;

        }
        catch (Exception ex) {
            return null;

        }

    }
    else {
        Toast.makeText(this, "External storage not available. Downloading from internet.",
                Toast.LENGTH_SHORT).show();
        return null;
    }

}
A: 

The picture downloaded from the server is done byte per byte and cannot be double sized magically...

fedj
this is what I thought obviously. Could it be that its not recompressing it into a png properly?
Espiandev
Check this link : http://developer.android.com/guide/appendix/media-formats.html
fedj