如何正确更新WallpaperService?视频动态壁纸配置修改后不生效的问题求助
如何正确更新WallpaperService?视频动态壁纸配置修改后不生效的问题求助
嘿,我之前做视频动态壁纸的时候也踩过这个一模一样的坑!你的问题核心就是WallpaperService的Engine实例没有及时感知到配置变化,也没有在参数更新后重新应用到绘制逻辑里,所以才会一直用旧的缩放类型、背景色这些值。
给你几个实用的解决思路,都是我亲测有效的:
- 首先,把你的配置项(视频路径、缩放类型、背景色)统一存在
SharedPreferences里(当然用其他全局状态管理也可以,但SharedPreferences最省心),而且一定要在Engine里监听配置的变化。 - 给你贴个我当时改的代码片段参考,在你的
VideoEngine里加个SharedPreferences的监听器,一旦配置变了就立刻更新参数并重绘:
internal inner class VideoEngine : WallpaperService.Engine() { private lateinit var configPrefs: SharedPreferences private var currentScaleType: String = "CROP" private var currentBgColor: Int = Color.BLACK // 配置变化的监听器 private val configChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> when (key) { "KEY_SCALE_TYPE" -> { currentScaleType = configPrefs.getString("KEY_SCALE_TYPE", "CROP") ?: "CROP" updateDrawMatrix() // 重新计算视频绘制的矩阵 redrawSurface() // 触发重绘 } "KEY_BG_COLOR" -> { currentBgColor = configPrefs.getInt("KEY_BG_COLOR", Color.BLACK) redrawSurface() } "KEY_VIDEO_PATH" -> { reloadTargetVideo() // 切换到新路径的视频 } } } override fun onCreate(surfaceHolder: SurfaceHolder?) { super.onCreate(surfaceHolder) // 初始化SharedPreferences configPrefs = getSharedPreferences("wallpaper_config", Context.MODE_PRIVATE) // 注册监听器 configPrefs.registerOnSharedPreferenceChangeListener(configChangeListener) // 读取初始配置 currentScaleType = configPrefs.getString("KEY_SCALE_TYPE", "CROP") ?: "CROP" currentBgColor = configPrefs.getInt("KEY_BG_COLOR", Color.BLACK) } override fun onDestroy() { super.onDestroy() // 一定要注销监听器,不然会内存泄漏! configPrefs.unregisterOnSharedPreferenceChangeListener(configChangeListener) } // 计算视频绘制的矩阵,适配不同缩放类型 private fun updateDrawMatrix() { // 这里写你的矩阵计算逻辑,比如CROP是居中裁剪,FIT是等比适配屏幕 // 比如根据surface的宽高和视频的宽高来计算matrix } // 重绘Surface的方法 private fun redrawSurface() { val canvas = surfaceHolder?.lockCanvas() ?: return try { // 先画背景色 canvas.drawColor(currentBgColor) // 再用更新后的矩阵绘制视频帧(这里替换成你实际的视频绘制逻辑) // videoRenderer.draw(canvas, drawMatrix) } finally { surfaceHolder?.unlockCanvasAndPost(canvas) } } // 重新加载新路径的视频 private fun reloadTargetVideo() { // 记得先释放旧的MediaPlayer/ExoPlayer实例,避免内存泄漏 // 然后根据新的视频路径初始化播放器,重新开始播放 } }
- 还有个小细节要注意:如果你在设置界面修改完配置后,不用手动去重启WallpaperService,监听器会自动触发Engine里的更新逻辑。另外,要是你用的是ExoPlayer或者MediaPlayer,切换视频路径的时候一定要先释放旧的播放器实例,不然很容易内存溢出。
其实本质就是让Engine和配置项之间建立实时的关联,配置一变,Engine立刻更新参数并重绘,而不是只在初始化的时候读一次参数。
内容来源于stack exchange
相关产品推荐
相关产品推荐

