Complete API documentation for native_workmanager v1.3.3
Main entry point for scheduling and managing background tasks.
Initializes the work manager. Must be called before any other methods.
static Future<void> initialize({
Map<String, DartWorkerCallback>? dartWorkers,
bool debugMode = false,
int maxConcurrentTasks = 4,
int diskSpaceBufferMB = 20,
int cleanupAfterDays = 30,
bool enforceHttps = false,
bool blockPrivateIPs = false,
bool registerPlugins = false,
})Parameters:
dartWorkers- Optional map ofDartWorkerCallbackfor executing Dart code in the background.debugMode- Enable verbose logging (defaults tofalse).maxConcurrentTasks- Maximum number of background tasks running simultaneously (defaults to 4).diskSpaceBufferMB- Required free disk space before I/O tasks run (defaults to 20MB).cleanupAfterDays- Days to keep completed task records in SQLite (defaults to 30, use 0 to disable).enforceHttps- When true, all HTTP workers reject plain HTTP URLs (defaults tofalse).blockPrivateIPs- When true, HTTP workers reject requests to private IP ranges to prevent SSRF (defaults tofalse).registerPlugins- When true, registers all plugins in the background Flutter Engine. Defaults tofalseto maintain the Zero-Engine I/O principle.- Caution: Enabling this increases RAM usage and may cause hardware side-effects (e.g., Bluetooth disconnects).
- Recommendation: Keep this
falseand usesetPluginRegistrantCallbackon the native side for selective registration.
Example:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await NativeWorkManager.initialize();
runApp(MyApp());
}Schedules a single background task.
static Future<TaskHandler> enqueue({
required String taskId,
TaskTrigger trigger = const TaskTrigger.oneTime(),
required Worker worker,
Constraints constraints = const Constraints(),
ExistingTaskPolicy existingPolicy = ExistingTaskPolicy.replace,
String? tag,
})Parameters:
taskId- Unique identifier for the tasktrigger- When/how the task should run. Defaults toTaskTrigger.oneTime()worker- The worker that executes the task logic. Any input data goes through the specificWorkersubclass's own constructor (e.g.NativeWorker.httpSync(...),DartWorker(callbackId: ..., input: ...)) — there is no separateinputDataparameterconstraints- Execution constraints (network, battery, etc.). Defaults toConstraints()existingPolicy- What to do iftaskIdalready has a pending/running task. Defaults toExistingTaskPolicy.replacetag- Optional tag for grouping tasks (seecancelByTag,getTasksByTag)
Returns: TaskHandler — streams progress/result events scoped to this task (see Track progress in real time)
Example:
await NativeWorkManager.enqueue(
taskId: 'api-sync',
trigger: TaskTrigger.periodic(Duration(hours: 1)),
worker: NativeWorker.httpSync(
url: 'https://api.example.com/sync',
),
constraints: Constraints(requiresNetwork: true),
);Creates a task chain for sequential or parallel execution.
static TaskChainBuilder beginWith(TaskRequest firstTask)Returns: TaskChainBuilder for chaining more tasks
Example:
await NativeWorkManager.beginWith(
TaskRequest(id: 'download', worker: HttpDownloadWorker(...)),
).then(
TaskRequest(id: 'process', worker: ImageProcessWorker(...)),
).then(
TaskRequest(id: 'upload', worker: HttpUploadWorker(...)),
).enqueue();Cancels a scheduled task by ID.
static Future<void> cancel({required String taskId})Example:
await NativeWorkManager.cancel(taskId: 'api-sync');Cancels all scheduled tasks.
static Future<void> cancelAll()Example:
await NativeWorkManager.cancelAll();Checks whether taskId has been cancelled or stopped by the OS — for a running DartWorker
callback to poll cooperatively. cancel()/cancelAll() do not interrupt a callback already
executing (Dart has no API to preemptively abort a running Future); a callback doing
long-running work must check this between chunks and return promptly once it turns true.
static Future<bool> isTaskCancelled(String taskId)Example:
@pragma('vm:entry-point')
Future<bool> longSync(Map<String, dynamic>? input) async {
final taskId = input?['__taskId'] as String?;
for (var i = 1; i <= 100; i++) {
if (taskId != null && await NativeWorkManager.isTaskCancelled(taskId)) {
return false; // bail out — do not keep working
}
await processChunk(i);
}
return true;
}Added in 1.8.0 (discussion #66). Returns
false(never throws) iftaskIdis empty or the platform channel call fails.
Stream of task completion events.
static Stream<TaskEvent> get eventsReturns: Stream emitting TaskEvent for each completed task
Example:
NativeWorkManager.events.listen((event) {
print('Task ${event.taskId}: ${event.success ? "✅" : "❌"}');
print('Message: ${event.message}');
});// Every task the store knows about.
final all = await NativeWorkManager.allTasks();
// Just the ones in a given state.
final running = await NativeWorkManager.getTasksByStatus(TaskStatus.running);
// One task.
final record = await NativeWorkManager.getTaskRecord(taskId: 'sync');
final status = await NativeWorkManager.getTaskStatus(taskId: 'sync');
// Bulk pause/resume — these operate on whatever is currently running/paused.
await NativeWorkManager.pauseAll();
await NativeWorkManager.resumeAll();| Method | Returns |
|---|---|
allTasks() |
List<TaskRecord> — every persisted task |
getTasksByStatus(TaskStatus) |
List<TaskRecord> filtered by state |
getTaskRecord(taskId:) |
TaskRecord? |
getTaskStatus(taskId:) |
TaskStatus? |
pauseAll() / resumeAll() |
void — pauses every running task / resumes every paused one |
Fixed in 1.6.0.
getTasksByStatus,pauseAllandresumeAllthrewMissingPluginExceptionon both platforms in every earlier version — they invoked a method channel neither Android nor iOS implemented. If you are upgrading from ≤1.5.0 and had worked around them, the workaround can go.
A completed task's TaskEvent.resultData carries whatever the worker produced. The typed
helpers in worker_results.dart parse it:
NativeWorkManager.events.listen((event) {
if (!event.success) return;
final result = DownloadResult.from(event.resultData);
print('Saved ${result?.fileSize} bytes to ${result?.filePath}');
});Available parsers: DownloadResult, UploadResult, ParallelUploadResult,
HttpRequestResult, CryptoResult, CompressionResult, DecompressionResult,
ImageProcessResult, FileSystemResult.
Also fixed in 1.6.0.
resultDatawas alwaysnullon Android before this release, so every one of these helpers returned an empty object there. A few of them were additionally reading field names the workers never emit. Both are corrected — see the changelog for the per-parser detail.Two known per-platform gaps remain, by design rather than oversight:
ParallelUploadResult.files(the per-file breakdown) is iOS-only — Android reports the counters without it — andParallelDownloadResulthas no producer at all, becauseParallelHttpDownloadWorkerdownloads a single file over parallel range requests and reports the single-file shape. UseDownloadResultfor it.
Factory for creating built-in native workers (no Flutter engine overhead).
Simple HTTP request worker.
static Worker httpRequest({
required String url,
HttpMethod method = HttpMethod.get,
Map<String, String> headers = const {},
String? body,
Duration timeout = const Duration(seconds: 30),
TokenRefreshConfig? tokenRefresh,
})Multipart file upload worker.
static Worker httpUpload({
required String url,
required String filePath,
String fileFieldName = 'file',
String? fileName,
String? mimeType,
Map<String, String> headers = const {},
Map<String, String> additionalFields = const {},
Duration timeout = const Duration(minutes: 5),
bool useBackgroundSession = false,
})File download worker with resume support.
static Worker httpDownload({
required String url,
required String savePath,
Map<String, String> headers = const {},
Duration timeout = const Duration(minutes: 5),
bool enableResume = true,
String? expectedChecksum,
String checksumAlgorithm = 'SHA-256',
bool useBackgroundSession = false,
bool skipExisting = false,
bool allowPause = false,
Map<String, String>? cookies,
String? authToken,
String authHeaderTemplate = 'Bearer {accessToken}',
DuplicatePolicy onDuplicate = DuplicatePolicy.overwrite,
bool moveToPublicDownloads = false,
bool saveToGallery = false,
})Bidirectional sync worker with retry.
static Worker httpSync({
required String url,
HttpMethod method = HttpMethod.post,
Map<String, String> headers = const {},
Map<String, dynamic>? requestBody,
Duration timeout = const Duration(seconds: 60),
TokenRefreshConfig? tokenRefresh,
RequestSigning? requestSigning,
})Chunked parallel download — splits the file into numChunks ranged requests for faster downloads on high-bandwidth connections.
static Worker parallelHttpDownload({
required String url,
required String savePath,
int numChunks = 4,
Map<String, String> headers = const {},
Duration timeout = const Duration(minutes: 10),
String? expectedChecksum,
String checksumAlgorithm = 'SHA-256',
bool showNotification = false,
})Two ways to upload several files, for different situations. Neither is invoked via a
NativeWorker.xxx() factory the way most other workers are:
ParallelHttpUploadWorker(...)— construct directly (it's aWorkersubclass, not aNativeWorkerfactory). Uploads each file as a separate concurrent multipart request, with per-host concurrency (maxConcurrent) and independent per-file retries.NativeWorker.multiUpload(...)— bundles all files into a single multipart request (reusesHttpUploadWorker'sfilesarray). Simpler, but one request means one success/failure for the whole batch.
static MultiUploadWorker multiUpload({
required String url,
required List<UploadFile> files,
Map<String, String> headers = const {},
Map<String, String> additionalFields = const {},
Duration timeout = const Duration(minutes: 10),
bool useBackgroundSession = false,
})// Direct construction — no NativeWorker.parallelHttpUpload() factory exists.
ParallelHttpUploadWorker({
required String url,
required List<UploadFile> files,
Map<String, String> headers = const {},
Map<String, String> fields = const {},
int maxConcurrent = 3,
int maxRetries = 1,
Duration timeout = const Duration(minutes: 5),
bool showNotification = false,
String? notificationTitle,
String? notificationBody,
CertificatePinning? certificatePinning,
})Example:
worker: ParallelHttpUploadWorker(
url: 'https://api.example.com/photos',
files: [
UploadFile(filePath: '/data/user/0/.../img1.jpg'),
UploadFile(filePath: '/data/user/0/.../img2.jpg', fieldName: 'photo'),
],
maxConcurrent: 3,
maxRetries: 2,
),Invoke a custom native worker class you registered yourself (Android SimpleAndroidWorkerFactory / iOS IosWorkerFactory). See Custom Native Workers.
static Worker custom({
required String className,
Map<String, dynamic>? input,
})Deprecated since v1.1.0 — native ZIP support was removed. Do not use in new code.
static Worker fileCompress({
required String inputPath,
required String outputPath,
CompressionLevel level = CompressionLevel.medium,
List<String> excludePatterns = const [],
bool deleteOriginal = false,
})Deprecated since v1.1.0 — native ZIP support was removed. Do not use in new code.
static Worker fileDecompress({
required String zipPath,
required String targetDir,
bool deleteAfterExtract = false,
bool overwrite = true,
})Copy files or directories.
static Worker fileCopy({
required String sourcePath,
required String destinationPath,
bool overwrite = false,
bool recursive = true,
})Move files or directories.
static Worker fileMove({
required String sourcePath,
required String destinationPath,
bool overwrite = false,
})Delete files or directories.
static Worker fileDelete({
required String path,
bool recursive = false,
})List files in directory with pattern matching.
static Worker fileList({
required String path,
String? pattern,
bool recursive = false,
})Create directory.
static Worker fileMkdir({
required String path,
bool createParents = true,
})Process images (resize, compress, convert).
static Worker imageProcess({
required String inputPath,
required String outputPath,
int? maxWidth,
int? maxHeight,
bool maintainAspectRatio = true,
int quality = 85,
ImageFormat? outputFormat,
Rect? cropRect,
bool deleteOriginal = false,
})cropRect is dart:ui's Rect (import 'dart:ui' show Rect;) — not a package-specific type.
Calculate file hash.
static Worker hashFile({
required String filePath,
HashAlgorithm algorithm = HashAlgorithm.sha256,
})Calculate string hash.
static Worker hashString({
required String data,
HashAlgorithm algorithm = HashAlgorithm.sha256,
})Encrypt file with AES-256-GCM.
static Worker cryptoEncrypt({
required String inputPath,
required String outputPath,
required String password,
})Decrypt AES-256-GCM encrypted file.
static Worker cryptoDecrypt({
required String inputPath,
required String outputPath,
required String password,
})Merge multiple PDF files into one.
static Worker pdfMerge({
required List<String> inputPaths,
required String outputPath,
})Re-render a PDF at lower quality to reduce file size.
static Worker pdfCompress({
required String inputPath,
required String outputPath,
int quality = 80,
})Convert image files into a PDF (one image per page).
static Worker pdfFromImages({
required List<String> imagePaths,
required String outputPath,
PdfPageSize pageSize = PdfPageSize.a4,
int margin = 0,
})Move a file into shared/public storage (Android MediaStore — Downloads/Pictures/Movies; iOS Files app).
static MoveToSharedStorageWorker moveToSharedStorage({
required String sourcePath,
required SharedStorageType storageType,
String? fileName,
String? mimeType,
String? subDir,
})Send a sequence of WebSocket messages and optionally capture responses. Android only.
static Worker webSocket({
required String url,
List<String> messages = const [],
Map<String, String> headers = const {},
int timeoutSeconds = 30,
int receiveMessages = 1,
String? storeResponseAt,
int? pingIntervalSeconds,
})Worker for custom Dart logic (uses Flutter engine).
DartWorker({
required String callbackId,
Map<String, dynamic>? input,
bool autoDispose = false,
int? timeoutMs,
})Parameters:
callbackId- Identifier for registered callback functioninput- Optional data passed to callbackautoDispose- Whether to dispose Flutter engine after execution (default:false)timeoutMs- Optional execution timeout in milliseconds
Example:
// Register callback (in main.dart during initialize)
@WorkerCallback('processData')
Future<bool> myProcessData(Map<String, dynamic>? input) async {
// Your Dart logic here
print('Processing data...');
return true;
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await NativeWorkManager.initialize(
dartWorkers: {
'processData': myProcessData,
}
);
runApp(MyApp());
}
// Schedule task
await NativeWorkManager.enqueue(
taskId: 'process',
trigger: TaskTrigger.oneTime(),
worker: DartWorker(callbackId: 'processData'),
);Defines when tasks should execute.
Execute task once after optional delay.
static TaskTrigger oneTime([Duration initialDelay = Duration.zero])Example:
TaskTrigger.oneTime(Duration(seconds: 30)) // Run after 30 secondsExecute task repeatedly at fixed interval.
static TaskTrigger periodic(
Duration interval, {
Duration? flexInterval,
Duration? initialDelay,
bool runImmediately = true,
})Parameters:
interval: Time between executions (minimum 15 minutes).flexInterval: (Android only) Flex window for OS optimization.initialDelay: (New in v1.2.3) Delay before the very first execution.runImmediately: Whether the first execution fires right away (subject toinitialDelay) or waits a fullintervalbefore the first run. Defaults totrue.
Example:
// Run every hour, but wait 30 mins before first run
TaskTrigger.periodic(
Duration(hours: 1),
initialDelay: Duration(minutes: 30),
)Note: Minimum interval is 15 minutes on both iOS and Android. initialDelay ensures the task doesn't run immediately upon registration.
Execute when device is idle (Android only).
static TaskTrigger deviceIdle()Execute when battery is not low.
static TaskTrigger batteryOkay()Execution constraints for tasks.
Constraints({
bool requiresNetwork = false,
bool requiresUnmeteredNetwork = false,
bool requiresCharging = false,
bool requiresDeviceIdle = false,
bool requiresBatteryNotLow = false,
bool requiresStorageNotLow = false,
bool allowWhileIdle = false,
bool isHeavyTask = false,
QoS qos = QoS.background,
ExactAlarmIOSBehavior exactAlarmIOSBehavior = ExactAlarmIOSBehavior.showNotification,
BackoffPolicy backoffPolicy = BackoffPolicy.exponential,
int backoffDelayMs = 30000,
int maxRetries = 3,
Set<SystemConstraint> systemConstraints = const {},
BGTaskType? bgTaskType,
ForegroundServiceType? foregroundServiceType,
ForegroundNotificationConfig? foregroundNotificationConfig,
})allowWhileIdle: (Android only) If true, uses Expedited Work to run tasks silently even when the device is locked or in Doze mode. Warning: Do not use simultaneously withisHeavyTask: true.
Note on FGS Bypass: Providing a foregroundNotificationConfig automatically promotes the task to an Android Foreground Service. This is the recommended way to bypass battery optimizations for critical, long-running tasks.
Example:
Constraints(
requiresNetwork: true,
foregroundServiceType: ForegroundServiceType.dataSync,
foregroundNotificationConfig: ForegroundNotificationConfig(
title: "Syncing Data",
body: "Please wait...",
showCancelButton: true,
),
)enum HttpMethod {
get,
post,
put,
delete,
patch,
}enum CompressionLevel {
low,
medium,
high,
}enum ImageFormat {
jpeg,
png,
webp,
}enum HashAlgorithm {
md5, // ⚠️ Deprecated — cryptographically broken, use sha256/sha512
sha1, // ⚠️ Deprecated — cryptographically broken, use sha256/sha512
sha256,
sha512,
}enum BackoffPolicy {
exponential,
linear,
}Used to specify the type of Foreground Service for Android 14+ compliance.
enum ForegroundServiceType {
dataSync, // Default — safe for most heavy tasks, no permissions required
location, // Requires ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION
mediaPlayback, // Requires FOREGROUND_SERVICE_MEDIA_PLAYBACK (Android 14+)
camera, // Requires CAMERA + FOREGROUND_SERVICE_CAMERA (Android 14+)
microphone, // Requires RECORD_AUDIO + FOREGROUND_SERVICE_MICROPHONE (Android 14+)
health, // Requires BODY_SENSORS + FOREGROUND_SERVICE_HEALTH (Android 14+)
}Configuration for the mandatory notification shown when a task runs as a Foreground Service on Android.
const ForegroundNotificationConfig({
required String title,
required String body,
String? iconName,
String? colorHex,
bool showCancelButton = true,
String cancelText = "Cancel",
})Parameters:
title- The primary title of the notification.body- The description text shown under the title.iconName- Name of the drawable resource to use as small icon (e.g., "ic_notification"). Defaults to app icon.colorHex- Hex color code for the notification (e.g., "#FF5722").showCancelButton- Whether to show a "Cancel" action button in the notification.cancelText- Label for the cancel button.
Emitted when task completes.
class TaskEvent {
final String taskId;
final bool success;
final String? message;
final String? errorCode;
final Map<String, dynamic>? resultData;
final DateTime timestamp;
final bool isStarted;
final String? workerType;
}isStarted is true for the transient "worker began execution" event (see enqueue()'s progress stream); resultData carries worker-specific output (e.g. downloaded file size, hash value).
Example:
NativeWorkManager.events.listen((event) {
if (event.success) {
print('✅ ${event.taskId} completed: ${event.message}');
} else {
print('❌ ${event.taskId} failed: ${event.message}');
}
});Builder for creating task chains.
Add sequential task.
TaskChainBuilder then(TaskRequest task)Add parallel tasks.
TaskChainBuilder thenAll(List<TaskRequest> tasks)Schedule the chain.
Future<ScheduleResult> enqueue()Represents a task in a chain.
TaskRequest({
required String id,
required Worker worker,
Constraints constraints = const Constraints(),
})For large file transfers that survive app termination.
// Use with httpDownload or httpUpload
NativeWorker.httpDownload(
url: 'https://example.com/large-file.zip',
savePath: '/path/to/save.zip',
useBackgroundSession: true, // ← iOS Background URLSession
)Benefits:
- Survives app termination
- No time limits
- Automatic retry on network failure
The most common real-world reason a periodic task runs late is the OS — or the device manufacturer — deferring it. These report what the OS actually says.
final report = await NativeWorkManager.batteryRestriction();
if (report.isExempt == false) {
await NativeWorkManager.openBatteryOptimizationSettings();
}| Method | Returns | Notes |
|---|---|---|
batteryRestriction() |
BatteryRestrictionReport |
Pure diagnostic. Does not require initialize(). |
openBatteryOptimizationSettings() |
Future<bool> |
Opens the system list. No permission needed. |
requestDisableBatteryOptimization() |
BatteryOptimizationRequestResult |
Direct dialog. Needs a host-app permission — see below. |
BatteryRestrictionReport
| Field | Type | Meaning |
|---|---|---|
isExempt |
bool? |
PowerManager.isIgnoringBatteryOptimizations(). null = no answer (iOS, or an OEM build that threw). |
manufacturer |
String? |
Build.MANUFACTURER, lowercased. null on iOS. |
canOpenSettings |
bool |
Whether the settings screen resolves on this device — checked, not assumed. |
isSupported |
bool |
false whenever isExempt is null. |
isExempt: trueis not a guarantee. It reflects one stock-Android list. Xiaomi (MIUI/HyperOS), Samsung, Huawei, Oppo and Vivo run their own task killer on top of it, so a device can reporttrueand still stretch a 15-minute task into hours.
There are deliberately no per-manufacturer settings deep links — those screens are
undocumented internal activities that get renamed between firmware builds. Use manufacturer
to word your own guidance.
BatteryOptimizationRequestResult
shown · alreadyExempt · missingPermission · unavailable · notSupported
requestDisableBatteryOptimization() needs this in your manifest:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />The plugin never declares it — it is Play-policy restricted and a library manifest merges into
every consumer app. Without it the call returns missingPermission rather than throwing. Unless
your app fits one of Google's eligible categories, prefer openBatteryOptimizationSettings().
See ANDROID_SETUP.md for the full guidance.
Version: 1.8.3 Last Updated: 2026-09-24