Android Bitmap Memory Issue - Error: Out Of Memory On A 8294416-byte Allocation
Solution 1:
I wasn't able to determine why memory allocation and collection is different among the different platforms, but I was able to mitigate the problem and prevent my application from crashing on any platform by scaling the images down to fit available memory.
This first function determines where the Bitmap memory is being stored (native or Java), and then calculates the remaining available memory (in KB).
private long calcAvailableMemory()
{
long value = Runtime.getRuntime().maxMemory();
Stringtype = "";
if (android.os.Build.VERSION.SDK_INT >= 11)
{
value = value / 1024) - (Runtime.getRuntime().totalMemory() / 1024);
type = "JAVA";
}
else
{
value = value / 1024) - (Debug.getNativeHeapAllocatedSize() / 1024);
type = "NATIVE";
}
Log.i(TAG, "calcAvailableMemory, size = " + value + ", type = " + type);
return value;
}
This second function creates an ImageView to attach to the Layout. The Show object contains different variables I need to initialize the ImageView such as dimensions and filepath etc. The long maxImageMemory is derived from the first function, and is then divided by the number of views I'm attaching to the layout giving the me maximum amount of memory to allocate each Bitmap.
private ImageView newImage(Show show, long maxImageMemory)
{
ImageViewiv=newImageView(this);
StringfilePath= comin.generateFilePath(show);
Bitmapbmp= scaleBitmap(filePath, maxImageMemory);
Log.i(TAG, "newImage, id:" + show.id + ", file:" + filePath + ", x:" + bmp.getWidth() + ", y:" + bmp.getHeight());
iv.setImageBitmap(bmp);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setId(show.id);
//set visibilityif (show.visible)
iv.setVisibility(View.VISIBLE);
else
iv.setVisibility(View.INVISIBLE);
//set dimensionsintwidth= (app.getWidth() * show.dimX) / 100;
intheight= (app.getHeight() * show.dimY) / 100;
RelativeLayout.LayoutParamsrlp=newRelativeLayout.LayoutParams(width, height);
iv.setLayoutParams(rlp);
return iv;
}
This third function scales the Bitmap that will be loaded into the ImageView being created in function 2. The while loop is the important part, that is where I increase the sample size until the needed memory for the bitmap is less than the maximum memory available.
private Bitmap scaleBitmap(String path, long maxImageMemory)
{
BitmapFactory.Optionsoptions=newBitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
intsample=1;
//Scale image to screen resolutionif (options.outHeight > app.getHeight() || options.outWidth > app.getWidth())
{
intheightRatio= Math.round((float) options.outHeight / (float) app.getHeight());
intwidthRatio= Math.round((float) options.outWidth / (float) app.getWidth());
sample = heightRatio < widthRatio ? heightRatio : widthRatio;
}
//Scale image to stay within memory limitationswhile (calcBitmapSize(options.outWidth, options.outHeight, sample) > maxImageMemory)
{
sample++;
}
options.inSampleSize = sample;
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
Log.i(TAG, "scaleBitmap, scaleSample = " + sample);
return BitmapFactory.decodeFile(path, options);
}
This fourth function calculates the amount of memory required by the Bitmap depending on the original resolution, as well as the proposed sample size.
privatelongcalcBitmapSize(int width, int height, int sample){
long value = ((width/sample) * (height/sample) * 4) / 1024;
Log.i(TAG, "calcBitmapSize, size = " + value);
return value;
}
Lastly, I developed this function to assist in troubleshooting all of these memory problems. It logs memory utilization depending on which version of Android you are running.
privatevoidlogMemory(String callingFunction){
long max = Runtime.getRuntime().maxMemory() / 1024;
if (debugJavaMemory)
{
long used = Runtime.getRuntime().totalMemory() / 1024;
long available = max - used;
long change = available - availableJavaMemoryOld;
if (availableJavaMemoryOld != 0)
Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
availableJavaMemoryOld = available;
}
elseif (debugNativeMemory)
{
long used = Debug.getNativeHeapAllocatedSize() / 1024;
long available = max - used;
long change = available - availableNativeMemoryOld;
if (availableNativeMemoryOld != 0)
Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
availableNativeMemoryOld = available;
}
}
Solution 2:
I have had this problem couple of months ago, try this,may help:
BitmapFactory.Optionsoptions=newBitmapFactory.Options();
options.inSampleSize = 8;
Bitmapbitmap= BitmapFactory.decodeStream(fis, null, options);
Solution 3:
This link may help you http://developer.android.com/training/displaying-bitmaps/load-bitmap.html This problem also arises when the drawable is not available in the drawable-xhdpi folder for the large 720x1280 mobiles. Please cross check it that the drawables you are using are in the correct drawable folder.
Post a Comment for "Android Bitmap Memory Issue - Error: Out Of Memory On A 8294416-byte Allocation"