flutter_wallpaper_plus 1.0.1
flutter_wallpaper_plus: ^1.0.1 copied to clipboard
Production-grade Flutter plugin for setting image and video (live) wallpapers on Android. Supports assets, files, URLs, caching, thumbnails, and structured error handling.
Flutter Wallpaper Plus #
Production-grade Flutter plugin for setting image and video (live) wallpapers on Android.
- Set wallpaper from asset, file, or URL
- Use typed results and structured error codes
- Generate and cache video thumbnails
- Manage cache with size limits + LRU eviction
- Handle OEM target limitations with
getTargetSupportPolicy()

Table of Contents #
- Platform Support
- Installation
- Android Permissions
- Quick Start
- API Reference
- Target Behavior and OEM Limitations
- Real Device Results
- FAQ
- Architecture
- Roadmap
- License
Platform Support #
- Flutter:
>=3.3.0 - Dart:
^3.11.0 - Platform: Android only
- Android API: 24+
| Capability | Android Support |
|---|---|
| Static image wallpaper | API 24+ |
| Live video wallpaper | API 24+ (device must support live wallpaper feature) |
| Video thumbnail generation | API 24+ |
Installation #
Add the package:
dependencies:
flutter_wallpaper_plus: ^1.0.1
Install dependencies:
flutter pub get
Android Permissions #
Permissions are declared by the plugin manifest:
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Permission notes:
SET_WALLPAPER,INTERNET, andACCESS_NETWORK_STATEare normal permissions (auto-granted).- Storage permissions are only needed for
WallpaperSource.file(...)when reading outside app-internal storage. WallpaperSource.asset(...)andWallpaperSource.url(...)do not require storage read permission.
Quick Start #
Import once:
import 'package:flutter_wallpaper_plus/flutter_wallpaper_plus.dart';
Set Image Wallpaper #
final result = await FlutterWallpaperPlus.setImageWallpaper(
source: WallpaperSource.url('https://example.com/wallpaper.jpg'),
target: WallpaperTarget.home,
);
if (result.success) {
print('Applied: ${result.message}');
} else {
print('Failed: ${result.errorCode.name} - ${result.message}');
}
Set Video (Live) Wallpaper #
final result = await FlutterWallpaperPlus.setVideoWallpaper(
source: WallpaperSource.url('https://example.com/live.mp4'),
target: WallpaperTarget.home,
enableAudio: false,
loop: true,
goToHome: false,
);
Notes:
- Android opens the system live wallpaper chooser and user confirmation is required.
WallpaperTarget.lockis not supported for live video wallpaper (WallpaperErrorCode.unsupported).- Live wallpaper service runs independently after apply (survives app process death).
- Selected live wallpaper video is persisted in app-internal storage so it remains available even after cache cleanup.
Open Native Wallpaper Chooser #
final result = await FlutterWallpaperPlus.openNativeWallpaperChooser(
source: WallpaperSource.url('https://example.com/wallpaper.jpg'),
goToHome: true, // optional best-effort: minimize app before chooser
);
source is required and supports:
WallpaperSource.asset(...)WallpaperSource.file(...)WallpaperSource.url(...)
Source path/URL must be non-empty.
Get Device Target Support Policy #
Use this before rendering target options in UI:
final policy = await FlutterWallpaperPlus.getTargetSupportPolicy();
if (!policy.allowImageBoth) {
// Disable "Image -> Both" action in UI
}
Generate Video Thumbnail #
final bytes = await FlutterWallpaperPlus.getVideoThumbnail(
source: WallpaperSource.url('https://example.com/video.mp4'),
quality: 50,
cache: true,
);
if (bytes != null) {
// Example: Image.memory(bytes)
}
Cache Management #
final size = await FlutterWallpaperPlus.getCacheSize();
print('Cache bytes: $size');
await FlutterWallpaperPlus.setMaxCacheSize(100 * 1024 * 1024); // 100 MB
final clearResult = await FlutterWallpaperPlus.clearCache();
print(clearResult.message);
API Reference #
FlutterWallpaperPlus #
| Method | Returns | Description |
|---|---|---|
setImageWallpaper(...) |
Future<WallpaperResult> |
Apply static image wallpaper |
setVideoWallpaper(...) |
Future<WallpaperResult> |
Launch system chooser for live wallpaper |
openNativeWallpaperChooser(...) |
Future<WallpaperResult> |
Open native chooser with provided source (asset/file/url) |
getVideoThumbnail(...) |
Future<Uint8List?> |
Extract video thumbnail bytes |
getTargetSupportPolicy() |
Future<TargetSupportPolicy> |
Get device/OEM target reliability policy |
clearCache() |
Future<WallpaperResult> |
Clear cached media + thumbnails |
getCacheSize() |
Future<int> |
Read cache size in bytes |
setMaxCacheSize(int) |
Future<void> |
Set max cache size (bytes) |
WallpaperSource #
| Constructor | Meaning |
|---|---|
WallpaperSource.asset(path) |
Flutter asset declared in pubspec.yaml |
WallpaperSource.file(path) |
Absolute file path on Android device |
WallpaperSource.url(url) |
Remote URL (downloaded and cached) |
WallpaperTarget #
| Value | Static image | Live video |
|---|---|---|
home |
Supported | Supported |
lock |
Supported on compatible devices/OEMs | Unsupported by Android public APIs |
both |
Supported on compatible devices/OEMs | System chooser controlled; restricted on some OEMs |
WallpaperResult #
| Field | Type | Description |
|---|---|---|
success |
bool |
Operation success flag |
message |
String |
Human-readable outcome |
errorCode |
WallpaperErrorCode |
Structured code for handling |
isError |
bool |
Convenience getter (!success) |
WallpaperErrorCode #
nonesourceNotFounddownloadFailedunsupportedpermissionDeniedapplyFailedvideoErrorthumbnailFailedcacheFailedmanufacturerRestrictionunknown
Target Behavior and OEM Limitations #
This section is important for product behavior and user expectations.
Live Wallpaper Targeting Rules #
- Live wallpaper always uses Android's native chooser flow.
WallpaperTarget.lockfor live video is unsupported on public Android APIs.- Final behavior for live wallpapers can still be altered by OEM system apps/policies.
Known OEM Restrictions #
On some OEM ROMs (commonly Xiaomi/Redmi/Oppo/Vivo/Realme), lock-screen wallpaper behavior may be controlled by system policy (carousel/slideshow/theme engines). In these environments:
- Third-party apps may not reliably force lock wallpaper persistence.
- Lock/both behavior can diverge from what user selected in the system UI.
- The plugin may return
WallpaperErrorCode.manufacturerRestrictionfor targets known to be unreliable. - Similar behavior is likely on other heavily customized OEM ROMs with lock-screen themes/carousel features.
There is currently no reliable cross-OEM workaround using public Android APIs.
Real Device Results #
Observed behavior from real testing (as of February 18, 2026):
| Device | Image both |
Video both |
Notes |
|---|---|---|---|
| Pixel 6 (emulator) | Works | Works | Smooth and expected behavior |
| Oppo Reno Z | Not reliable (does not apply both for image) | Works | both is effectively reliable only for video |
| Redmi 13C | Not reliable (applies to home only) | Not reliable (applies to home only) | both selection does not persist as both |
Additional Redmi 13C note:
- In some cases, video wallpaper may briefly appear on lock, then revert to the user lock-screen slideshow/carousel managed by the OEM system.
Recommended App-Side UX #
- Query
getTargetSupportPolicy()before showing target options. - Disable unreliable target choices in your UI.
- Prefer
hometarget by default on restrictive OEMs. - Explain to users when device policy may override lock-screen wallpaper behavior.
FAQ #
Does video wallpaper keep playing if the app is closed? #
Yes. Playback is hosted in WallpaperService and is independent from your Flutter UI process.
Why does video wallpaper open a system screen? #
Android requires user confirmation for live wallpaper selection.
Why does "Home only" sometimes affect lock screen? #
Some OEMs mirror lock/home wallpaper behavior unless lock wallpaper is independently controlled by the ROM.
Why does lock wallpaper revert after a few seconds on some devices? #
Some ROM features (for example lock-screen slideshow/carousel) can override third-party lock wallpaper shortly after apply.
What formats are supported? #
- Video: device codec support via MediaCodec/ExoPlayer (MP4 H.264 recommended for best compatibility)
- Image: device-supported bitmap formats (JPEG/PNG/WebP/BMP, etc.)
Architecture #
Flutter (Dart API)
-> MethodChannel (com.flutterwallpaperplus/methods)
-> Kotlin plugin layer
-> ImageWallpaperManager
-> VideoWallpaperService + ExoPlayer
-> ThumbnailGenerator
-> SourceResolver
-> CacheManager (LRU)
-> PermissionHelper
Roadmap #
Planned next additions:
- Expand OEM policy coverage and reliability hints for more manufacturers
- Add more end-to-end integration testing across Android OEM variants
License #
MIT. See LICENSE.
