1

im using a custom method to decode bitmap and set it to imageview as background. For now it's working fine, but in some devices sometimes it's crashing due to out ot memory error. Any idea how can I optime that code and make it better? Here is what I am using :

    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private String data = null;

    public BitmapWorkerTask(ImageView imageView) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    // Decode image in background.
    @Override
    protected Bitmap doInBackground(String... params) {
        data = params[0];

        if(data != null){
            File bufferFile = new File(data);
            Log.e("","data : "+data);
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(bufferFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            Cipher cipher = null;
            try {
                cipher = Cipher.getInstance("AES/CBC/NoPadding");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            }
            int userId = RPCCommunicator.getUserId(Store.this);
            String secretSalt = RPCCommunicator.getSecretKey(userId);
            String iv = RPCCommunicator.getIv(secretSalt);
            SecretKeySpec keySpec = new SecretKeySpec(secretSalt.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            try {
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            CipherInputStream cis = new CipherInputStream(fis, cipher);

            BitmapFactory.Options o2 = new BitmapFactory.Options();
            //o2.inSampleSize=2;
            o2.inTempStorage = new byte[4*1024];

            int width = (int) RPCCommunicator.getPlaceHolderWidth(Store.this, 45);
            int height = (int) RPCCommunicator.getPlaceHolderHeight(Store.this, 25);

            Rect rect = new Rect();
            rect.inset(width, height);

            Bitmap finall = BitmapFactory.decodeStream(cis,rect,o2);
            if(finall != null){
                Bitmap bmp = Bitmap.createScaledBitmap(finall, width, height, true);
                return bmp;
            } else {
                return null;
            }
        }
        return null;
    }

    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null) {
            final ImageView imageView = imageViewReference.get();
            if(bitmap != null){
                if (imageView != null) {
                    Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadein);
                    imageView.startAnimation(animation);
                    imageView.setImageBitmap(bitmap);
                }
            } else {
                int width = (int) RPCCommunicator.getPlaceHolderWidth(Store.this, 45);
                int height = (int) RPCCommunicator.getPlaceHolderHeight(Store.this, 25);

                RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(width, height);
                param.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
                param.rightMargin = 15;
                imageView.setBackgroundResource(R.drawable.placeholder);
                imageView.setLayoutParams(param);
            }
        }
    }
}

Any ideas / suggestions / helps are really appreciated!

2 Answers 2

3

try this code

public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
        try {
            //Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //The new size we want to scale to
            final int REQUIRED_WIDTH=WIDTH;
            final int REQUIRED_HIGHT=HIGHT;
            //Find the correct scale value. It should be the power of 2.
            int scale=1;
            while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
                scale*=2;

            //Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        }
            catch (FileNotFoundException e) {}
        return null;
    }

this will scale bitmap as you pass width and height..

Sign up to request clarification or add additional context in comments.

Comments

1

Use bitmap.recycle() after using your bitmap and before allocating it another value. You can also scale your bitmap down before actually using it. Here's a link: https://stackoverflow.com/a/13226982/1117338

Also one advice: please search well before posting questions. This is an old problem already solved by many.

3 Comments

As i've read in many other places before bitmap.recycle(); does not work everytime. My issue is actually with the streams, because that AsyncTask is used only once in my app, but the conversation of streams from one to another is allocating memory and in devices with less memory it can cause crash. This is the point where I need more advices than scaling the bitmap. I'm already scaling it with other functions.
I was about to say the same thing as vickey. It's a very good idea to use recycle() once you are done with an image. The bitmap allocations get pretty nasty especially in 2.x
What do you mean by 'conversation of streams from one to another'?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.