Недостаточно памяти при выделении 16571536 байт

По сути, я добавляю средство выбора обоев для фона экрана блокировки 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)

ничего из того, что я пробовал, пока не сработало, есть идеи?

ОТРЕДАКТИРОВАНО

чтобы уточнить, что устанавливает изображение в настройках:

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

        }

person cphelps76    schedule 07.02.2014    source источник
comment
Возможно, попробовать с другим, меньшим изображением?   -  person initramfs    schedule 08.02.2014
comment
ну проблема в том, что это выбираемое пользователем изображение из галереи, поэтому изображение нужно как-то сжать... возможность установить собственный фон экрана блокировки относительно бесполезна, если обычное изображение не может быть загружено   -  person cphelps76    schedule 08.02.2014
comment
Я не понимаю, почему вы пытаетесь сжать изображение в PNG, это ничего не делает для уменьшения объема памяти изображения, и если изображение является изображением, результирующий файл PNG будет намного больше, чем исходный файл JPG. .   -  person Kai    schedule 08.02.2014
comment
Но основная проблема заключается в том, что вы пытаетесь выделить Bitmap, который занимает 16 МБ, что подразумевает изображение размером 4 мегапикселя. Так что вопрос в том, способен ли экран отображать 4-мегапиксельную картинку в родном разрешении. Так как только Nexus 10 имеет такое высокое разрешение, я бы сказал, что нет. Если вы не хотите использовать стороннюю библиотеку, просто используйте первую ссылку, предоставленную @Sharj, решение изменяет масштаб изображения до необходимого.   -  person Kai    schedule 08.02.2014


Ответы (1)


У вас заканчивается память, потому что вы неаккуратно обрабатываете изображения. Взгляните на следующий вопрос/ответ, чтобы лучше понять, что происходит, когда вы пытаетесь загрузить изображение: Странная проблема нехватки памяти при загрузке изображения в растровый объект

Если вы новый разработчик, я бы порекомендовал вам просто использовать любую хорошую библиотеку, которая загружает часть за вас, иначе будет очень сложно загружать изображения.

Android-Universal-Image-Loader: широко используемая библиотека https://github.com/nostra13/Android-Universal-Image-Loader

Альтернативная библиотека Пикассо. Одна строка кода сделает всю работу за вас: http://square.github.io/picasso/

Обновлено:

Растровые изображения занимают много памяти, особенно для насыщенных изображений, таких как фотографии. Например, камера Galaxy Nexus делает фотографии размером до 2592x1936 пикселей (5 мегапикселей). Если используется конфигурация растрового изображения ARGB_8888 (по умолчанию, начиная с Android 2.3), то загрузка этого изображения в память занимает около 19 МБ памяти (2592 * 1936 * 4 байта), что немедленно исчерпает лимит для каждого приложения на некоторых устройствах.

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

person Sharj    schedule 07.02.2014
comment
я добавил код, который я использую в настройках, чтобы установить изображение, чтобы помочь понять, как я обрабатываю изображение - person cphelps76; 08.02.2014
comment
можно ли использовать публичный логический сжатие (формат Bitmap.CompressFormat, качество int, поток OutputStream) для сжатия изображения? - person cphelps76; 08.02.2014
comment
Проблема не в функции, проблема в размере. На вашем устройстве заканчивается память. Даже если вы оптимизируете свое решение, не гарантируется, что оно будет работать на всех устройствах. Лучше использовать библиотеку, разработанную и используемую ведущими разработчиками. Это всего лишь одна строка кода. - person Sharj; 08.02.2014
comment
я согласен, но я сомневаюсь, что остальная часть команды будет на борту для использования кода, отличного от Google, для такого рода, учитывая, что точно такая же вещь работала без проблем до 4.4.2 ... но вышеприведенное обновление выглядит так, как будто оно дает мне то, что я необходимость - person cphelps76; 08.02.2014