16571536字节分配的内存不足

时间:2014-02-07 20:35:19

标签: android image bitmap bitmapfactory

基本上我正在为Android 4.4.2锁屏背景添加一个壁纸选择器,当图像设置完毕后我关闭屏幕然后重新开启以查看锁屏我的屏幕变黑并且logcat正在给我一个内存分配错误。到目前为止,我已经尝试使用Bitmap decodeFile(String pathName),我也重新使用Bitmap decodeFile(String pathName,Options opts)但每次结果都是相同的......

以下是用于设置图像的原始方法:

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);
    }
};

从案例1中调用:

    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();
    }

这是我的logcat输出:

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)

我还没有尝试过任何想法?

EDITED

进一步澄清这是设置中的图像设置:

        } 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;
                }
            }

        }

1 个答案:

答案 0 :(得分:7)

由于您未仔细处理图像,因此内存不足。请查看以下问题/答案,以便更好地了解尝试加载图片时会发生什么:Strange out of memory issue while loading an image to a Bitmap object

如果您是新开发人员,那么我建议您只使用任何为您加载部分的好库,否则加载图片会非常困难。

Android-Universal-Image-Loader:广泛使用的库https://github.com/nostra13/Android-Universal-Image-Loader

替代毕加索图书馆:一行代码为您完成工作:http://square.github.io/picasso/

更新:

  

Bitmaps会占用大量内存,特别是对于像这样的丰富图像   照片。例如,Galaxy Nexus上的相机拍照   高达2592x1936像素(5百万像素)。如果是位图配置   使用的是ARGB_8888(默认来自Android 2.3以后)   将此图像加载到内存大约需要19MB内存(2592 * 1936 * 4   字节),立即耗尽某些设备上的每应用限制。

http://developer.android.com/training/displaying-bitmaps/index.html