Skip to content

3.3.0

Latest

Choose a tag to compare

@codenameakshay codenameakshay released this 16 Sep 09:54
0d8af27

Android reliability release. The public API is unchanged, but rotation now needs HTTPS URLs and no longer uses a foreground service. See doc/migration.md.

  • Android 11+: the plugin manifest now declares <queries> for the live-wallpaper, chooser, set-wallpaper, and crop-and-set intents. Without them package visibility hid the system wallpaper apps, so getCapabilities() reported live, OpenGL, and picker support as unavailable, and the video, OpenGL, picker, cropper, and chooser flows failed with unsupported or system-ui-unavailable on devices that had them.
  • Wallpaper rotation no longer runs a foreground service. The interval and charging triggers use WorkManager and the time-of-day trigger uses one inexact alarm re-armed after each delivery, which removes the FOREGROUND_SERVICE, POST_NOTIFICATIONS, and SCHEDULE_EXACT_ALARM permissions and keeps charging/time-of-day rotation working on Android 14+ and Android 15+.
  • downloadWallpaper on Android 9 and older: saving to the gallery there needs WRITE_EXTERNAL_STORAGE, which the plugin does not declare, so the call always failed with a SecurityException after downloading the image. It now fails before downloading, logs the reason, and the README and Android guide explain what the host app must declare and request.
  • Rotation sources now load through the same bounded loader as static wallpapers, so rotation URLs must be HTTPS and inherit the redirect, content-type, encoded-size, and decoded-pixel limits. This removes the Picasso dependency, which otherwise pulled OkHttp 3 into consumer release builds and broke R8 minification.
  • systemCropper now reports an unreadable content URI as source-unavailable and a non-image one as invalid-content-type, the same codes the direct path uses. Before, Android's crop-intent lookup failed on the missing image type and the result was a generic system-ui-failed.
  • Video live wallpapers keep an unconfirmed candidate separate from the active asset. A prepared candidate is promoted only when the plugin opens the live-wallpaper preview, so a candidate that is never previewed no longer replaces the active video. Once the system preview is open, Android owns the outcome; the plugin cannot detect that the user cancelled.
  • The video scale mode is persisted with the active asset instead of being held in a process-global field, so fitCenter survives process death and cannot be applied to a different video.
  • Static wallpapers and rotation now draw onto the display size instead of the launcher's desired size. That size is a wide virtual canvas (for example 4800x2400 on a 1080x2400 phone), and Android shows its left edge, so fitCenter and center produced an all-black screen and the other modes showed only a zoomed-in left strip of the image.
  • Charging rotation now applies at most once per configured interval while the device is charging instead of once per plug-in event. Overnight active-hour windows (for example 22 to 6) are supported, equal start/end hours mean a full-day window, and alarm scheduling no longer drifts by the window length.
  • Starting a rotation no longer applies twice. WorkManager ran the new periodic request at once, right after start had applied the first wallpaper, so the playlist skipped ahead. The first scheduled run now waits one interval.
  • A rejected rotation start (for example every source failing to load) no longer deletes the cache of the rotation that is still running. Before, that rotation kept reporting "running" but every later rotation failed.
  • WallpaperRotationStatus.totalCount now counts the requested sources and cachedCount the ones that loaded, so a source that failed to load is visible instead of both numbers matching.
  • startWallpaperRotation, stopWallpaperRotation, rotateWallpaperNow, and getWallpaperRotationStatus now return an unsupported result / a not-running status off Android instead of falling through to a platform call.
  • getWallpaperRotationStatus() no longer throws when the platform call fails; it returns a not-running status with lastError set instead.
  • Results decided in Dart (unsupported platform, invalid input, transport exception) now fill home/lock for each requested target, the same way Android does, instead of leaving them null.
  • An unsupported video scale mode (center, fill, stretch) now returns unsupported with video-scale-unsupported, as documented and as Android reports it. The Dart pre-check returned failed with invalid-input.
  • OpenGL live wallpaper: an unexpected I/O error while reading a texture source during configuration is now reported as texture-source-unavailable instead of configuration-store-failed, matching what the renderer reports for the same failure.
  • Video and OpenGL live wallpapers now reload when the user sets the plugin's wallpaper again over itself. Android keeps the running engine for the same component and only sends it a reapply command, which the engines ignored, so the home screen kept the previous video or shader until the process restarted. On Android 10 and older the running engine picks up the new content only when its surface is recreated.
  • Internal: removed unused legacy platform-channel endpoints and dead pre-Android 7 code paths.
  • Example (Android 12+): the example keeps one FlutterEngine for the process. A new wallpaper changes the dynamic colors, Android relaunches the Activity, and the default FlutterActivity destroyed its engine, so the example restarted and never showed the applyWallpaper result. The Android compatibility guide now explains this relaunch and how a host app can keep its result.
  • Example: the example exposes every public API (download, chooser, legacy set, Material You, platform version, rotation) and its default inputs work out of the box.
  • Docs: the README is shorter and shows current screenshots. Migration notes moved to doc/migration.md.

Full migration notes: doc/migration.md