Android App crashing on Samsung Galaxy S3 (out of memory error)
android
Solution
I sort of solved the issue myself. The app running out of memory didn't have to do anything with the above code. I added the MAT and I saw that the bitmap objects were being kept alive from previous views. So I removed the graphics from the view and it solved the memory issue.
Problem
I have an Android app that takes some pictures, re-sizes them and sends them over to the back-end server. This app works perfectly fine on all other phones (Gingerbread and Ice cream sandwich) except Samsung Galaxy S3. Whenever it takes the pictures and tries to re-size it, it runs out of memory. Initially I thought it was an issue with the re-sizing part and I implemented the bitmap object with insamplesize and tried everything but it still kept on crashing. Then I realized that when the app launches at first, it is using up a lot of memory. On HTC and all other phones, when my app launches, it uses up about 4 MB but on the Galaxy S3, it uses up about 30 MG - almost 10 times more. I can't seem to figure out what would cause it to use up that much more memory. I am recycling all the objects and layouts properly (I think). Here is the code I have to resize the image: ``` public static void resizeImage(String pathOfInputImage, String pathOfOutputImage) { try { int inWidth = 0; int inHeight = 0; float factor; InputStream in = new FileInputStream(pathOfInputImage); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); inWidth = options.outWidth; inHeight = options.outHeight; in.close(); in = null; options = null; if (inWidth > inHeight) { factor = (float) inHeight / 480; } else { factor = (float) inWidth / 480; } options = new BitmapFactory.Options(); Bitmap roughBitmap; if(Build.VERSION.SDK_INT < 12) { System.gc(); } try { in = new FileInputStream(pathOfInputImage); options.inSampleSize = 4; roughBitmap = BitmapFactory.decodeStream(in, null, options); } catch (OutOfMemoryError e) { roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor); } finally { roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor); } in.close(); in = null; boolean rotate = false; Bitmap rotatedBitmap = null; if (isNeedToRotate(pathOfInputImage)) { rotate = true; Matrix m = new Matrix(); m.postRotate(90); try { rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0, roughBitmap.getWidth(), roughBitmap.getHeight(), m, true); } catch (OutOfMemoryError e) { rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0, roughBitmap.getWidth()/2, roughBitmap.getHeight()/2, m, true); } } if (rotate) { Utils.log(TAG, "Rotate Invoked :------->"); int temp = inHeight; inHeight = inWidth; inWidth = temp; } options.inSampleSize = Math.round(factor); float dstWidth = (int) inWidth / factor; float dstHeight = (int) inHeight / factor; Bitmap resizedBitmap; if (rotate) { try { resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) dstWidth, (int) dstHeight, true); } catch (OutOfMemoryError e) { resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) dstWidth/2, (int) dstHeight/2, true); } } else { try { resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) dstWidth, (int) dstHeight, true); } catch (OutOfMemoryError e) { resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) dstWidth/2, (int) dstHeight/2, true); } } try { FileOutputStream out = new FileOutputStream(pathOfOutputImage); resizedBitmap.compress(Bitmap.CompressFormat.PNG, 80, out); } catch (Exception e) { Utils.log("Image", e.getMessage() + e); } //Free up the memory. roughBitmap.recycle(); resizedBitmap.recycle(); if (rotatedBitmap != null) { rotatedBitmap.recycle(); } } catch (IOException e) { Utils.log("Image", e.getMessage() + e); } } private static Bitmap fetchRoughBitmap(String pathOfInputImage, float factor) { Bitmap roughBitmap = null; try { FileInputStream in = new FileInputStream(pathOfInputImage); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = Math.round(factor); roughBitmap = BitmapFactory.decodeStream(in, null, options); return roughBitmap; } catch (OutOfMemoryError mem_error) { return Utils.fetchRoughBitmap(pathOfInputImage, factor+1); } catch (FileNotFoundException e) { //return Utils.fetchRoughBitmap(pathOfInputImage, factor+1); return roughBitmap; } } ``` This code works fine because I run it through a recursive loop until it doesn't run out of memory but then my resulting image is only about 300x300 px and I need it to be at least 640x480. My questions are: - Can anyone tell me why Galaxy S3 uses up upto 90% memory when it first loads my app instead of 60% on HTC phones. - Is there anything wrong being done in the re-size code that is making my app run out of memory. Any help will be greatly appreciated as I have already spent 3 days on this issue :-(.