native_workmanager 1.3.1 copy "native_workmanager: ^1.3.1" to clipboard
native_workmanager: ^1.3.1 copied to clipboard

Background task scheduling for Flutter — 25+ native workers (HTTP, image, crypto, file), task chains, zero Flutter Engine overhead.

Changelog #

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.


1.3.1 - 2026-06-07 #

Fixed #

  • Android (critical regression, since v1.2.4): All file-based native workers (HttpDownload, HttpUpload, ParallelHttpDownload/Upload, FileCompression, FileDecompression, ImageProcess, Crypto hash/encrypt/decrypt, Pdf, WebSocket, FileSystem, MoveToSharedStorage) failed on real devices with "Invalid or unsafe file path". v1.2.4 added a blanket "/data" entry to SecurityValidator's blocked-prefix list, which rejected the app's own private sandbox (/data/data/<pkg>, /data/user/<n>/<pkg> — exactly what path_provider returns). The validator now blocks only the genuinely OS-owned sub-directories of /data (/data/local, /data/system, /data/misc, /data/app, …) while allowing the app sandbox. Path-traversal protection (canonical-path resolution) and blocking of /proc, /sys, /etc, /system, /vendor, /dev, /root are unchanged. Added SecurityValidatorFilePathTest (Kotlin) plus device coverage in the "All Workers" integration group.
  • iOS: Fixed an issue where the KMPWorkManager.xcframework was extracted into a double-nested path (Frameworks/Frameworks/KMPWorkManager.xcframework) during pod install, causing iOS builds to fail with "Unable to find module dependency: 'KMPWorkManager'". The prepare_command in native_workmanager.podspec is now layout-agnostic (Resolves #33).

1.3.0 - 2026-06-04 #

Added #

  • Android Auto-Init (NativeWorkManagerInitializer): Plugin now ships an androidx.startup Initializer declared in its own AndroidManifest.xml. It runs automatically before Application.onCreate(), restoring the callbackHandle from SharedPreferences and initializing KmpWorkManager with SimpleAndroidWorkerFactory.

    • Breaking zero-config change: DartWorker killed-app support now requires no custom Application class and no manual AndroidManifest.xml edits for the common case.
    • Opt-out for apps with custom WorkManager configuration: add <meta-data android:name="native_workmanager.auto_init" android:value="false" /> to <application> in your AndroidManifest.xml, then follow doc/ANDROID_SETUP.md.
    • isSchedulerInitialized flag prevents double-initialization when onAttachedToEngine runs after the Initializer.
  • Unified setup CLI (dart run native_workmanager:setup): Evolves setup_ios into a universal command covering both platforms.

    • --android: validates the app manifest has no conflicts with auto-init.
    • --ios: patches Info.plist with UIBackgroundModes and BGTaskSchedulerPermittedIdentifiers (same as the legacy setup_ios command).
    • --check: read-only validation mode — no files are written.
    • --help: full usage reference.
    • setup_ios executable retained for backward compatibility.
  • iOS WorkerResult.retry(): Added retry(reason:delayMs:attemptCap:) factory on the Swift WorkerResult struct, providing parity with WorkerResult.Retry introduced in kmpworkmanager v2.5.0.

Changed #

  • Core: Upgraded KMP WorkManager core dependency from v2.4.3 to v2.5.1.

    • Android: added WorkerResult.Retry branch in ForegroundNativeWorker to satisfy sealed-class exhaustiveness (maps to Result.retry()).
    • iOS KMPWorkManager.xcframework rebuilt from v2.5.1 source.
  • iOS retry semantics (executeWorkerSync): the retry loop now respects WorkerResult.shouldRetry. A worker returning failure(shouldRetry: false) stops retrying immediately instead of exhausting all maxRetries attempts.

  • iOS maxRetries honored on the direct-task execution path: RetryConfig.from(constraintsMap:) is now called and passed to executeWorkerSync. Previously Constraints.maxRetries was silently ignored on iOS (dead code).

  • iOS direct-task qos now read from constraintsMap["qos"] instead of being hardcoded to "background".

Fixed #

  • Android DartCallbackWorker: CancellationException is now rethrown before the outer catch (Exception) block. executeDartCallback is a suspending function; without this fix, WorkManager task cancellation was silently converted to a Failure result.

  • iOS WebSocket: NativeWorker.webSocket() now throws UnsupportedError at call-site when run on iOS. Previously the task was enqueued and silently failed with "Unknown worker class" because IosWorkerFactory has no WebSocketWorker case.

  • Android handleResume: constraint JSON parse failure now logs a NativeLogger.w warning instead of silently falling back to empty constraints (which could cause resumed downloads to ignore requiresNetwork / requiresCharging).

  • Dart resolveDispatcherTimeout: values ≤ 0 (zero, negative, NaN, ±Infinity) now fall back to the 25 s default. A Duration(milliseconds: -n).timeout() fires immediately, which would kill every DartWorker. Added four regression tests.

  • Android HttpDownloadWorker — data corruption (directory mode): concurrent downloads to the same directory now each use their own temp file (__pending_<taskId>__.tmp) instead of sharing the hardcoded __pending__.tmp. Two workers writing to the same temp path produced a mixed-byte file; the first to finish would rename corrupted data.

  • Android HttpDownloadWorker — TOCTOU rename (onDuplicate: "rename"): replaced findNextAvailableFile() + Files.move(REPLACE_EXISTING) with an atomic probe loop using ATOMIC_MOVE only (no REPLACE_EXISTING). A FileAlreadyExistsException now signals the next candidate rather than silently overwriting a file from a concurrent download.

  • Android constraint conflict warning: enqueueing with allowWhileIdle: true and isHeavyTask: true simultaneously now logs a NativeLogger.w at enqueue time. The long-running worker already bypasses Doze mode, making allowWhileIdle redundant and potentially causing WorkManager rejection on some Android versions.

1.2.8 - 2026-06-04 #

Changed #

  • Core: Upgraded KMP WorkManager core dependency from v2.4.3 to v2.5.1.
    • Android: added WorkerResult.Retry branch in ForegroundNativeWorker to satisfy sealed-class exhaustiveness (maps to Result.retry()).
    • iOS: added WorkerResult.retry(reason:delayMs:attemptCap:) factory method for parity with the new KMP sealed variant; existing failure(shouldRetry: true) callers unchanged.
    • iOS KMPWorkManager.xcframework rebuilt from v2.5.1 source.

1.2.7 - 2026-05-11 #

Fixed #

  • Core: Enforced DartWorker.timeoutMs end-to-end (Issue #30).
    • Android and iOS bridges now correctly forward timeoutMs to the Dart callback dispatcher.
    • Added resolveDispatcherTimeout helper in Dart to securely parse the timeout, protecting against NaN, Infinity, and invalid types.
    • Enforced timeoutMs in both the background dispatcher and the foreground MethodChannel (_executeDartCallback).
    • Added comprehensive unit, integration, performance, and security test coverage.

1.2.6 - 2026-05-08 #

Added #

  • Android: Industrial-grade Foreground Service (FGS) Support. Added ForegroundNotificationConfig to Constraints, allowing tasks to run as prioritized Foreground Services to bypass Android 12+ background restrictions.
  • Android: Full compliance with Android 14 (API 34) Foreground Service Types. Automatically maps task types (dataSync, location, media, etc.) to system-level flags.
  • Android: Proactive task promotion using setForeground() to ensure immediate execution even when the app is in the background.
  • Android: FGS state persistence: configuration is automatically restored after device reboots or task resumes.
  • Core: Added comprehensive unit tests and a new Demo page in the example app for FGS bypass.

Fixed #

  • Android: Fixed regression where background tasks would not fire when the device screen was locked (Doze mode) even after the app was killed. Resolved by correctly mapping allowWhileIdle to WorkManager's expedited mode (#28).
  • iOS: Fixed Swift Concurrency deadlocks by migrating SQLite queues (DispatchQueue) from concurrent to serial.
  • iOS: Improved scheduling reliability by adjusting internal TaskTrigger execution delays on iOS to ensure BGTaskScheduler correctly enqueues tasks.
  • Test: Added platform-aware timeouts for iOS integration tests and automatically excluded timeout-prone integration tests (TaskGraph and OfflineQueue) when running on the iOS Simulator.

1.2.5 - 2026-05-06 #

Fixed #

  • Core: Removed over-restrictive assertion in TaskTrigger.periodic that prevented using initialDelay and runImmediately: false together (#26).
  • iOS: Fixed bug where runImmediately flag was incorrectly recomputed from initialDelay instead of using the user-provided value.

1.2.4 - 2026-04-29 #

Fixed #

  • Android: Added automatic ProGuard rules to prevent task classes from being stripped in Release builds (#24).
  • Android: Clarified that Application class setup is required for all tasks to survive app kill.
  • iOS: Synchronized background task identifiers between setup_ios.dart and Swift code.
  • iOS: getTaskStatus() now correctly returns TaskStatus.completed for finished tasks. Previously, the iOS plugin wrote "success" to SQLite but Dart's TaskStatus enum has no success case, so every call returned null.
  • Android: Removed duplicate taskStore.updateStatus() call on task completion. The redundant second write used JSONObject(map).toString() which could corrupt nested result maps, overwriting the correctly-encoded first write.
  • iOS: FlutterEngineManager now disposes the engine after a Dart callback timeout. Previously the engine remained isInitialized = true with a hung MethodChannel, causing all subsequent DartCallbackWorker tasks to silently fail (timeout again).

Changed #

  • Engine: Upgraded core kmpworkmanager to v2.4.3 (re-publish of v2.4.2 to fix Maven Central artifact issue; no code changes).

1.2.3 - 2026-04-24 #

Added #

  • Feature: Support initialDelay and runImmediately for periodic tasks (#21)
    • Allows delaying the first execution of a periodic task.
    • Added runImmediately flag to skip the first execution.
    • On Android, uses native PeriodicWorkRequest.setInitialDelay().
    • On iOS, maps initialDelay to earliestBeginDate for optimized scheduling.
    • Added parameters to TaskTrigger.periodic().
  • Security: Advanced Input Validation
    • All native workers now perform strict validation to block Null Byte Injection, Path Traversal (.., %2e%2e), and Shell Injection characters in URLs and file paths.
  • Enterprise-Grade Testing:
    • Implemented comprehensive scripts/run_all_tests.sh covering Unit, Integration, Security, Performance, and Stress tests.
    • Added specific performance benchmarks for task scheduling overhead.
    • Added malicious payload protection tests.
  • Improved CI/CD: Integrated automated Security, Performance, and Stress testing into the GitHub Actions pipeline.

Fixed #

  • Android: Upgraded to kmpworkmanager 2.4.1
    • Switched to native setInitialDelay instead of manual bypass logic.
    • Fixed edge-case crashes on Android 15.
  • iOS: Improved Periodic Task Lifecycle
    • Fixed regression where periodic tasks were not tracked in activeTasks, preventing cancellation.
  • Android: Fixed broken expedited flag logic in direct enqueue path.

1.2.2 - 2026-04-22 #

Added #

  • registerPlugins parameter in NativeWorkManager.initialize(): opt-in flag to register all Flutter plugins in the background engine, required when using plugins like flutter_local_notifications inside DartWorker callbacks. Defaults to false to preserve the Zero-Engine I/O principle and avoid side-effects (e.g. Bluetooth disconnects). Also added NativeWorkmanagerPlugin.setPluginRegistrantCallback on Android and iOS to allow selective plugin registration when registerPlugins is false. (#18)

Fixed #

  • iOS: openFile always fails on Flutter 3.38+ / scene-based appsUIApplication.shared.keyWindow returns nil in UIWindowScene lifecycle. Replaced with a new activeRootViewController extension that traverses connectedScenes to find the active key window. (#16)
  • Android: StackOverflowError when middleware is registered — Kotlin companion extension applyMiddleware was shadowing the internal package-level function of the same name, causing infinite recursion. Renamed the internal function to applyMiddlewareInternal to eliminate the ambiguity. (#17)
  • native_workmanager_gen incompatible with Flutter 3.41.xanalyzer >=11.0.0 requires meta ^1.18.0 which conflicts with the Flutter SDK's meta 1.17.0 pin. Widened constraint to >=10.0.0 <13.0.0; analyzer 10.x supports all APIs used by the generator and requires only meta ^1.15.0. (#15)

1.2.1 - 2026-04-19 #

Added #

  • Security Hardening: All HTTP workers now support HTTPS Enforcement and Private IP Blocking (SSRF Protection) via NativeWorkManager.initialize(enforceHttps: true, blockPrivateIPs: true).
  • Path Traversal Protection: Enhanced file path validation to block null-byte injection and encoded dot-segments (%2e%2e) across all native workers.
  • WorkManagerLogger interface: A type-safe delegate for forwarding background task events to third-party SDKs like Firebase or Sentry without dynamic reflection.
  • New Test Suite: Added 100+ new test cases covering input sanitization, security policy enforcement, performance benchmarks for large directory operations, and multi-stage task chains.

Fixed #

  • Android: Dart Isolate Timeouts: Implemented hard timeout handling for background Dart execution. If an isolate hangs, the engine is now force-disposed to prevent 50MB+ RAM leaks.
  • Android: Task Store Performance: Added batch deletion for task history cleanup to prevent long SQLite write-locks on high-traffic apps.
  • Migration Tool: Moved the migrate.dart script to the bin/ directory and added it to the executables section in pubspec.yaml to resolve the Could not find bin/migrate.dart error when running dart run native_workmanager:migrate (#14). Also changed developer.log to print so the CLI output displays correctly.
  • Test Infrastructure: Fixed a bug in TaskEventTracker where it incorrectly resolved on "task started" events instead of terminal completion events, leading to flakey stress tests.

1.2.0 - 2026-04-17 #

Added #

  • Android cold-start DartWorker persistence: DartWorker tasks now execute reliably after app kill. The callbackHandle is persisted to SharedPreferences (Android) and UserDefaults (iOS) during initialize() and automatically restored when WorkManager restarts the process. Requires host app to implement Configuration.Provider — see doc/ANDROID_SETUP.md.
  • Advanced Remote Trigger: Support for direct commands in push payloads (native_wm key). Execute tasks, chains (enqueue_chain), graphs, and offline queues without waking Flutter. Both Android and iOS support executing task chains completely in the background.
  • HMAC Security: Robust HMAC SHA-256 signature verification for remote triggers (supporting nested objects) to prevent unauthorized task execution.
  • Real-time Observability: DevTools extension now supports real-time event streaming via developer.postEvent.
  • Global Middleware API: Global interceptors for task configuration (Headers, RemoteConfig, Logging).
  • Code Generation Enhancements: native_workmanager_gen now generates type-safe enqueue wrappers and automatic worker registries from @WorkerCallback annotations.
  • Task Graphs (DAG): Support for complex non-linear task dependencies on Android.
22
likes
160
points
402
downloads

Documentation

API reference

Publisher

verified publisherbrewkits.dev

Weekly Downloads

Background task scheduling for Flutter — 25+ native workers (HTTP, image, crypto, file), task chains, zero Flutter Engine overhead.

Repository (GitHub)
View/report issues
Contributing

Topics

#background #networking #files #images #cryptography

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on native_workmanager

Packages that implement native_workmanager