Android OutOfMemoryError:?
Solution 1
maybe this help you ?
add manifest
android > v3
<application
....
android:largeHeap="true">
Solution 2
Common fixes:
1. Fix your contexts:
Try using the appropiate context: For example since a Toast can be seen in many activities instead of in just one, use getApplicationContext()
for toasts, and since services can keep running even though an activity has ended start a service with:
Intent myService = new Intent(getApplicationContext(), MyService.class)
Use this table as a quick guide for what context is appropiate:
Original article on context here.
2. Check that you're actually finishing your services.
For example I have an intentService that use google location service api. And I forgot to call googleApiClient.disconnect();
:
//Disconnect from API onDestroy()
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, GoogleLocationService.this);
googleApiClient.disconnect();
}
3. Check image and bitmaps usage:
If you are using square's library Picasso I found I was leaking memory by not using the .fit()
, that drastically reduced my memory footprint from 50MB in average to less than 19MB:
Picasso.with(ActivityExample.this) //Activity context
.load(object.getImageUrl())
.fit() //This avoided the OutOfMemoryError
.centerCrop() //makes image to not stretch
.into(imageView);
4. If you are using broadcast receivers unregister them.
5. If you are using java.util.Observer
(Observer pattern):
Make sure to to use deleteObserver(observer);
Solution 3
You can do following to avoid this.
Drawable drawable = resultMatchHeaderContainer.getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable != null) {
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
}
}
Loading Bitmap in Imageview always been a cause of out of memory issue it is very common so we have to handle imageview and bitmaps very carefully. What you can do is While setting any background bitmap to your imageview first get the drawable and recycle it so that it is removed from memory and then set the new bitmap. This will help to avoid any OOM issue. Further. You can use BitmapFactoryOptions to reduce the size of your bitmap. like:
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_WIDTH
|| height_tmp / 2 < REQUIRED_HIGHT)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Solution 4
This could occur for several reasons, you might be keeping references to other parts of your code too long. You might be loading to large bitmaps which together with holding on to many references gives you OOM, etc.
Normally when an OOM occurs a hprof (snapshot of the Heap) is created on the root of the sdcard (or internal storage if sdcard does not exist), which can be read by tools like Eclipse MAT (included in the android tools if you use Eclipse). First one might need to convert the hprof with hprof-conv
tool. Here's one tutorial of how to use Eclipse MAT: Investigating Your RAM Usage. The leak suspects report is a good first read when hprof is loaded in Eclipse MAT
After profiling you you could read up on how to load images effectively from Displaying Bitmaps Efficiently
There's also several popular image loading libraries such as universal image loader and picasso available, that do what you need with ease.
Solution 5
final Bitmap smile = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);
Call
String pathname=BitMapToString(smile);
and then call
setImagesNew(linearview,pathname,activity);
...
public String BitMapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String temp = Base64.encodeToString(b, Base64.DEFAULT);
return temp;
}
public static void setImagesNew(LinearLayout linearLayout, String pathName,
Activity activity) {
Bitmap bmp = decodeSampledBitmapFromResource(pathName,
getDeviceWidth(activity), getDeviceHeight(activity));
linearLayout.setBackgroundDrawable(bmp);
bmp = null;
System.gc();
Runtime.getRuntime().gc();
}
public static Bitmap decodeSampledBitmapFromResource(String pathName,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(pathName, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
@SuppressLint("NewApi")
public static int getDeviceWidth(Activity activity) {
int deviceWidth = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceWidth = size.x;
} else {
Display display = windowManager.getDefaultDisplay();
deviceWidth = display.getWidth();
}
return deviceWidth;
}
@SuppressLint("NewApi")
public static int getDeviceHeight(Activity activity) {
int deviceHeight = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceHeight = size.y;
} else {
Display display = windowManager.getDefaultDisplay();
deviceHeight = display.getHeight();
}
return deviceHeight;
}
please put all function in your activity and call only setImageNew()
and pass parameter in imageview ,sdcardpathname and activity
I hope it will not crash after you implement this code. because I arise same problem as you..
![NagarjunaReddy](https://i.stack.imgur.com/w4Sh8.jpg?s=256&g=1)
NagarjunaReddy
My Gitlab Applications http://pnrandroid.blogspot.in/2018/03/how-to-handle-storage-permissions-in.html https://wordpress.com/stats/day/polamreddyn.wordpress.com Usfull Questions: 1) http://stackoverflow.com/questions/424752/any-good-graphing-packages-for-android 2) http://android-graphview.org/ 3) http://jaxenter.com/effort-free-graphs-on-android-with-achartengine-46199.html 4) http://www.dreamincode.net/forums/topic/303235-visualizing-sound-from-the-microphone/ 5) https://github.com/melanke/MlkAndroidChartApi 6) http://www.osciprime.com/?p=source 7) http://android.codeandmagic.org/achartengine-live-scrolling-graph/ 9) http://android-innovation.blogspot.in/2013/07/how-to-implement-pinch-and-pan-zoom-on.html 10) Full to Refresh https://github.com/chrisbanes/Android-PullToRefresh
Updated on August 12, 2020Comments
-
NagarjunaReddy almost 4 years
I am sporadically getting an
OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
in one of my apps. What can I do to diagnose this?01-09 10:32:02.079: E/dalvikvm(8077): Out of memory: Heap Size=49187KB, Allocated=41957KB, Limit=49152KB 01-09 10:32:02.079: E/dalvikvm(8077): Extra info: Footprint=48611KB, Allowed Footprint=49187KB, Trimmed=7852KB 01-09 10:32:02.079: D/skia(8077): --- decoder->decode returned false 01-09 10:32:02.079: D/AndroidRuntime(8077): Shutting down VM 01-09 10:32:02.079: W/dalvikvm(8077): threadid=1: thread exiting with uncaught exception (group=0x40a97228) 01-09 10:32:02.079: E/AndroidRuntime(8077): FATAL EXCEPTION: main 01-09 10:32:02.079: E/AndroidRuntime(8077): java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:486) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.loadDrawable(Resources.java:2044) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.getDrawable(Resources.java:675) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.view.View.setBackgroundResource(View.java:11776) 01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.ImageLoader.DisplayImage(ImageLoader.java:81) 01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.MatchActivity$MatchAsyncTask.onPostExecute(MatchActivity.java:1768) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.finish(AsyncTask.java:602) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.access$600(AsyncTask.java:156) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Handler.dispatchMessage(Handler.java:99) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Looper.loop(Looper.java:156) 01-09 10:32:02.079: E/AndroidRuntime(8077): at android.app.ActivityThread.main(ActivityThread.java:4987) 01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invokeNative(Native Method) 01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invoke(Method.java:511) 01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 01-09 10:32:02.079: E/AndroidRuntime(8077): at dalvik.system.NativeStart.main(Native Method) 01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Process: com.blsk.bigtoss 01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Package: com.blsk.bigtoss v6 (1.2) 01-09 10:32:02.129: E/EmbeddedLogger(1612): Application Label: Cricket
This is the line where it is happening:
LinearLayout resultMatchHeaderContainer = new LinearLayout(activity); if (!resultImagePath.equals("")) { imageLoader.DisplayImage(resultImagePath,resultMatchHeaderContainer, -1,modifiedHeight, R.drawable.matches_placeholder_result2x); } else { try { resultMatchHeaderContainer.setBackgroundResource(R.drawable.matches_placeholder_result2x); } catch (OutOfMemoryError e) { e.printStackTrace(); } }
-
Avtar Guleria over 10 yearsWhy it is downvoted, let me know also the reason for that..Whosover downvoted it please mentioned the reason for it..
-
TheIT over 10 yearsAlthough this is a nice idea in theory, it doesn't work so well in practice. The call to Recycle() is merely a hint to the GC to reclaim memory. It may not be reclaimed by the time you create your new image and as such may still cause your application to crash. More to the point though, the GC will automatically reclaim the memory when over the next few CG cycles.
-
TheIT over 10 yearsFor your second point, I would look at loading the bitmap at a reduced scale if possible using BitmapFactory.Options and the BitmapFactory.decodeResource() method. See developer.android.com/training/displaying-bitmaps/… for more details.
-
Shakeeb Ayaz over 10 yearsReally why somebody downvoted ,he/she is real nerd ..Most of the time it works ..It worked for me ..in my project..
-
Shakeeb Ayaz over 10 yearsi was about to answer the same so +1
-
Avtar Guleria over 10 yearsThanks. Shakeeb Ayaz. @TheIT, Do you mean that recycle method on bitmap is not useful or what if that then in Which situation we should use it?
-
dipali over 10 yearsfinal Bitmap smile = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);
-
dipali over 10 yearspublic String BitMapToString(Bitmap bitmap) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] b = baos.toByteArray(); String temp = Base64.encodeToString(b, Base64.DEFAULT); return temp; }
-
dipali over 10 yearscall BitMapToString(smile);
-
NagarjunaReddy over 10 years
-
Magnus over 10 years@NagarjunaReddy updated this answer with some more ideas what you could do. I would start off by analyzing the
hprof
to see if you're holding on to too many refs of some kind, if that's not the case you could consider using some image libraries which are caching images and adapting them to your needed view sizes needs with ease. -
TheIT over 10 yearsI'm not fully aware of the exact details of it's functionality, but I believe it simply increases the object's GC priority.
-
Mood almost 9 yearsThe use of largeHeap is not recommended in all cases, please use it very cautiously, it might slow other running application, and also impact your app's reactiveness, since the garbage collector with be solicited more often. For more information check this speech from google i/o youtube.com/watch?v=_CruQY55HOk
-
Adnan Ali almost 8 yearsNever request a large heap simply because you've run out of memory and you need a quick fix—you should use it only when you know exactly where all your memory is being allocated and why it must be retained. Yet, even when you're confident your app can justify the large heap, you should avoid requesting it to whatever extent possible. see developer.android.com/training/articles/memory.html