Out of memory on a 16571536 byte allocation
You are running out of memory because you are not handling images carefully. Take a look at following question/answer for a better idea what happens when you try to load an image: Strange out of memory issue while loading an image to a Bitmap object
If you are a new developer then I would recommend you to just use any good library that does loading part for you otherwise it would be very hard to load images.
Android-Universal-Image-Loader: Widely used library https://github.com/nostra13/Android-Universal-Image-Loader
Alternative Picasso Library: One line of code does the job for you: http://square.github.io/picasso/
Updated:
Bitmaps take up a lot of memory, especially for rich images like photographs. For example, the camera on the Galaxy Nexus takes photos up to 2592x1936 pixels (5 megapixels). If the bitmap configuration used is ARGB_8888 (the default from the Android 2.3 onward) then loading this image into memory takes about 19MB of memory (2592*1936*4 bytes), immediately exhausting the per-app limit on some devices.
http://developer.android.com/training/displaying-bitmaps/index.html
cphelps76
Updated on June 05, 2022Comments
-
cphelps76 almost 2 years
Basically i'm adding a wallpaper picker for android 4.4.2 lockscreen background and when the image is set and i turn the screen off then back on to view the lockscreen my screen is going black and logcat is giving me an out of memory allocation error. So far i have tried using Bitmap decodeFile(String pathName) and i also rebased to use Bitmap decodeFile(String pathName, Options opts) but the result is the same every time...
Here is the original method used to set the image:
private static final String WALLPAPER_IMAGE_PATH = "/data/data/com.android.settings/files/lockscreen_wallpaper.png"; private KeyguardUpdateMonitorCallback mBackgroundChanger = new KeyguardUpdateMonitorCallback() { @Override public void onSetBackground(Bitmap bmp) { if (bmp != null) { mKeyguardHost.setCustomBackground( new BitmapDrawable(mContext.getResources(), bmp)); } else { File file = new File(WALLPAPER_IMAGE_PATH); if (file.exists()) { mKeyguardHost.setCustomBackground( new BitmapDrawable(mContext.getResources(), WALLPAPER_IMAGE_PATH)); } else { mKeyguardHost.setCustomBackground(null); } } updateShowWallpaper(bmp == null); } };
which is being called from case 1 in:
public void setCustomBackground(Drawable d) { if (!mAudioManager.isMusicActive()) { int mBackgroundStyle = Settings.System.getInt(mContext.getContentResolver(), Settings.System.LOCKSCREEN_BACKGROUND_STYLE, 2); int mBackgroundColor = Settings.System.getInt(mContext.getContentResolver(), Settings.System.LOCKSCREEN_BACKGROUND_COLOR, 0x00000000); switch (mBackgroundStyle) { case 0: d = new ColorDrawable(mBackgroundColor); d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER); mCustomBackground = d; break; case 1: KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(null); break; case 2: default: mCustomBackground = d; } computeCustomBackgroundBounds(mCustomBackground); setBackground(mBackgroundDrawable); } if (!ActivityManager.isHighEndGfx()) { mCustomBackground = d; if (d != null) { d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER); } computeCustomBackgroundBounds(mCustomBackground); invalidate(); } else { if (getWidth() == 0 || getHeight() == 0) { d = null; } if (d == null) { mCustomBackground = null; setBackground(mBackgroundDrawable); return; } Drawable old = mCustomBackground; if (old == null) { old = new ColorDrawable(0); computeCustomBackgroundBounds(old); } d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER); mCustomBackground = d; computeCustomBackgroundBounds(d); Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); mBackgroundDrawable.draw(c); Drawable dd = new BitmapDrawable(b); mTransitionBackground = new TransitionDrawable(new Drawable[]{old, dd}); mTransitionBackground.setCrossFadeEnabled(true); setBackground(mTransitionBackground); mTransitionBackground.startTransition(200); mCustomBackground = dd; invalidate(); } if (d != null) { d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER); } computeCustomBackgroundBounds(mCustomBackground); invalidate(); }
this is my logcat output:
I/dalvikvm-heap(13100): Forcing collection of SoftReferences for 16571536-byte allocation E/dalvikvm-heap(13100): Out of memory on a 16571536-byte allocation. I/dalvikvm(13100): "main" prio=5 tid=1 RUNNABLE I/dalvikvm(13100): | group="main" sCount=0 dsCount=0 obj=0x4159fe40 self=0x414d4548 I/dalvikvm(13100): | sysTid=13100 nice=0 sched=0/0 cgrp=apps handle=1074098536 I/dalvikvm(13100): | state=R schedstat=( 0 0 0 ) utm=877 stm=93 core=1 I/dalvikvm(13100): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) I/dalvikvm(13100): at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:613) I/dalvikvm(13100): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:589) I/dalvikvm(13100): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:369) I/dalvikvm(13100): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:395) I/dalvikvm(13100): at com.android.keyguard.KeyguardViewManager$1.onSetBackground(KeyguardViewManager.java:127) I/dalvikvm(13100): at com.android.keyguard.KeyguardUpdateMonitor.dispatchSetBackground(KeyguardUpdateMonitor.java:452) I/dalvikvm(13100): at com.android.keyguard.KeyguardViewManager$ViewManagerHost.setCustomBackground(KeyguardViewManager.java:302)
nothing i have tried as of yet has worked, any ideas?
EDITED
to further clarify this is what sets the image in Settings:
} else if (requestCode == REQUEST_PICK_WALLPAPER) { FileOutputStream wallpaperStream = null; try { wallpaperStream = getActivity().openFileOutput(WALLPAPER_NAME, Context.MODE_WORLD_READABLE); } catch (FileNotFoundException e) { return; // NOOOOO } Uri selectedImageUri = getLockscreenExternalUri(); Bitmap bitmap; if (data != null) { Uri mUri = data.getData(); try { bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), mUri); bitmap.compress(Bitmap.CompressFormat.PNG, 100, wallpaperStream); Toast.makeText(getActivity(), getResources().getString(R.string. background_result_successful), Toast.LENGTH_LONG).show(); Settings.System.putInt(getContentResolver(), Settings.System.LOCKSCREEN_BACKGROUND_STYLE, 1); updateVisiblePreferences(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } else { try { bitmap = BitmapFactory.decodeFile(selectedImageUri.getPath()); bitmap.compress(Bitmap.CompressFormat.PNG, 100, wallpaperStream); } catch (NullPointerException npe) { Log.e(TAG, "SeletedImageUri was null."); Toast.makeText(getActivity(), getResources().getString(R.string. background_result_not_successful), Toast.LENGTH_LONG).show(); super.onActivityResult(requestCode, resultCode, data); return; } } }
-
cphelps76 about 10 yearsi added the code i'm using in settings to set the image to help clarify how i'm handling the image
-
cphelps76 about 10 yearscould public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) be used to compress the image?
-
Sharjeel about 10 yearsThe problem is not the function the problem is the size. Your device runs out of memory. Even if you optimize your solution it is not guaranteed that it will run on all devices. It's a better option to use a library that has been developed and used by top developers. It's just one line of code.
-
cphelps76 about 10 yearsi agree but i doubt the rest of the team would be on board for using non google code for this sort of considering this exact same thing worked without issue prior to 4.4.2...but the above update looks like it gives me what i need