native_workmanager 1.0.7
native_workmanager: ^1.0.7 copied to clipboard
Background task manager for Flutter using platform-native APIs. Zero Flutter Engine overhead for I/O operations.
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.0.7 - 2026-03-04 #
Fixed #
- iOS: Custom workers silently failed — input data never reached
doWork()(NativeWorkmanagerPlugin.swift,BGTaskSchedulerManager.swift)- Root cause:
CustomNativeWorker.toMap()encodes user input under the"input"key as a pre-serialised JSON string.executeWorkerSync()(the real iOS execution path for all foreground tasks) was passing the fullworkerConfigtodoWork(), so workers received outer wrapper fields (workerType,className,input) instead of their own parameters (inputPath,quality, …). All custom-worker invocations silently returned failure since the initial implementation. - Fix: Extract
workerConfig["input"] as? Stringwhen present and pass that directly todoWork(); fall back to full config for built-in workers (which have no"input"key). Applied consistently to both the foreground path (executeWorkerSync) and the background path (BGTaskSchedulerManager.executeWorker).
- Root cause:
Improved #
doc/use-cases/07-custom-native-workers.md— Corrected return types throughout (Boolean/Bool→WorkerResult), updated Android registration hook toconfigureFlutterEngine, updated iOS AppDelegate to@main+import native_workmanager, fixed broken file reference, aligned all code examples with the actual public API.README.md— Added "Custom Kotlin/Swift workers (no fork)" row to feature comparison table; added full custom-worker showcase section with Kotlin, Swift, and Dart examples.- Demo app — Custom Workers tab now exercises real
NativeWorker.custom()calls againstImageCompressWorkerinstead of placeholderDartWorkerstubs. - Integration tests — Added Group 10 "Custom Native Workers" (3 tests: success path, graceful failure on missing input, unknown-class error event). Total passing tests: 32.
SimpleAndroidWorkerFactory— Unknown worker class now logs a clearLog.emessage pointing tosetUserFactory()instead of silently returningnull.
1.0.6 - 2026-02-28 #
Fixed #
-
Android: Thread safety —
taskTags,taskStatuses,taskStartTimesreplaced withConcurrentHashMap(NativeWorkmanagerPlugin.kt)- Root cause: All three maps used
mutableMapOf()(LinkedHashMapunder the hood), which is not thread-safe. Multiple coroutines launched from the plugin'sCoroutineScopecould read and write concurrently, causing silent data corruption orConcurrentModificationExceptionunder load - Fix: Replaced with
java.util.concurrent.ConcurrentHashMapwhich provides lock-free reads and segment-level locking for writes
- Root cause: All three maps used
-
iOS: Memory safety —
onTaskCompleteclosure capturesinstanceweakly (NativeWorkmanagerPlugin.swift)- Root cause:
BGTaskSchedulerManager.shared.onTaskCompleteheld a strong reference to the plugin instance via an implicit capture; the adjacentprogressDelegateclosure already used[weak instance]correctly but this one did not - Fix: Added
[weak instance]capture and optional-chained the call site (instance?.emitTaskEvent(...))
- Root cause:
Changed #
- pub.dev: Added
topics—background,workmanager,networking,files,cryptographyfor better discoverability - SDK constraint tightened —
sdk: '>=3.6.0 <4.0.0'andflutter: '>=3.27.0'(was>=3.10.0/>=3.3.0; stricter constraint matches actual minimum required APIs and fixes pub.dev static analysis) analysis_options.yaml— added lint rules:cancel_subscriptions,close_sinks,avoid_returning_null_for_future,avoid_void_async,unawaited_futures,always_declare_return_types,avoid_relative_lib_imports; addedmissing_required_param: errorandmissing_return: erroranalyzer settings
1.0.5 - 2026-02-22 #
Added #
- Swift Package Manager (SPM) support for iOS — the plugin now works with both SPM and CocoaPods
- Added
ios/native_workmanager/Package.swiftwithbinaryTargetfor the bundled KMPWorkManager XCFramework andZIPFoundationdependency - Moved Swift sources from
ios/Classes/toios/native_workmanager/Sources/native_workmanager/(Flutter SPM layout) - Updated
ios/native_workmanager.podspecto reference new source paths (CocoaPods build unchanged) - Resolves the partial pub.dev platform score for Swift Package Manager support
- Added
Fixed (Critical — Android periodic tasks) #
-
Android: Trigger type was hardcoded to
OneTime— periodic/exact/windowed triggers were silently ignored (NativeWorkmanagerPlugin.kt)- Root cause:
handleEnqueuealways passedTaskTrigger.OneTime(initialDelayMs = 0)to the kmpworkmanager scheduler, regardless of what the Dart side sent - Impact: Every task was treated as a one-shot task. Periodic tasks only ran once; exact and windowed triggers were completely ineffective
- Fix: Added full trigger parsing from
call.argument<Map<String, Any?>>("trigger"), switching on the"type"key and creating the correctTaskTriggersubtype (Periodic,Exact,Windowed,ContentUri, battery, idle, storage) - Reported by: Abdullah Al-Hasnat (confirmed in production)
- Root cause:
-
Android:
ExistingTaskPolicywas hardcoded toKEEP— users could not replace existing tasks (NativeWorkmanagerPlugin.kt)- Root cause:
handleEnqueuealways passedExistingPolicy.KEEP, ignoring theexistingPolicyargument sent from Dart - Impact:
ExistingTaskPolicy.replacewas silently treated asKEEP; callingenqueue()a second time with the same task ID had no effect even whenreplacewas specified - Fix: Parse
existingPolicyfromcall.argument<String>("existingPolicy")and map"replace"→ExistingPolicy.REPLACE, anything else →ExistingPolicy.KEEP
- Root cause:
-
Android: Constraints were hardcoded to defaults — network, charging, backoff, system constraints were never applied (
NativeWorkmanagerPlugin.kt)- Root cause:
handleEnqueueandtoTaskRequestalways usedConstraints()(all defaults), ignoring the map sent by Dart - Impact:
requiresNetwork,requiresCharging,backoffPolicy,backoffDelayMs,isHeavyTask,systemConstraintswere silently ignored - Fix: Added
parseConstraints(map: Map<String, Any?>?)helper that reads every field from Dart'sConstraints.toMap()output
- Root cause:
-
Android: Periodic tasks stopped emitting events after the first execution (
NativeWorkmanagerPlugin.kt)- Root cause:
observeWorkCompletionusedFlow.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 - Fix: Periodic tasks now use
takeWhile { state != CANCELLED }.collect {}to observe every execution cycle; one-time tasks keep the originalfirst {}behaviour - Related:
isPeriodicflag propagated from trigger parsing toobserveWorkCompletion
- Root cause:
-
iOS:
flexMskey lookup used wrong nameflexIntervalMs(KMPSchedulerBridge.swift)- Root cause:
parseTriggerlooked formap["flexIntervalMs"]but Dart'sPeriodicTrigger.toMap()sends the key as"flexMs" - Impact:
flexIntervalwas alwaysnilon iOS regardless of what Dart passed; WorkManager flex window was completely ignored - Fix: Changed key from
"flexIntervalMs"to"flexMs"to match Dart
- Root cause:
-
iOS: Constraints parsing ignored
qosandexactAlarmIOSBehaviorfrom Dart (KMPSchedulerBridge.swift)- Root cause:
parseConstraintsonly readrequiresNetwork,requiresCharging, andisHeavyTask;qosandexactAlarmIOSBehaviorwere hardcoded to.backgroundand.showNotification - Fix: Added full parsing for
qosandexactAlarmIOSBehaviorfrom the constraint map
- Root cause:
-
iOS: Chain resume drops all worker config values (
NativeWorkmanagerPlugin.swift)- Root cause:
resumeChainused.mapValues { $0.value as? [String:Any] ?? [:] }.compactMapValues { $0.isEmpty ? nil : $0 }which cast everyAnyCodableto a nested dict; non-dict values (strings, ints, URLs) became empty dicts and were filtered out - Impact: After an app kill/crash, resumed chains ran workers with an empty config
- Fix: Replaced faulty pipeline with
task.workerConfig.mapValues { $0.value }
- Root cause:
-
iOS: Initial task state set to
"running"instead of"pending"(NativeWorkmanagerPlugin.swift)- Root cause:
handleEnqueuesettaskStates[taskId] = "running"when scheduling; the task hasn't started executing yet - Fix: Changed to
"pending"— state transitions to"running"when the worker actually starts
- Root cause:
-
iOS: Custom worker registration always silently skipped (
example/ios/Runner/AppDelegate.swift)- Root cause:
#if canImport(ImageCompressWorker)is alwaysfalse—canImport()checks module names, not class names - Fix: Removed
#if canImportguard; registration now unconditional
- Root cause:
-
iOS:
IosWorkerprotocol andIosWorkerFactorywereinternal(ios/Classes/workers/IosWorker.swift)- Root cause: Both lacked
publicmodifier, making them inaccessible outside thenative_workmanagermodule; host apps could not conform toIosWorkeror callIosWorkerFactory.registerWorker - Fix: Added
publicto both declarations
- Root cause: Both lacked
-
iOS example:
WorkerErrorundefined;WorkerResult.success(data:)wrong type (example/ios/Runner/ImageCompressWorker.swift)- Fix: Defined local
ImageCompressErrorenum; changedsuccess(data: "string")→success(message: "...", data: [String: Any])
- Fix: Defined local
-
iOS example: Type conflict between
Runner.IosWorkerandnative_workmanager.IosWorker(example/ios/Runner/IosWorker.swift,WorkerResult.swift)- Fix: Replaced duplicate declarations with
typealiaspointing to the plugin module's types
- Fix: Replaced duplicate declarations with
-
Android: Stale version strings in comments and logs (
NativeWorkmanagerPlugin.kt,KMPBridge.swift)- Fix: Updated "v2.3.1" / "v2.3.0" references to v2.3.3
-
Dart docs:
ExistingTaskPolicydefault incorrectly documented askeep- Fix: Corrected to
replace(the actual default inNativeWorkManager.enqueue)
- Fix: Corrected to
-
Example app: Stale version strings — updated to v1.0.5
-
Android:
CancellationExceptionsilently swallowed in Flow-collection coroutines (NativeWorkmanagerPlugin.kt)- Root cause: Three
catch (e: Exception)blocks inlistenForProgress,listenForEvents, andobserveWorkCompletioncaughtkotlinx.coroutines.CancellationException(a subtype ofException), preventing structured concurrency from propagating coroutine cancellation - Impact: Coroutines leaked when the Flutter plugin was detached (e.g., hot reload, app restart); could cause event-sink callbacks after disposal
- Fix: Added
catch (e: kotlinx.coroutines.CancellationException) { throw e }before the genericcatch (e: Exception)block in all three locations
- Root cause: Three
-
Android: HttpDownloadWorker deletes temp file on network error, breaking resume (
HttpDownloadWorker.kt)- Root cause: The
catch (e: Exception)block unconditionally calledtempFile.delete(), destroying the partial download that resume logic depends on - Impact: Resume downloads (
enableResume = true) always restarted from byte 0 on any network error, wasting bandwidth - 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
- Root cause: The
-
iOS:
CryptoWorkerloads arbitrarily large files into RAM before size check (CryptoWorker.swift)- Root cause:
Data(contentsOf: inputURL)was called beforeSecurityValidator.validateFileSize(), so large files caused an OOM crash rather than a clean error - Fix: Moved
validateFileSize()guard to run before reading the file; added random salt generation (SecRandomCopyBytes) replacing the hardcoded string salt, improving encryption security
- Root cause:
-
Android:
ImageProcessWorkerusesmin()without explicit import (ImageProcessWorker.kt)- Root cause:
min(widthRatio, heightRatio)without an explicitimport kotlin.math.mincould resolve tojava.lang.Math.minin some Kotlin compiler configurations, producing a compile warning or error - Fix: Changed to
maxOf(1, min(widthRatio, heightRatio))using Kotlin's built-inmaxOf; themax(1, …)also preventssampleSize = 0when one image dimension already fits within the requested bounds
- Root cause:
Added #
- Device integration test suite (
example/integration_test/device_integration_test.dart)- Covers all trigger types, ExistingPolicy (REPLACE/KEEP), all 11 workers, chains, tags, cancellation, events and progress streams
- GROUP 9 — DartWorker constraint & delay enforcement — reproduces and verifies the fix for issue #1:
requiresNetworkandinitialDelayare now correctly applied to the WorkManagerWorkRequestfor all task types - Run with:
flutter test integration_test/device_integration_test.dart --timeout=none
1.0.4 - 2026-02-18 #
Fixed #
- Android: Worker crash "IllegalStateException: Not implemented" (Complete fix)
- Root cause: WorkManager 2.10.0+ calls
getForegroundInfoAsync()in execution path for expedited tasks. Upstreamkmpworkmanagerdid not overridegetForegroundInfo(), causing crash - Solution: Upgraded to
kmpworkmanager:2.3.3which adds propergetForegroundInfo()override - Impact: All Android users can now safely use WorkManager 2.10.0+
- Files changed:
android/build.gradle
- Root cause: WorkManager 2.10.0+ calls
- Example app: Flutter rendering error in Chain Resilience Test screen
- Fixed
RenderFlexunbounded height constraint error caused byExpandedwidget insideSingleChildScrollView - Changed to
SizedBoxwith fixed height for logs section
- Fixed
- Example app: Integration test API errors
- Updated bug fix integration tests to use correct
native_workmanagerAPI - Fixed
TaskTrigger.periodic()usage and event stream handling
- Updated bug fix integration tests to use correct
- Example app: Incorrect library naming in benchmarks
- Corrected competitor library references from
flutter_wmtoworkmanager - Updated production impact comparison pages and manual benchmark page
- Corrected competitor library references from
Changed #
- Dependencies:
- Upgraded
kmpworkmanagerfrom 2.3.1 to 2.3.3 (fixes WorkManager 2.10.0+ compatibility) - Upgraded
work-runtime-ktxfrom 2.9.1 to 2.10.1 (safe with kmpworkmanager 2.3.3+)
- Upgraded
Added #
- Bug fix verification demo - Interactive UI demonstrating WorkManager 2.10.0+ compatibility
- Shows original bug details and fix information
- Runs expedited tasks (original crash scenario) and displays real-time results
- Tests concurrent expedited tasks and task chains
- Accessible via "🐛 Bug Fix" tab in example app
- Integration tests - Comprehensive test coverage for WorkManager 2.10.0+ bug fix
- Tests expedited tasks, concurrent tasks, periodic tasks, and chains
- Verifies notification i18n support
- Documentation - Complete bug fix verification guide (
BUG_FIX_VERIFICATION.md)- Root cause analysis and fix details
- Build and runtime verification steps
- Migration guide for users
Upstream Fix (kmpworkmanager 2.3.3) #
- Added
getForegroundInfo()override inKmpWorkerwith notification localization support - Fixed chain heavy-task routing bug (tasks with
isHeavyTask=truenow correctly useKmpHeavyWorker) - Notification strings now support i18n via Android string resources
1.0.3 - 2026-02-16 #
Fixed #
- Android: Critical initialization bug - "KmpWorkManager not initialized!" error
- Root cause: Plugin was not calling
KmpWorkManager.initialize()from kmpworkmanager library - Impact: All Android users attempting to use the plugin would get runtime errors when tasks execute
- Solution: Added
KmpWorkManager.initialize()call ininitializeKoin()before setting up Koin modules - Files changed:
NativeWorkmanagerPlugin.kt - Reported by: Community user feedback
- Root cause: Plugin was not calling
Added #
- Documentation: Android Setup Guide (
doc/ANDROID_SETUP.md)- Comprehensive Android configuration requirements
- Minimum SDK 26+ requirement clearly documented
- Troubleshooting section for initialization errors
- Build verification steps
- ProGuard/R8 configuration
- Production checklist
Changed #
- Documentation: Updated README, GETTING_STARTED, and FAQ with Android setup requirements
- Platform requirements mentioned upfront in Quick Start
- Android minSdk 26+ requirement added to prerequisites
- Troubleshooting section enhanced with Android-specific issues
- Links to new Android setup guide
Notes #
- CRITICAL FIX - All Android users should upgrade immediately
- Previous versions (1.0.0, 1.0.1) are non-functional on Android
- iOS not affected by this bug
- Package description updates from 1.0.2 (2026-02-13) merged into this release
1.0.1 - 2026-02-12 #
Fixed #
- Package Description: Shortened from 215 to 154 characters to meet pub.dev requirements (60-180 chars)
- Impact: Improves pub.dev score from 150/160 to 160/160 points
- Details: Removed redundant text while preserving key value propositions
Notes #
- No code changes - metadata fix only
- Fixes issue identified in pub.dev analysis
- Achieves perfect pub.dev compliance score
1.0.0 - 2026-02-12 #
Production release with 11 built-in native workers for background task management.
Critical Safety Fixes #
iOS Force Unwrap Elimination
- Fixed: Removed all unsafe force unwraps (
!) from iOS worker JSON parsing - Impact: Prevents potential crashes from invalid UTF-8 encoding
- Files: 8 iOS workers (Crypto, DartCallback, FileCompression, FileDecompression, HttpDownload, HttpSync, HttpUpload, ImageProcess)
- Pattern: Replaced
input.data(using: .utf8)!with safeguard letstatements - Result: Zero crash risk from encoding issues
Test Infrastructure Improvements
- Fixed: chain_data_flow_test.dart initialization issues
- Added: Proper platform channel mocking for unit tests
- Result: 808 tests passing
Features #
1. HttpDownloadWorker: Resume Support
Downloads can now resume from the last byte on network failure, saving bandwidth and time.
Implementation:
- HTTP Range Requests (RFC 7233) with 206 Partial Content handling
- Automatic retry from last downloaded byte
- Fallback to full download if server doesn't support Range
enableResume: trueby default (backward compatible)
Example:
NativeWorker.httpDownload(
url: 'https://cdn.example.com/app-update.apk', // 100MB file
savePath: '/downloads/update.apk',
enableResume: true, // Resume from last byte on failure
)
Benefits:
- Saves bandwidth on mobile networks
- Faster completion for large files
- Better UX (no restart from 0%)
- Critical for unreliable connections
2. HttpUploadWorker: Multi-File Support
Upload multiple files in a single request, unblocking social media and e-commerce apps.
Implementation:
files: List<FileConfig>array for multiple files- Same
fileFieldName= array on server side - Different
fileFieldName= separate form fields - Backward compatible with single file API
Example:
NativeWorker.httpUpload(
url: 'https://api.example.com/gallery',
files: [
FileUploadConfig(filePath: '/photos/img1.jpg', fileFieldName: 'photos'),
FileUploadConfig(filePath: '/photos/img2.jpg', fileFieldName: 'photos'),
FileUploadConfig(filePath: '/photos/thumb.jpg', fileFieldName: 'thumbnail'),
],
)
Benefits:
- Upload multiple photos in one request
- Mix different form fields (photos + thumbnail)
- Reduces server round-trips
- Unblocks social media, e-commerce use cases
3. FileDecompressionWorker: NEW Worker
Complete ZIP extraction worker with security protections, completing the compression/decompression pair.
Implementation:
- Streaming extraction (low memory usage ~5-10MB)
- Zip slip protection (canonical path validation)
- Zip bomb protection (size validation during extraction)
deleteAfterExtractoption to save storageoverwritecontrol for existing files- Basic ZIP support
Example:
// Download → Extract → Delete workflow
await NativeWorkManager.enqueue(
taskId: 'extract-assets',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.fileDecompress(
zipPath: '/cache/assets.zip',
targetDir: '/data/assets/',
deleteAfterExtract: true,
overwrite: true,
),
);
Benefits:
- Completes compression/decompression pair
- Enables Download → Extract workflows
- Security built-in (zip slip, zip bomb)
- Memory efficient (~5-10MB RAM)
- Password support coming in v1.1.0
4. ImageProcessWorker: NEW Worker
Native image processing (resize, compress, convert) with native performance.
Implementation:
- Native Bitmap (Android) / UIImage (iOS) APIs
- Hardware-accelerated rendering
- Memory-efficient: No Flutter Engine overhead
- Native performance
- Formats: JPEG, PNG, WEBP
Example:
// Resize 4K photo to 1080p for upload
await NativeWorkManager.enqueue(
taskId: 'resize-photo',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.imageProcess(
inputPath: '/photos/IMG_4032.png',
outputPath: '/processed/photo_1080p.jpg',
maxWidth: 1920,
maxHeight: 1080,
quality: 85,
outputFormat: ImageFormat.jpeg,
deleteOriginal: false,
),
);
Benefits:
- Native performance (no Flutter Engine)
- Lower memory usage
- Resize, compress, convert formats
- Crop support
- For photo upload pipelines
5. CryptoWorker: NEW Worker
File hashing and AES-256-GCM encryption/decryption for data security.
Implementation:
- Hash algorithms: MD5, SHA-1, SHA-256, SHA-512
- AES-256-GCM encryption (authenticated)
- Password-based key derivation (PBKDF2)
- Streaming operations for large files
Example:
// Hash file for integrity verification
await NativeWorkManager.enqueue(
taskId: 'verify-download',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.hashFile(
filePath: '/downloads/file.zip',
algorithm: HashAlgorithm.sha256,
),
);
// Encrypt sensitive file
await NativeWorkManager.enqueue(
taskId: 'encrypt-backup',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.cryptoEncrypt(
inputPath: '/data/backup.db',
outputPath: '/data/backup.db.enc',
password: 'mySecretPassword',
),
);
Benefits:
- File integrity verification
- Secure backups with encryption
- Deduplication via hashing
6. FileSystemWorker: NEW Worker
Native file system operations (copy, move, delete, list, mkdir) enabling pure-native task chains without Flutter Engine overhead.
Implementation:
- 5 operations: copy, move, delete, list, mkdir
- Security validations (path traversal, protected paths, sandbox enforcement)
- Atomic operations when possible (move on same filesystem)
- Pattern matching with wildcards (*.jpg, file_?.txt)
- Progress reporting for large operations
Example:
// Pure-native workflow: Download → Move → Extract → Process
await NativeWorkManager.beginWith(
TaskRequest(
id: 'download',
worker: NativeWorker.httpDownload(url: url, savePath: '/temp/file.zip'),
),
).then(
TaskRequest(
id: 'move',
worker: NativeWorker.fileMove(
sourcePath: '/temp/file.zip',
destinationPath: '/downloads/file.zip',
),
),
).then(
TaskRequest(
id: 'extract',
worker: NativeWorker.fileDecompress(
zipPath: '/downloads/file.zip',
targetDir: '/extracted/',
),
),
).enqueue();
// List files with pattern
await NativeWorkManager.enqueue(
taskId: 'find-photos',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.fileList(
path: '/photos',
pattern: '*.jpg',
recursive: true,
),
);
Benefits:
- Enables pure-native task chains (no Dart callbacks)
- Lower memory usage (no Flutter Engine)
- All 5 operations: copy, move, delete, list, mkdir
- Security built-in (path traversal, sandbox)
- Pattern matching for file filtering
- Atomic move when possible (faster than copy+delete)
✨ Enhanced Features #
HttpDownloadWorker: Checksum Verification
Verify file integrity after download to detect corruption or tampering.
Implementation:
- Algorithms: MD5, SHA-1, SHA-256, SHA-512
- Automatic file deletion if checksum mismatch
- Task retry on verification failure
Example:
NativeWorker.httpDownload(
url: 'https://cdn.example.com/firmware.bin',
savePath: '/downloads/firmware.bin',
expectedChecksum: 'a3b2c1d4e5f6...',
checksumAlgorithm: 'SHA-256',
)
Benefits:
- Detect corrupted downloads
- Prevent security vulnerabilities
- Critical for firmware, installers, sensitive files
HttpUploadWorker: Raw Bytes Upload
Upload data from memory without creating temp files.
Implementation:
body: Stringfor text data (JSON, XML)bodyBytes: Stringfor Base64-encoded binary datacontentType: Stringfor MIME type
Example:
// Upload JSON without temp file
NativeWorker.httpUpload(
url: 'https://api.example.com/data',
body: '{"userId": "123", "action": "sync"}',
contentType: 'application/json',
)
Benefits:
- No temp file for in-memory data
- Faster for small payloads
- Cleaner API for JSON/XML
HttpRequestWorker: Response Validation
Detect API errors in HTTP 200 responses using regex patterns.
Implementation:
successPattern: String- Regex response must matchfailurePattern: String- Regex that indicates error- Fails task even with HTTP 200 if validation fails
Example:
NativeWorker.httpRequest(
url: 'https://api.example.com/login',
method: HttpMethod.post,
successPattern: r'"status"\s*:\s*"success"',
failurePattern: r'"status"\s*:\s*"error"',
)
Benefits:
- Prevent false positives (200 with error body)
- Critical for poorly-designed APIs
- Flexible regex validation
ImageProcessWorker Enhancements (Android)
1. EXIF Orientation Handling
- Auto-detects and corrects EXIF orientation from camera photos
- Handles all 8 EXIF orientations (rotate, flip, transpose)
- Photos always display correctly (no more sideways images!)
- Dependency added:
androidx.exifinterface:exifinterface:1.3.7
2. Progress Reporting (5 Stages)
- 20% - Image loaded into memory
- 40% - Crop applied (if requested)
- 60% - Resize applied (if requested)
- 80% - Compressing to output format
- 100% - Image saved to disk
3. WEBP Error Handling (iOS)
- Clear error message instead of silent fallback to JPEG
- Suggests alternatives (JPEG for smaller, PNG for lossless)
- Prevents user confusion
Example:
// Portrait photo from camera - automatically corrected!
await NativeWorkManager.enqueue(
taskId: 'process-photo',
trigger: TaskTrigger.oneTime(),
worker: NativeWorker.imageProcess(
inputPath: '/DCIM/IMG_4032.jpg', // May have EXIF orientation
outputPath: '/processed/corrected.jpg',
maxWidth: 1920,
maxHeight: 1080,
),
);
// Output is correctly oriented, EXIF removed
Benefits:
- Photos always display correctly
- Real-time progress for large images (4K, 8K)
- Clear errors instead of surprises
- Better UX for photo upload workflows
HttpUploadWorker Enhancements
Form Field Limit Validation
- Added 50 field limit to prevent memory issues
- Clear error message with helpful suggestion
- Guides users to use JSON body for large data
Example Error:
Too many form fields: 75
Maximum allowed: 50 fields
Consider sending large data as JSON in request body instead
Benefits:
- Prevents memory exhaustion
- Clear guidance for proper usage
- Protects against misuse
📚 Documentation #
User Guides
docs/GETTING_STARTED.md- 3-minute quick start guidedocs/MIGRATION_GUIDE.md- Step-by-step migration from workmanagerdocs/README.md- Documentation indexdocs/FAQ.md- Frequently asked questions
Worker-Specific Documentation
docs/workers/FILE_DECOMPRESSION.md- Complete guidedocs/workers/IMAGE_PROCESSING.md- Complete guidedocs/workers/CRYPTO_OPERATIONS.md- Complete guidedocs/workers/FILE_SYSTEM.md- Complete guide
Each guide includes:
- Overview and key benefits
- Usage examples and parameters
- Common use cases
- Error handling and troubleshooting
- Platform differences
Platform Guides
docs/PLATFORM_CONSISTENCY.md- Cross-platform behavior guidedocs/IOS_BACKGROUND_LIMITS.md- iOS 30-second limit guide
Example App Demonstrations
example/lib/pages/demo_scenarios_page.dart- Interactive demos- FileDecompressionWorker demo
- ImageProcessWorker demo
- CryptoWorker demo
- FileSystemWorker demo
- Complete Native Chain (7-step workflow)
- Enhanced Real-World Scenarios
example/lib/pages/file_system_demo_page.dart- Dedicated FileSystem demo- Interactive test environment
- 8 demo operations
- Real-time activity log
Security Improvements #
All workers now include:
- Path traversal validation (prevent
..attacks) - File size limits (prevent DoS)
- URL scheme validation (prevent
file://,ftp://) - Input sanitization for logging
- Atomic operations (cleanup on error)
Specific Security Features:
- FileDecompressionWorker: Zip slip + zip bomb protection
- CryptoWorker: PBKDF2 key derivation (100K iterations)
- HttpDownloadWorker: Checksum verification
- All Workers: Security validator utilities
⚡ Performance #
All workers maintain high performance with low resource usage:
| Worker | Memory Usage | Startup Time | Battery Impact |
|---|---|---|---|
| HttpDownloadWorker | Low | Fast | Minimal |
| HttpUploadWorker | Low | Fast | Minimal |
| FileDecompressionWorker | Low | Fast | Minimal |
| CryptoWorker | Low | Fast | Minimal |
Key: Streaming I/O keeps memory low regardless of file size.
🌐 Platform Consistency #
All features implemented on both Android and iOS with 98-100% API consistency.
Minor difference: CryptoWorker uses AES-CBC (Android) vs AES-GCM (iOS), both AES-256.
🔄 Backward Compatibility #
100% backward compatible - All features are opt-in:
enableResumedefaults totrue(can disable)filesarray is optional (single file API still works)- Validation patterns are optional
- New workers don't affect existing code
🙏 Acknowledgments #
Built on kmpworkmanager v2.3.0 for Kotlin Multiplatform.
Links #
Latest Version: 1.0.1 Status: Production Ready - Stable release for all production apps KMP Parity: 100% (kmpworkmanager v2.3.3) Platforms: Android | iOS