You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+101-3Lines changed: 101 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,105 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
---
9
9
10
+
## [1.0.5] - 2026-02-22
11
+
12
+
### Added
13
+
14
+
-**Swift Package Manager (SPM) support for iOS** — the plugin now works with both SPM and CocoaPods
15
+
- Added `ios/native_workmanager/Package.swift` with `binaryTarget` for the bundled KMPWorkManager XCFramework and `ZIPFoundation` dependency
16
+
- Moved Swift sources from `ios/Classes/` to `ios/native_workmanager/Sources/native_workmanager/` (Flutter SPM layout)
17
+
- Updated `ios/native_workmanager.podspec` to reference new source paths (CocoaPods build unchanged)
18
+
- Resolves the partial pub.dev platform score for Swift Package Manager support
19
+
20
+
### Fixed (Critical — Android periodic tasks)
21
+
22
+
-**Android: Trigger type was hardcoded to `OneTime` — periodic/exact/windowed triggers were silently ignored** (`NativeWorkmanagerPlugin.kt`)
23
+
-**Root cause:**`handleEnqueue` always passed `TaskTrigger.OneTime(initialDelayMs = 0)` to the kmpworkmanager scheduler, regardless of what the Dart side sent
24
+
-**Impact:** Every task was treated as a one-shot task. Periodic tasks only ran once; exact and windowed triggers were completely ineffective
25
+
-**Fix:** Added full trigger parsing from `call.argument<Map<String, Any?>>("trigger")`, switching on the `"type"` key and creating the correct `TaskTrigger` subtype (`Periodic`, `Exact`, `Windowed`, `ContentUri`, battery, idle, storage)
26
+
-**Reported by:** Abdullah Al-Hasnat (confirmed in production)
27
+
28
+
-**Android: `ExistingTaskPolicy` was hardcoded to `KEEP` — users could not replace existing tasks** (`NativeWorkmanagerPlugin.kt`)
29
+
-**Root cause:**`handleEnqueue` always passed `ExistingPolicy.KEEP`, ignoring the `existingPolicy` argument sent from Dart
30
+
-**Impact:**`ExistingTaskPolicy.replace` was silently treated as `KEEP`; calling `enqueue()` a second time with the same task ID had no effect even when `replace` was specified
31
+
-**Fix:** Parse `existingPolicy` from `call.argument<String>("existingPolicy")` and map `"replace"` → `ExistingPolicy.REPLACE`, anything else → `ExistingPolicy.KEEP`
32
+
33
+
-**Android: Constraints were hardcoded to defaults — network, charging, backoff, system constraints were never applied** (`NativeWorkmanagerPlugin.kt`)
34
+
-**Root cause:**`handleEnqueue` and `toTaskRequest` always used `Constraints()` (all defaults), ignoring the map sent by Dart
35
+
-**Impact:**`requiresNetwork`, `requiresCharging`, `backoffPolicy`, `backoffDelayMs`, `isHeavyTask`, `systemConstraints` were silently ignored
36
+
-**Fix:** Added `parseConstraints(map: Map<String, Any?>?)` helper that reads every field from Dart's `Constraints.toMap()` output
37
+
38
+
-**Android: Periodic tasks stopped emitting events after the first execution** (`NativeWorkmanagerPlugin.kt`)
39
+
-**Root cause:**`observeWorkCompletion` used `Flow.first {}` which suspends until the FIRST terminal state (SUCCEEDED/FAILED/CANCELLED) and then unsubscribes. Periodic tasks never reach a terminal state between cycles, so subsequent executions produced no events
40
+
-**Fix:** Periodic tasks now use `takeWhile { state != CANCELLED }.collect {}` to observe every execution cycle; one-time tasks keep the original `first {}` behaviour
41
+
-**Related:**`isPeriodic` flag propagated from trigger parsing to `observeWorkCompletion`
42
+
43
+
-**iOS: `flexMs` key lookup used wrong name `flexIntervalMs`** (`KMPSchedulerBridge.swift`)
44
+
-**Root cause:**`parseTrigger` looked for `map["flexIntervalMs"]` but Dart's `PeriodicTrigger.toMap()` sends the key as `"flexMs"`
45
+
-**Impact:**`flexInterval` was always `nil` on iOS regardless of what Dart passed; WorkManager flex window was completely ignored
46
+
-**Fix:** Changed key from `"flexIntervalMs"` to `"flexMs"` to match Dart
47
+
48
+
-**iOS: Constraints parsing ignored `qos` and `exactAlarmIOSBehavior` from Dart** (`KMPSchedulerBridge.swift`)
49
+
-**Root cause:**`parseConstraints` only read `requiresNetwork`, `requiresCharging`, and `isHeavyTask`; `qos` and `exactAlarmIOSBehavior` were hardcoded to `.background` and `.showNotification`
50
+
-**Fix:** Added full parsing for `qos` and `exactAlarmIOSBehavior` from the constraint map
51
+
52
+
-**iOS: Chain resume drops all worker config values** (`NativeWorkmanagerPlugin.swift`)
53
+
-**Root cause:**`resumeChain` used `.mapValues { $0.value as? [String:Any] ?? [:] }.compactMapValues { $0.isEmpty ? nil : $0 }` which cast every `AnyCodable` to a nested dict; non-dict values (strings, ints, URLs) became empty dicts and were filtered out
54
+
-**Impact:** After an app kill/crash, resumed chains ran workers with an empty config
55
+
-**Fix:** Replaced faulty pipeline with `task.workerConfig.mapValues { $0.value }`
56
+
57
+
-**iOS: Initial task state set to `"running"` instead of `"pending"`** (`NativeWorkmanagerPlugin.swift`)
58
+
-**Root cause:**`handleEnqueue` set `taskStates[taskId] = "running"` when scheduling; the task hasn't started executing yet
59
+
-**Fix:** Changed to `"pending"` — state transitions to `"running"` when the worker actually starts
-**Root cause:**`#if canImport(ImageCompressWorker)` is always `false` — `canImport()` checks module names, not class names
63
+
-**Fix:** Removed `#if canImport` guard; registration now unconditional
64
+
65
+
-**iOS: `IosWorker` protocol and `IosWorkerFactory` were `internal`** (`ios/Classes/workers/IosWorker.swift`)
66
+
-**Root cause:** Both lacked `public` modifier, making them inaccessible outside the `native_workmanager` module; host apps could not conform to `IosWorker` or call `IosWorkerFactory.registerWorker`
-**Fix:** Defined local `ImageCompressError` enum; changed `success(data: "string")` → `success(message: "...", data: [String: Any])`
71
+
72
+
-**iOS example: Type conflict between `Runner.IosWorker` and `native_workmanager.IosWorker`** (`example/ios/Runner/IosWorker.swift`, `WorkerResult.swift`)
73
+
-**Fix:** Replaced duplicate declarations with `typealias` pointing to the plugin module's types
74
+
75
+
-**Android: Stale version strings in comments and logs** (`NativeWorkmanagerPlugin.kt`, `KMPBridge.swift`)
76
+
-**Fix:** Updated "v2.3.1" / "v2.3.0" references to v2.3.3
77
+
78
+
-**Dart docs: `ExistingTaskPolicy` default incorrectly documented as `keep`**
79
+
-**Fix:** Corrected to `replace` (the actual default in `NativeWorkManager.enqueue`)
80
+
81
+
-**Example app: Stale version strings** — updated to v1.0.5
82
+
83
+
-**Android: `CancellationException` silently swallowed in Flow-collection coroutines** (`NativeWorkmanagerPlugin.kt`)
84
+
-**Root cause:** Three `catch (e: Exception)` blocks in `listenForProgress`, `listenForEvents`, and `observeWorkCompletion` caught `kotlinx.coroutines.CancellationException` (a subtype of `Exception`), preventing structured concurrency from propagating coroutine cancellation
85
+
-**Impact:** Coroutines leaked when the Flutter plugin was detached (e.g., hot reload, app restart); could cause event-sink callbacks after disposal
86
+
-**Fix:** Added `catch (e: kotlinx.coroutines.CancellationException) { throw e }` before the generic `catch (e: Exception)` block in all three locations
-**Root cause:** The `catch (e: Exception)` block unconditionally called `tempFile.delete()`, destroying the partial download that resume logic depends on
90
+
-**Impact:** Resume downloads (`enableResume = true`) always restarted from byte 0 on any network error, wasting bandwidth
91
+
-**Fix:** Removed the unconditional temp-file deletion; the file is now preserved so the next retry can use the `Range: bytes=N-` header to resume
92
+
93
+
-**iOS: `CryptoWorker` loads arbitrarily large files into RAM before size check** (`CryptoWorker.swift`)
94
+
-**Root cause:**`Data(contentsOf: inputURL)` was called before `SecurityValidator.validateFileSize()`, so large files caused an OOM crash rather than a clean error
95
+
-**Fix:** Moved `validateFileSize()` guard to run before reading the file; added random salt generation (`SecRandomCopyBytes`) replacing the hardcoded string salt, improving encryption security
96
+
97
+
-**Android: `ImageProcessWorker` uses `min()` without explicit import** (`ImageProcessWorker.kt`)
98
+
-**Root cause:**`min(widthRatio, heightRatio)` without an explicit `import kotlin.math.min` could resolve to `java.lang.Math.min` in some Kotlin compiler configurations, producing a compile warning or error
99
+
-**Fix:** Changed to `maxOf(1, min(widthRatio, heightRatio))` using Kotlin's built-in `maxOf`; the `max(1, …)` also prevents `sampleSize = 0` when one image dimension already fits within the requested bounds
100
+
101
+
### Added
102
+
-**Device integration test suite** (`example/integration_test/device_integration_test.dart`)
103
+
- Covers all trigger types, ExistingPolicy (REPLACE/KEEP), all 11 workers, chains, tags, cancellation, events and progress streams
104
+
-**GROUP 9 — DartWorker constraint & delay enforcement** — reproduces and verifies the fix for issue #1: `requiresNetwork` and `initialDelay` are now correctly applied to the WorkManager `WorkRequest` for all task types
105
+
- Run with: `flutter test integration_test/device_integration_test.dart --timeout=none`
106
+
107
+
---
108
+
10
109
## [1.0.4] - 2026-02-18
11
110
12
111
### Fixed
@@ -15,7 +114,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
114
-**Solution:** Upgraded to `kmpworkmanager:2.3.3` which adds proper `getForegroundInfo()` override
16
115
-**Impact:** All Android users can now safely use WorkManager 2.10.0+
17
116
-**Files changed:**`android/build.gradle`
18
-
-**Reported by:** Abdullah Al-Hasnat
19
117
-**Example app: Flutter rendering error** in Chain Resilience Test screen
0 commit comments