Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: cphelps76Ответов: 1

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

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

androidimagebitmapbitmapfactory

Ответы

Ответ 1 · рейтинг 7 · Sharj

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

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы