【发布时间】:2014-03-05 10:15:05
【问题描述】:
基本上,我正在为 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):强制收集软引用以分配 16571536 字节 E/dalvikvm-heap(13100):16571536 字节分配内存不足。 I/dalvikvm(13100):“主”prio=5 tid=1 RUNNABLE 我/dalvikvm(13100):| group="main" sCount=0 dsCount=0 obj=0x4159fe40 self=0x414d4548 我/dalvikvm(13100):| sysTid=13100 nice=0 sched=0/0 cgrp=apps 句柄=1074098536 我/dalvikvm(13100):| state=R schedstat=( 0 0 0 ) utm=877 stm=93 core=1 I/dalvikvm(13100):在 android.graphics.BitmapFactory.nativeDecodeStream(Native Method) I/dalvikvm(13100):在 android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:613) I/dalvikvm(13100):在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:589) I/dalvikvm(13100): 在 android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:369) I/dalvikvm(13100): 在 android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:395) I/dalvikvm(13100):在 com.android.keyguard.KeyguardViewManager$1.onSetBackground(KeyguardViewManager.java:127) I/dalvikvm(13100):在 com.android.keyguard.KeyguardUpdateMonitor.dispatchSetBackground(KeyguardUpdateMonitor.java:452) I/dalvikvm(13100):在 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;
}
}
}
【问题讨论】:
-
或许可以试试另一个更小的图片?
-
问题在于它是从图库中选择的用户可选择图像,因此需要以某种方式压缩图像......如果普通图像可以设置自定义锁屏背景的选项相对无用'不被加载
-
我不明白您为什么要尝试将图像压缩为 PNG,它在减少图像的内存占用方面没有任何作用,如果图像是图片,则生成的 PNG 文件将比原始 JPG 文件大很多。
-
但主要问题是您试图分配一个占用 16MB 的位图,这意味着一个 4M 像素的图像。所以问题是屏幕是否能够以原始分辨率显示 4MPixel 图像。由于只有 Nexus 10 具有如此高分辨率,我会拒绝。如果您不想使用 3rd 方库,只需使用@Sharj 提供的第一个链接,那里的解决方案会将图像重新缩放到所需的大小。
标签: android image bitmap bitmapfactory