Whenever I force portrait mode in onCreate
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
I get an error
What does Portrait mode have to do with OOM VM budget on image scale?
private void scaleFrom(BmpWrap image, Bitmap bmp)
{
if (image.bmp != null && image.bmp != bmp) {
image.bmp.recycle();
}
if (mDisplayScale > 0.99999 && mDisplayScale < 1.00001) {
image.bmp = bmp;
return;
}
int dstWidth = (int)(bmp.getWidth() * mDisplayScale);
int dstHeight = (int)(bmp.getHeight() * mDisplayScale);
image.bmp = Bitmap.createScaledBitmap(bmp, dstWidth, dstHeight, true);
}
private void resizeBitmaps()
{
scaleFrom(mBackground, mBackgroundOrig);
for (int i = 0; i < mBOrig.length; i++) {
scaleFrom(mB[i], mBOrig[i]);
}
for (int i = 0; i < mBlind.length; i++) {
scaleFrom(mBlind[i], mBlindOrig[i]);
}
for (int i = 0; i < mFrozen.length; i++) {
scaleFrom(mFrozen[i], mFrozenOrig[i]);
}
for (int i = 0; i < mTargeted.length; i++) {
scaleFrom(mTargeted[i], mTargetedOrig[i]);
}
scaleFrom(mBlink, mBlinkOrig);
scaleFrom(mWon, mWonOrig);
scaleFrom(mLost, mLostOrig);
mImagesReady = true;
}
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:498)
at android.graphics.Bitmap.createBitmap(Bitmap.java:465)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:370)
at com.company.app.View$hread.scaleFrom(View.java:313)
at com.company.app.View$hread.resizeBitmaps(View.java:337)
at com.company.app.View$hread.setSurfaceSize(View.java:480)
at com.company.app.View.surfaceChanged(View.java:905)
at android.view.SurfaceView.updateWindow(SurfaceView.java:538)
at android.view.SurfaceView.dispatchDraw(SurfaceView.java:339)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1891)
at android.view.ViewRoot.draw(ViewRoot.java:1416)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1172)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1736)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Whenever you do an orientation change, the app is reloaded entirely except for static properties. (read here : http://developer.android.com/reference/android/app/Activity.html)
This means that all the bitmap you allocated if they were not static will be reloaded. Since the memory allowed for one app is 16 MB(24 on some devices i hear) and that bitmap are stored in memory as raw bitmap(read not compressed) this create a spike in the memory usage that can lead to OOM
Add to that the fact that the memory used for bitmaps are allocated outside of your heap memory but counted as if part of it so that you can't actually trace that problem even using ddms or MAT.
Be sure to recycle all your bitmaps in your onDestroy method so that they can be garbage collected.
The one thing that finally got me out of this one are these three lines of code(hack) :
Beware though, it impacts performance(about 500 to 750 ms) so it is not suitable for a game with FPS concern but for an app it is perfectly reasonable.
Put them at the very beginning of your createScaledBitmap call.
It worked for me
Edit :
Depending on what you are doing with the bitmap in question you can ask android to open it downsampled, taking less memory. I wrote this function while dealing with this problem. It tries to open the bitmap as big as possible :