{"id":45813012,"url":"https://github.com/brewkits/native_workmanager","last_synced_at":"2026-04-14T07:00:32.546Z","repository":{"id":338035346,"uuid":"1150153903","full_name":"brewkits/native_workmanager","owner":"brewkits","description":"Native WorkManager: High-performance Flutter background Task Chains with zero-overhead. Harness the full power of Android WorkManager \u0026 iOS BGTaskScheduler using pure Kotlin/Swift Workers.","archived":false,"fork":false,"pushed_at":"2026-04-14T05:10:09.000Z","size":32356,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-14T06:31:08.573Z","etag":null,"topics":["android-workmanager","background","background-fetch","background-processing","background-tasks","battery-efficient","flutter","flutter-plugin","headless-execution","ios-background-tasks","kmp","kotlin","kotlin-multiplatform","memory-optimization","native-performance","performance-tuning","swift","task-chaining","task-scheduler","workmanager"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/native_workmanager","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brewkits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-05T00:11:24.000Z","updated_at":"2026-04-14T05:13:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"1211d674-25d8-4ef2-965f-d4080cc2f303","html_url":"https://github.com/brewkits/native_workmanager","commit_stats":null,"previous_names":["brewkits/native_workmanager"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/brewkits/native_workmanager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brewkits%2Fnative_workmanager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brewkits%2Fnative_workmanager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brewkits%2Fnative_workmanager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brewkits%2Fnative_workmanager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brewkits","download_url":"https://codeload.github.com/brewkits/native_workmanager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brewkits%2Fnative_workmanager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31785681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T02:24:21.117Z","status":"ssl_error","status_checked_at":"2026-04-14T02:24:20.627Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-workmanager","background","background-fetch","background-processing","background-tasks","battery-efficient","flutter","flutter-plugin","headless-execution","ios-background-tasks","kmp","kotlin","kotlin-multiplatform","memory-optimization","native-performance","performance-tuning","swift","task-chaining","task-scheduler","workmanager"],"created_at":"2026-02-26T17:09:54.906Z","updated_at":"2026-04-14T07:00:32.533Z","avatar_url":"https://github.com/brewkits.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/brewkits/native_workmanager/main/assets/logo.svg\" height=\"108\" alt=\"native_workmanager\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003enative_workmanager\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Background tasks for Flutter — \u003cstrong\u003e25+ built-in workers, zero Flutter Engine overhead.\u003c/strong\u003e\u003cbr/\u003e\n  HTTP, file ops, image processing, encryption — all in pure Kotlin \u0026 Swift.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pub.dev/packages/native_workmanager\"\u003e\u003cimg src=\"https://img.shields.io/pub/v/native_workmanager.svg\" alt=\"pub.dev\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pub.dev/packages/native_workmanager/score\"\u003e\u003cimg src=\"https://img.shields.io/pub/points/native_workmanager?label=pub%20points\" alt=\"Pub Points\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/brewkits/native_workmanager/actions\"\u003e\u003cimg src=\"https://github.com/brewkits/native_workmanager/workflows/ci/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg\" alt=\"MIT\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Android-8.0%2B-brightgreen.svg\" alt=\"Android 8.0+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/iOS-14.0%2B-lightgrey.svg\" alt=\"iOS 14.0+\"\u003e\n\u003c/p\u003e\n\n---\n\n## The 30-second pitch\n\n```dart\n// Download → resize → upload — survives app kill, device reboot, low memory\nawait NativeWorkManager\n  .beginWith(TaskRequest(id: 'dl',\n    worker: NativeWorker.httpDownload(url: photoUrl, savePath: '/tmp/raw.jpg')))\n  .then(TaskRequest(id: 'resize',\n    worker: NativeWorker.imageResize(inputPath: '/tmp/raw.jpg',\n      outputPath: '/tmp/thumb.jpg', maxWidth: 512)))\n  .then(TaskRequest(id: 'upload',\n    worker: NativeWorker.httpUpload(url: uploadUrl, filePath: '/tmp/thumb.jpg')))\n  .named('photo-pipeline')\n  .enqueue();\n```\n\nNo boilerplate. No native code to write. No `AndroidManifest.xml` changes. Each step retries independently — if the upload fails, only the upload retries.\n\n---\n\n## Quick Start\n\n**1. Add the dependency:**\n\n```yaml\ndependencies:\n  native_workmanager: ^1.1.2\n```\n\n**2. Initialize once in `main()`:**\n\n```dart\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await NativeWorkManager.initialize();\n  runApp(MyApp());\n}\n```\n\n**3. Schedule a background task:**\n\n```dart\nawait NativeWorkManager.enqueue(\n  taskId: 'daily-sync',\n  worker: NativeWorker.httpSync(url: 'https://api.example.com/sync'),\n  constraints: const Constraints(requiresNetwork: true),\n);\n```\n\n**iOS only** — run once to configure `BGTaskScheduler` automatically:\n\n```bash\ndart run native_workmanager:setup_ios\n```\n\n---\n\n## Why developers switch from `workmanager`\n\nThe dominant `workmanager` plugin spins up a **full Flutter Engine per background task**: ~50–100 MB RAM, up to 3 seconds cold start, a Dart isolate the OS kills the moment memory gets tight. On Xiaomi/Samsung/Huawei devices with aggressive battery optimization, the engine never even starts.\n\n`native_workmanager` runs tasks as pure Kotlin coroutines and Swift async functions — **no engine, no isolate, no cold-start penalty**.\n\n| | `workmanager` | `native_workmanager` |\n|---|:---:|:---:|\n| Memory per task | ~50–100 MB | **~2–5 MB** |\n| Task startup | 1,500–3,000 ms | **\u003c 50 ms** |\n| Built-in HTTP workers | ❌ | ✅ (resumable download, chunked upload, parallel) |\n| Built-in image workers | ❌ | ✅ (resize, crop, convert, thumbnail — EXIF-aware) |\n| Built-in crypto workers | ❌ | ✅ (AES-256-GCM, SHA-256/512, HMAC) |\n| Task chains (A→B→C) | ❌ | ✅ (persist across reboots) |\n| Per-task progress stream | ❌ | ✅ |\n| Survives device reboot | ✅ | ✅ |\n| Custom Dart workers | ✅ | ✅ (opt-in via `DartWorker`) |\n\n\u003e **If you only do HTTP syncs and file ops, you probably don't need Dart workers at all.** Use the native workers directly — they're production-hardened and need zero engine overhead.\n\n---\n\n## 25+ Built-in Workers\n\nAll workers run natively. No Flutter Engine. No setup beyond `initialize()`.\n\n| Category | Workers |\n|----------|---------|\n| **HTTP** | `httpDownload` (resumable), `httpUpload` (multipart), `parallelDownload` (chunked), `httpSync`, `httpRequest` |\n| **Image** | `imageResize`, `imageCrop`, `imageConvert`, `imageThumbnail` — all EXIF-aware |\n| **PDF** | `pdfMerge`, `pdfCompress`, `imagesToPdf` |\n| **Crypto** | `cryptoEncrypt` (AES-256-GCM), `cryptoDecrypt`, `cryptoHash` (SHA-256/512), `hmacSign` |\n| **File** | `fileCopy`, `fileMove`, `fileDelete`, `fileList` |\n| **Storage** | `moveToSharedStorage` (Android MediaStore / iOS Files app) |\n| **Real-time** | `webSocket` — Android |\n\n---\n\n## Track progress in real time\n\n`enqueue()` returns a `TaskHandler` that streams progress and completion events for that specific task — no manual filtering required.\n\n```dart\nfinal handler = await NativeWorkManager.enqueue(\n  taskId: 'big-download',\n  worker: NativeWorker.httpDownload(\n    url: 'https://cdn.example.com/video.mp4',\n    savePath: '/tmp/video.mp4',\n  ),\n);\n\n// Stream progress for this task only\nhandler.progress.listen((p) {\n  print('${p.progress}% — ${p.networkSpeedHuman} — ETA ${p.timeRemainingHuman}');\n});\n\n// Await completion\nfinal result = await handler.result;\nprint(result.success ? 'Done!' : 'Failed: ${result.message}');\n```\n\nOr drop in the built-in widget:\n\n```dart\nTaskProgressCard(handler: handler, title: 'Downloading video')\n```\n\n---\n\n## Task Chains\n\nChain workers into persistent pipelines. Each step only runs when the previous one succeeds, and the entire chain survives app kills and device reboots (SQLite-backed state).\n\n```dart\nawait NativeWorkManager\n  .beginWith(TaskRequest(\n    id: 'download',\n    worker: NativeWorker.httpDownload(\n      url: 'https://cdn.example.com/report.pdf',\n      savePath: '/tmp/report.pdf',\n    ),\n  ))\n  .then(TaskRequest(\n    id: 'encrypt',\n    worker: NativeWorker.cryptoEncrypt(\n      inputPath: '/tmp/report.pdf',\n      outputPath: '/tmp/report.enc',\n      password: vaultKey,\n    ),\n  ))\n  .then(TaskRequest(\n    id: 'upload',\n    worker: NativeWorker.httpUpload(\n      url: 'https://vault.example.com/store',\n      filePath: '/tmp/report.enc',\n    ),\n  ))\n  .named('secure-report-pipeline')\n  .enqueue();\n```\n\nUse `.thenAll([...])` to run tasks in parallel, then continue the chain when all finish.\n\n---\n\n## Custom Dart Workers\n\nFor app-specific logic that must run in Dart, register a top-level function as a background worker:\n\n```dart\n@pragma('vm:entry-point')\nFuture\u003cbool\u003e syncHealthData(Map\u003cString, dynamic\u003e? input) async {\n  final userId = input?['userId'] as String?;\n  await uploadHealthMetrics(userId);\n  return true;\n}\n\n// Register once at startup\nNativeWorkManager.registerDartWorker('health-sync', syncHealthData);\n\n// Schedule it\nawait NativeWorkManager.enqueue(\n  taskId: 'sync-user-42',\n  worker: DartWorker(callbackId: 'health-sync', input: {'userId': '42'}),\n);\n```\n\nDart workers boot a headless Flutter isolate (~50 MB, 1–2 s cold start). The isolate is cached for 5 minutes so back-to-back tasks pay the boot cost only once. For HTTP and file tasks, use native workers instead.\n\n---\n\n## Platform Support\n\n| Feature | Android | iOS |\n|---------|:-------:|:---:|\n| One-time tasks | ✅ | ✅ |\n| Periodic tasks | ✅ | ✅ (BGAppRefresh) |\n| Exact-time triggers | ✅ | ✅ |\n| Task chains (persistent) | ✅ | ✅ |\n| Network / charging constraints | ✅ | ✅ |\n| Per-task progress stream | ✅ | ✅ |\n| Foreground service (long tasks) | ✅ | — |\n| Custom Dart workers | ✅ | ✅ |\n| Min OS version | Android 8.0 (API 26) | iOS 14.0 |\n\n---\n\n## Migrating from `workmanager`\n\nMost migrations take under 10 minutes. The conceptual model is the same; the API is a strict superset.\n\n| `workmanager` | `native_workmanager` |\n|---|---|\n| `Workmanager().initialize(...)` | `NativeWorkManager.initialize()` |\n| `Workmanager().registerOneOffTask(...)` | `NativeWorkManager.enqueue(worker: NativeWorker.httpSync(...))` |\n| `Workmanager().registerPeriodicTask(...)` | `NativeWorkManager.enqueue(trigger: TaskTrigger.periodic(...))` |\n| Custom Dart callback | `DartWorker(callbackId: ...)` |\n\nSee [Migration Guide](doc/MIGRATION_GUIDE.md) for a step-by-step walkthrough.\n\n---\n\n## Common Use Cases\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📥 Resumable large file download\u003c/strong\u003e\u003c/summary\u003e\n\n```dart\nawait NativeWorkManager.enqueue(\n  taskId: 'download-dataset',\n  worker: NativeWorker.httpDownload(\n    url: 'https://data.example.com/dataset.zip',\n    savePath: '/tmp/dataset.zip',\n    headers: {'Authorization': 'Bearer $token'},\n    allowResume: true,\n  ),\n  constraints: const Constraints(requiresUnmeteredNetwork: true),\n);\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🔐 Encrypt \u0026amp; upload sensitive file\u003c/strong\u003e\u003c/summary\u003e\n\n```dart\nawait NativeWorkManager\n  .beginWith(TaskRequest(\n    id: 'encrypt',\n    worker: NativeWorker.cryptoEncrypt(\n      inputPath: '/documents/report.pdf',\n      outputPath: '/tmp/report.enc',\n      password: securePassword,\n    ),\n  ))\n  .then(TaskRequest(\n    id: 'upload',\n    worker: NativeWorker.httpUpload(\n      url: 'https://vault.example.com/store',\n      filePath: '/tmp/report.enc',\n    ),\n  ))\n  .named('secure-backup')\n  .enqueue();\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e⏱ Periodic background sync\u003c/strong\u003e\u003c/summary\u003e\n\n```dart\nawait NativeWorkManager.enqueue(\n  taskId: 'hourly-sync',\n  worker: NativeWorker.httpSync(url: 'https://api.example.com/sync'),\n  trigger: TaskTrigger.periodic(const Duration(hours: 1)),\n  constraints: const Constraints(requiresNetwork: true),\n  existingPolicy: ExistingTaskPolicy.keep,\n);\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📸 Photo backup pipeline\u003c/strong\u003e\u003c/summary\u003e\n\n```dart\nawait NativeWorkManager\n  .beginWith(TaskRequest(\n    id: 'compress',\n    worker: NativeWorker.imageResize(\n      inputPath: photoPath,\n      outputPath: '/tmp/photo_compressed.jpg',\n      maxWidth: 1920,\n      quality: 85,\n    ),\n  ))\n  .then(TaskRequest(\n    id: 'upload',\n    worker: NativeWorker.httpUpload(\n      url: 'https://backup.example.com/upload',\n      filePath: '/tmp/photo_compressed.jpg',\n    ),\n  ))\n  .named('photo-backup')\n  .enqueue();\n```\n\u003c/details\u003e\n\n---\n\n## Listen to task events\n\n```dart\nNativeWorkManager.events.listen((event) {\n  if (event.isStarted) {\n    print('▶ ${event.taskId} started (${event.workerType})');\n    return;\n  }\n  if (event.success) {\n    print('✅ ${event.taskId} — ${event.resultData}');\n  } else {\n    print('❌ ${event.taskId} — ${event.message}');\n  }\n});\n```\n\n---\n\n## Documentation\n\n| Guide | |\n|---|---|\n| [Getting Started](doc/GETTING_STARTED.md) | Full setup walkthrough |\n| [API Reference](doc/API_REFERENCE.md) | All public types and methods |\n| [Migration from workmanager](doc/MIGRATION_GUIDE.md) | Switch in under 10 minutes |\n| [iOS Setup Guide](doc/IOS_SETUP_GUIDE.md) | BGTaskScheduler details |\n| [Architecture](doc/ARCHITECTURE_ANALYSIS.md) | How zero-engine execution works |\n| [Security](doc/SECURITY.md) | SSRF, path traversal, data redaction |\n\n---\n\n## Support\n\n- [GitHub Issues](https://github.com/brewkits/native_workmanager/issues) — bugs and feature requests\n- [Discussions](https://github.com/brewkits/native_workmanager/discussions) — questions and community help\n\n---\n\nMIT License · Made by [BrewKits](https://brewkits.dev)\n\n*Found this useful? A ⭐ on [GitHub](https://github.com/brewkits/native_workmanager) helps others discover it.*\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrewkits%2Fnative_workmanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrewkits%2Fnative_workmanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrewkits%2Fnative_workmanager/lists"}