Android 16571536字节分配的内存不足

Android 16571536字节分配的内存不足,android,image,bitmap,bitmapfactory,Android,Image,Bitmap,Bitmapfactory,基本上,我正在为android 4.4.2锁屏背景添加一个墙纸选择器,当图像设置好后,我关闭屏幕,然后再打开以查看锁屏,我的屏幕变黑,logcat给我一个内存分配错误。到目前为止,我已经尝试使用位图解码文件(字符串路径名),我还重新设置了使用位图解码文件(字符串路径名,选项选项选项)的基础,但每次结果都是一样的 以下是用于设置图像的原始方法: private static final String WALLPAPER_IMAGE_PATH = "/data/data/com.an

基本上,我正在为android 4.4.2锁屏背景添加一个墙纸选择器,当图像设置好后,我关闭屏幕,然后再打开以查看锁屏,我的屏幕变黑,logcat给我一个内存分配错误。到目前为止,我已经尝试使用位图解码文件(字符串路径名),我还重新设置了使用位图解码文件(字符串路径名,选项选项选项)的基础,但每次结果都是一样的

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

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)
您的内存不足,因为您没有仔细处理图像。查看以下问题/答案,以更好地了解尝试加载图像时会发生什么情况:

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

Android通用图像加载器:广泛使用的库

备选毕加索库:一行代码即可完成此任务:

更新:

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


也许可以尝试使用另一个更小的图像?问题是,这是一个用户从gallery中选择的图像,因此图像需要以某种方式进行压缩…如果无法加载正常图像,则设置自定义锁屏背景的选项相对无用。我不明白为什么要将图像压缩为PNG,它在减少图像的内存占用方面没有任何作用,如果图像是图片,生成的PNG文件将比原始JPG文件大得多。但主要问题是,您试图分配一个16MB的位图,这意味着一个4M像素的图像。因此,问题在于屏幕是否能够以其本机分辨率显示4M像素的图像。因为只有Nexus 10具有如此高的分辨率,我想说不。如果你不想使用第三方库,只需使用@Sharj提供的第一个链接,那里的解决方案会将图像重新缩放到所需的大小。我在设置中添加了设置图像的代码,以帮助澄清我如何处理图像(位图.CompressFormat格式、整数质量、输出流)用于压缩图像?问题不在于功能,而在于大小。您的设备内存不足。即使您优化了解决方案,也不能保证它能在所有设备上运行。最好使用由顶级开发人员开发和使用的库。这只是一行代码。我同意,但我怀疑团队的其他成员也会使用非谷歌代码来做这类事情,因为在4.4.2之前,同样的事情是没有问题的……但是上面的更新似乎给了我所需要的
        } 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;
                }
            }

        }