Android调用WallpaperManager.setBitmap设置壁纸切换黑屏问题
Android WallpaperManager.setBitmap 切换壁纸黑屏问题解析
AOSP 10 黑屏触发位置
切换壁纸时的黑屏不是setBitmap接口本身的逻辑问题,是系统壁纸切换流程的固有空窗导致,触发点对应两处源码逻辑:
- 当新壁纸文件写入系统分区完成后,
WallpaperManagerService会调用方法销毁当前正在运行的旧壁纸渲染Engine,直接移除旧壁纸的所有渲染内容,对应源码路径为frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java的bindWallpaperComponentLocked方法。 - 新壁纸Engine启动后,需要等待Surface创建完成、首帧壁纸内容绘制上屏才会显示有效内容,这个间隔期内壁纸窗口无任何可渲染内容,而系统对壁纸窗口设置的默认背景为纯黑色,对应配置在
frameworks/base/core/res/res/values/themes.xml中定义为@android:color/black,因此空窗期会直接透出黑色,形成用户可见的黑屏。
消除过渡黑屏的可行方案
- 普通第三方应用(无系统权限):在调用
setBitmap前,先通过WallpaperManager.getDrawable()获取当前正在显示的旧壁纸,添加一个和屏幕尺寸匹配的全屏覆盖临时View,在View上绘制旧壁纸内容。调用setBitmap后注册监听壁纸变化的系统广播,确认新壁纸已经成功显示后,给临时View添加200ms左右的淡出动画再移除,全程挡住系统的黑色空窗。 - 系统应用/持系统签名应用:反射调用系统隐藏的带回调参数的
setBitmap重载方法,精确监听新壁纸首帧渲染完成的时机,减少占位层的显示时长;部分Android版本支持传入过渡位图参数,系统会自动完成新旧壁纸的过渡,不需要自行添加覆盖层。 - 定制ROM开发场景:直接修改AOSP源码逻辑,在销毁旧壁纸Engine前,先将旧壁纸的快照绘制为壁纸窗口的临时背景,等新壁纸Engine首帧上屏后再清空临时背景,从系统层面彻底消除切换空窗。
注:提供的实现代码中声明了
OutputStream out变量但全程未使用,属于冗余代码,可直接删除,不会影响壁纸设置功能。
问题关联代码片段
setUserWallpaper(this,"test"); private void setUserWallPaper(final Context context, final String userName) { setUserWallpaperRunnable = new Runnable() { @Override public void run() { Log.i(TAG, "setUserWallPaper() run"); InputStream in = null; OutputStream out = null; try { in = new BufferedInputStream( context.getContentResolver() .openInputStream( Uri.parse( "content://test.app.personalization.provider/" + "wall_paper" + "?user=" + userName + "&encryption=false")) ); Bitmap wallpaperBitmap = BitmapFactory.decodeStream(in); if(wallpaperBitmap != null){ WallpaperManager wallpaperManager = WallpaperManager.getInstance(context); wallpaperManager.setBitmap(wallpaperBitmap); } else { Log.i(TAG, "user wallpaper is null."); } Log.i(TAG, "setUserWallPaper() end"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (in != null) { in.close(); } if(out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } }; sUserCustomizeWorker.post(setUserWallpaperRunnable); }
内容的提问来源于stack exchange,提问作者Star
相关产品推荐
相关产品推荐

