如何在Flutter中设置动态/视频壁纸(无需第三方应用)
Flutter 无需第三方应用/Activity 设置视频动态壁纸方案
由于async_live_wallpaper依赖系统或第三方应用完成设置,要实现无跳转的视频动态壁纸,核心思路是在Android端自定义LiveWallpaper Service,通过Flutter与原生的MethodChannel通信直接触发设置。iOS平台受系统限制,无法实现无跳转设置,以下仅针对Android方案说明。
实现步骤
1. 编写Android原生LiveWallpaper Service
创建VideoLiveWallpaperService.kt文件,继承WallpaperService并实现视频播放逻辑:
import android.service.wallpaper.WallpaperService import android.view.SurfaceHolder import android.media.MediaPlayer import android.net.Uri class VideoLiveWallpaperService : WallpaperService() { override fun onCreateEngine(): Engine = VideoWallpaperEngine() inner class VideoWallpaperEngine : Engine() { private var mediaPlayer: MediaPlayer? = null override fun onSurfaceCreated(holder: SurfaceHolder) { super.onSurfaceCreated(holder) mediaPlayer = MediaPlayer().apply { // 替换为你的视频路径:这里示例用res/raw下的video.mp4 setDataSource(applicationContext, Uri.parse("android.resource://${packageName}/raw/video")) setSurface(holder.surface) isLooping = true prepareAsync() setOnPreparedListener { start() } } } override fun onVisibilityChanged(visible: Boolean) { super.onVisibilityChanged(visible) if (visible) mediaPlayer?.start() else mediaPlayer?.pause() } override fun onSurfaceDestroyed(holder: SurfaceHolder) { super.onSurfaceDestroyed(holder) mediaPlayer?.release() mediaPlayer = null } } }
2. 配置AndroidManifest与资源文件
- 在
AndroidManifest.xml中添加权限与Service注册:
<uses-permission android:name="android.permission.SET_WALLPAPER" /> <!-- Android 13+ 使用READ_MEDIA_VIDEO替代下面的权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <service android:name=".VideoLiveWallpaperService" android:label="Video Live Wallpaper" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper" /> </service>
- 在
res/xml目录下创建wallpaper.xml:
<?xml version="1.0" encoding="utf-8"?> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />
- 将
video.mp4放入res/raw目录(注意文件名小写,无特殊字符)。
3. Flutter端通过MethodChannel调用原生方法
在Flutter中创建通道,调用原生代码完成壁纸设置:
import 'package:flutter/services.dart'; class VideoWallpaperManager { static const MethodChannel _channel = MethodChannel('video_wallpaper'); static Future<void> setVideoWallpaper() async { try { await _channel.invokeMethod('setVideoWallpaper'); } on PlatformException catch (e) { print('设置动态壁纸失败: ${e.message}'); } } } // 调用示例:比如在按钮点击事件中触发 // ElevatedButton( // onPressed: () => VideoWallpaperManager.setVideoWallpaper(), // child: const Text('设置视频壁纸'), // )
4. 原生端注册MethodChannel
在MainActivity.kt中处理Flutter的调用请求:
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import android.app.WallpaperManager class MainActivity : FlutterActivity() { private val CHANNEL = "video_wallpaper" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "setVideoWallpaper") { val wallpaperManager = WallpaperManager.getInstance(this) try { wallpaperManager.setWallpaperComponent(componentName = componentName, cls = VideoLiveWallpaperService::class.java) result.success(null) } catch (e: Exception) { result.error("SET_FAILED", e.message, null) } } else { result.notImplemented() } } } }
注意事项
- Android 13及以上版本,需动态申请
READ_MEDIA_VIDEO权限才能读取外部存储的视频文件。 - 若视频位于外部存储,需修改
setDataSource的Uri为对应文件路径(如Uri.fromFile(File("/storage/emulated/0/DCIM/video.mp4")))。 - iOS平台:苹果系统限制第三方应用直接设置动态壁纸,仅能引导用户手动前往设置界面完成操作,无无跳转方案。
内容的提问来源于stack exchange,提问作者Muhammad Tayyab
相关产品推荐
相关产品推荐

