### Build Android Example App
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Build the debug version of the Android example application. This command should be run from the example directory.
```bash
cd example && flutter build apk --debug
```
--------------------------------
### Clone and Run Example
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/example/README.md
Commands to download and execute the example project locally.
```bash
git clone https://github.com/fluttercommunity/flutter_workmanager.git
cd flutter_workmanager/example
flutter run
```
--------------------------------
### Build example application
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Commands to build the example application for debugging purposes.
```bash
cd example
flutter build apk --debug
flutter build ios --debug --no-codesign
```
--------------------------------
### Build iOS Example App
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Build the debug version of the iOS example application without codesigning. This command should be run from the example directory.
```bash
cd example && flutter build ios --debug --no-codesign
```
--------------------------------
### Build Verification Commands
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/SPM_MIGRATION_PLAN.md
Commands to verify the example app build for both dependency managers.
```bash
flutter config --no-enable-swift-package-manager
cd example && flutter build ios --debug --no-codesign
```
```bash
flutter config --enable-swift-package-manager
cd example && flutter build ios --debug --no-codesign
```
--------------------------------
### Install Workmanager Dependency
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Add the package to your pubspec.yaml file and fetch dependencies.
```yaml
dependencies:
workmanager: ^0.8.0
```
```bash
flutter pub get
```
--------------------------------
### Run Flutter Pub Get
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Execute this command in your terminal after updating pubspec.yaml to fetch the new dependency.
```bash
flutter pub get
```
--------------------------------
### Run Android Native Tests
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Execute native Android tests for the workmanager_android module. Ensure you are in the example directory before running.
```bash
cd example/android && ./gradlew :workmanager_android:test
```
--------------------------------
### Tabs Component Syntax
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Example syntax for using the Tabs and TabItem components from the docs.page library. Ensure both 'label' and 'value' props are included on TabItem.
```jsx
Content here
```
--------------------------------
### Add Comprehensive Task Logging
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Implement detailed logging for task start, input data, duration, and stack traces to aid in debugging.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
final startTime = DateTime.now();
print('🚀 Task started: $task');
print('📊 Input data: $inputData');
try {
// Your task implementation
final result = await performTask(task, inputData);
final duration = DateTime.now().difference(startTime);
print('✅ Task completed in ${duration.inSeconds}s');
return result;
} catch (e, stackTrace) {
final duration = DateTime.now().difference(startTime);
print('❌ Task failed after ${duration.inSeconds}s: $e');
print('📋 Stack trace: $stackTrace');
return false; // Retry
}
});
}
```
--------------------------------
### iOS Logging Debug Handler Setup
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure the logging debug handler in your AppDelegate for iOS to view background task execution in the Xcode console. Ensure the workmanager_apple library is imported.
```swift
import workmanager_apple
@main
class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Option 1: Logging debug handler (visible in Xcode console)
WorkmanagerDebug.setCurrent(LoggingDebugHandler())
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
```
--------------------------------
### Android Logging Debug Handler Setup
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure the logging debug handler in your Application class to view background task execution in adb logcat. Ensure the WorkmanagerDebug class is imported.
```kotlin
import dev.fluttercommunity.workmanager.WorkmanagerDebug
import dev.fluttercommunity.workmanager.LoggingDebugHandler
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Option 1: Logging debug handler (visible in adb logcat)
WorkmanagerDebug.setCurrent(LoggingDebugHandler())
}
}
```
--------------------------------
### Pull Request Description Template
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
A template for describing changes in a pull request, including a summary and a section for breaking changes with before/after code examples.
```markdown
## Summary
- Brief change description
Fixes #123
## Breaking Changes (if applicable)
**Before:** `old code`
**After:** `new code`
```
--------------------------------
### iOS Notification Debug Handler Setup
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure the notification debug handler in your AppDelegate for iOS. This can be customized with a specific category identifier and thread identifier.
```swift
import workmanager_apple
@main
class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Option 2: Notification debug handler
// WorkmanagerDebug.setCurrent(NotificationDebugHandler())
// Option 3: Notification handler with custom category
// WorkmanagerDebug.setCurrent(NotificationDebugHandler(
// categoryIdentifier: "myAppDebugCategory",
// threadIdentifier: "workmanager_debug_thread"
// ))
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
```
--------------------------------
### Android Notification Debug Handler Setup
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure the notification debug handler in your Application class. This requires notification permissions and can be customized with a specific channel ID and group key for Android 8.0+.
```kotlin
import dev.fluttercommunity.workmanager.WorkmanagerDebug
import dev.fluttercommunity.workmanager.NotificationDebugHandler
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Option 2: Notification debug handler (requires notification permissions)
// WorkmanagerDebug.setCurrent(NotificationDebugHandler())
// Option 3: Notification handler with custom channel
// val channelId = "MyAppDebugChannel"
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// val channel = NotificationChannel(channelId, "Debug", NotificationManager.IMPORTANCE_DEFAULT)
// getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
// }
// WorkmanagerDebug.setCurrent(NotificationDebugHandler(
// channelId = channelId,
// groupKey = "workmanager_debug_group"
// ))
}
}
```
--------------------------------
### BackoffPolicy: Exponential Retry
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure exponential backoff for retrying tasks that fail. The delay increases exponentially, starting from 30 seconds and potentially reaching up to 5 hours.
```dart
import 'package:workmanager/workmanager.dart';
// Exponential backoff: 30s, 1m, 2m, 4m... up to 5 hours
Workmanager().registerOneOffTask(
"upload-task",
"file_upload",
backoffPolicy: BackoffPolicy.exponential,
backoffPolicyDelay: Duration(seconds: 30),
);
```
--------------------------------
### Run integration tests
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Commands to execute integration tests for iOS and Android platforms.
```bash
# iOS integration tests
melos run test:drive_ios
# Android integration tests
melos run test:drive_android
```
--------------------------------
### Cancel task by unique name
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Stops a specific task from executing if it has not started yet.
```dart
import 'package:workmanager/workmanager.dart';
// Cancel a specific task
await Workmanager().cancelByUniqueName("sync-task-1");
// Example: Cancel upload task when user cancels action
Future cancelUpload(String uploadTaskId) async {
await Workmanager().cancelByUniqueName(uploadTaskId);
print('Upload task cancelled: $uploadTaskId');
}
```
--------------------------------
### Package.swift Configuration
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/SPM_MIGRATION_PLAN.md
The manifest file defining the Swift package targets and resources.
```swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "workmanager_apple",
platforms: [
.iOS(.v14)
],
products: [
.library(name: "workmanager_apple", targets: ["workmanager_apple"])
],
targets: [
.target(
name: "workmanager_apple",
resources: [.process("Resources")]
)
]
)
```
--------------------------------
### Manage package versions
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Command to coordinate version bumps across all packages in the monorepo.
```bash
# Bump versions across related packages
melos version
```
--------------------------------
### Run project tests
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Commands to execute unit, native, and integration tests across the monorepo.
```bash
# All tests
melos run test
# Specific package tests
cd workmanager_android && flutter test
cd workmanager_apple && flutter test
# Native tests
cd example/android && ./gradlew :workmanager_android:test
cd example/ios && xcodebuild test -workspace Runner.xcworkspace -scheme Runner
```
--------------------------------
### Workmanager.cancelByUniqueName
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Cancels a specific scheduled task by its unique name. This stops the task from executing if it hasn't started yet.
```APIDOC
## Workmanager.cancelByUniqueName
### Description
Cancels a specific scheduled task by its unique name. This stops the task from executing if it hasn't started yet.
### Method
POST
### Endpoint
`/workmanager/cancelByUniqueName` (Internal)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **uniqueName** (string) - Required - The unique name of the task to cancel.
### Request Example
```dart
await Workmanager().cancelByUniqueName("sync-task-1");
// Example: Cancel upload task when user cancels action
Future cancelUpload(String uploadTaskId) async {
await Workmanager().cancelByUniqueName(uploadTaskId);
print('Upload task cancelled: $uploadTaskId');
}
```
### Response
#### Success Response (200)
Indicates the task cancellation request was processed.
#### Response Example
```json
{
"status": "cancelled"
}
```
```
--------------------------------
### Initialize Workmanager in main()
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Initialize the Workmanager plugin by calling `Workmanager().initialize()` with your callback dispatcher function in the `main` method.
```dart
import 'package:flutter/foundation.dart';
void main() {
Workmanager().initialize(callbackDispatcher);
runApp(MyApp());
}
```
--------------------------------
### Inspect Android Jobs via ADB
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Use ADB commands to inspect, monitor, and force-run Android jobs during development.
```bash
# View scheduled jobs
adb shell dumpsys jobscheduler | grep yourapp
# View detailed job info
adb shell dumpsys jobscheduler yourapp
# Force run job (debug only)
adb shell cmd jobscheduler run -f yourapp JOB_ID
```
```bash
# Monitor WorkManager logs
adb logcat | grep WorkManager
# Monitor app background execution
adb logcat | grep "yourapp"
```
```bash
# Check if your app is whitelisted from battery optimization
adb shell dumpsys deviceidle whitelist
# Check battery optimization status
adb shell settings get global battery_saver_constants
# Force device into idle mode (testing)
adb shell dumpsys deviceidle force-idle
```
--------------------------------
### BackoffPolicy: Linear Retry
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Implement linear backoff for task retries, where the delay increases by a fixed amount for each subsequent retry, starting from the specified initial delay.
```dart
import 'package:workmanager/workmanager.dart';
// Linear backoff: 30s, 60s, 90s, 120s...
Workmanager().registerOneOffTask(
"sync-task",
"data_sync",
backoffPolicy: BackoffPolicy.linear,
backoffPolicyDelay: Duration(seconds: 30),
);
```
--------------------------------
### GitHub Actions Matrix Configuration
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/SPM_MIGRATION_PLAN.md
YAML configuration for testing both CocoaPods and SPM build paths in CI.
```yaml
strategy:
matrix:
spm_enabled: [true, false]
include:
- spm_enabled: true
config_cmd: "flutter config --enable-swift-package-manager"
name: "SPM"
- spm_enabled: false
config_cmd: "flutter config --no-enable-swift-package-manager"
name: "CocoaPods"
```
--------------------------------
### Run All Tests with Melos
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Execute all tests across the project using Melos. This is the recommended way to run tests.
```bash
melos run test
```
--------------------------------
### Run Individual Package Tests
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Run tests within a specific package. Navigate to the package directory first.
```bash
cd workmanager_android && flutter test
```
```bash
cd workmanager_apple && flutter test
```
```bash
cd workmanager && flutter test
```
--------------------------------
### Current iOS Directory Structure
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/SPM_MIGRATION_PLAN.md
The existing file layout for the workmanager_apple plugin before migration.
```text
workmanager_apple/ios/
├── Assets/
├── Classes/
│ ├── BackgroundTaskOperation.swift
│ ├── BackgroundWorker.swift
│ ├── Extensions.swift
│ ├── LoggingDebugHandler.swift
│ ├── NotificationDebugHandler.swift
│ ├── SimpleLogger.swift
│ ├── ThumbnailGenerator.swift
│ ├── UserDefaultsHelper.swift
│ ├── WMPError.swift
│ ├── WorkmanagerDebugHandler.swift
│ ├── WorkmanagerPlugin.swift
│ └── pigeon/
│ └── WorkmanagerApi.g.swift
├── Resources/
│ └── PrivacyInfo.xcprivacy
└── workmanager_apple.podspec
```
--------------------------------
### Initialize Workmanager
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Initialize the Workmanager plugin without debug parameters before setting up platform-specific handlers.
```dart
await Workmanager().initialize(callbackDispatcher);
```
--------------------------------
### Implement WorkmanagerPlatform Interface
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/workmanager_platform_interface/README.md
To create a new platform-specific implementation of workmanager, extend the `WorkmanagerPlatform` class. This involves defining the platform-specific behavior for background task management. After implementation, register your custom platform instance by calling `WorkmanagerPlatform.instance = MyWorkmanagerPlatform()`.
```dart
WorkmanagerPlatform.instance = MyWorkmanagerPlatform()
```
--------------------------------
### Implement Task Callback Dispatcher
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/task-status.mdx
Defines the entry point for background tasks using the Workmanager executeTask method.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
try {
// Your task logic here
final result = await performWork(task, inputData);
if (result.isSuccess) {
return true; // ✅ Task succeeded
} else {
return false; // 🔄 Retry with backoff (Android) or manual reschedule (iOS)
}
} catch (e) {
// 🔥 Permanent failure - will not retry
throw Exception('Task failed: $e');
}
});
}
```
--------------------------------
### Run SwiftLint Formatter
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Apply SwiftLint formatting to Swift code files. The --fix flag attempts to automatically fix formatting issues.
```bash
swiftlint --fix
```
--------------------------------
### Run ktlint Formatter
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Apply ktlint formatting to Kotlin code files. The -F flag attempts to automatically fix formatting issues.
```bash
ktlint -F .
```
--------------------------------
### Configure Task Constraints
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Define device conditions like network status or battery level that must be met for a task to execute.
```dart
Workmanager().registerOneOffTask(
"sync-task",
"data_sync",
constraints: Constraints(
networkType: NetworkType.connected, // Require internet connection
requiresBatteryNotLow: true, // Don't run when battery is low
requiresCharging: false, // Can run when not charging
requiresDeviceIdle: false, // Can run when device is active
requiresStorageNotLow: true, // Don't run when storage is low
),
);
```
```dart
// Different network requirements
NetworkType.connected // Any internet connection
NetworkType.unmetered // WiFi or unlimited data only
NetworkType.not_required // Can run without internet
```
```dart
constraints: Constraints(
requiresBatteryNotLow: true, // Wait for adequate battery
requiresCharging: true, // Only run when plugged in
)
```
--------------------------------
### Configure iOS Debug Handlers
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Set up logging or notification handlers in the AppDelegate to track background task execution on iOS.
```swift
// In your AppDelegate.swift
import workmanager_apple
@main
class AppDelegate: FlutterAppDelegate {
override fun application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
WorkmanagerDebug.setCurrent(LoggingDebugHandler())
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
```
```swift
WorkmanagerDebug.setCurrent(NotificationDebugHandler())
```
--------------------------------
### Configure iOS Periodic Tasks
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Set up periodic tasks with custom frequency in Info.plist and AppDelegate.
```xml
UIBackgroundModes
processing
BGTaskSchedulerPermittedIdentifiers
com.yourapp.periodic_task
```
```swift
import workmanager_apple
// In application didFinishLaunching
WorkmanagerPlugin.registerPeriodicTask(
withIdentifier: "com.yourapp.periodic_task",
frequency: NSNumber(value: 20 * 60) // 20 minutes (15 min minimum)
)
```
--------------------------------
### Proposed SPM Directory Structure
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/SPM_MIGRATION_PLAN.md
The target directory structure required for Swift Package Manager compliance.
```text
workmanager_apple/ios/
├── Sources/
│ └── workmanager_apple/
│ ├── include/
│ │ └── workmanager_apple-umbrella.h (if needed)
│ └── [all .swift files moved here]
└── Resources/
└── PrivacyInfo.xcprivacy
```
--------------------------------
### Validate packages for publishing
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Commands to perform a dry-run validation to ensure packages are ready for publication.
```bash
# Validate all packages are ready for publishing
melos run publish:dry-run
# Or for individual packages:
cd workmanager && dart pub publish --dry-run
cd workmanager_android && dart pub publish --dry-run
cd workmanager_apple && dart pub publish --dry-run
cd workmanager_platform_interface && dart pub publish --dry-run
```
--------------------------------
### Configure iOS Info.plist for Background Fetch
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Add the 'fetch' background mode to your Info.plist file to enable Background Fetch for periodic tasks.
```xml
UIBackgroundModes
fetch
```
--------------------------------
### Implement Workmanager Background Tasks
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
The callback dispatcher must be a top-level function or static method annotated with @pragma('vm:entry-point'). It handles task execution logic and returns a boolean indicating success or failure for retry purposes.
```dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
import 'package:shared_preferences/shared_preferences.dart';
const simpleTaskKey = "com.example.simpleTask";
const periodicSyncKey = "com.example.periodicSync";
const fileUploadKey = "com.example.fileUpload";
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
print('Executing task: $task at ${DateTime.now()}');
print('Input data: $inputData');
try {
switch (task) {
case simpleTaskKey:
// Simple one-off task
await prefs.setString('lastSimpleTask', DateTime.now().toIso8601String());
print('Simple task completed');
break;
case periodicSyncKey:
// Periodic data sync
await Future.delayed(Duration(seconds: 2)); // Simulate API call
await prefs.setString('lastSync', DateTime.now().toIso8601String());
print('Periodic sync completed');
break;
case fileUploadKey:
final fileName = inputData?['fileName'] as String?;
final attempt = inputData?['attempt'] ?? 1;
if (attempt < 3) {
print('Upload attempt $attempt for $fileName - simulating retry');
return Future.value(false); // Trigger retry
}
print('Upload succeeded for $fileName');
break;
case Workmanager.iOSBackgroundTask:
// iOS Background Fetch
await prefs.setString('lastBackgroundFetch', DateTime.now().toIso8601String());
print('iOS background fetch completed');
break;
default:
print('Unknown task: $task');
return Future.value(false);
}
return Future.value(true);
} catch (e) {
print('Task failed with error: $e');
return Future.error(e);
}
});
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
bool _initialized = false;
Future _initializeWorkmanager() async {
await Workmanager().initialize(callbackDispatcher);
setState(() => _initialized = true);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Workmanager Example')),
body: ListView(
padding: EdgeInsets.all(16),
children: [
ElevatedButton(
onPressed: _initializeWorkmanager,
child: Text('Initialize Workmanager'),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: _initialized ? () {
Workmanager().registerOneOffTask(
simpleTaskKey,
simpleTaskKey,
initialDelay: Duration(seconds: 5),
);
} : null,
child: Text('Schedule One-Off Task'),
),
ElevatedButton(
onPressed: _initialized && Platform.isAndroid ? () {
Workmanager().registerPeriodicTask(
periodicSyncKey,
periodicSyncKey,
frequency: Duration(hours: 1),
constraints: Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: true,
),
);
} : null,
child: Text('Schedule Periodic Task (Android)'),
),
ElevatedButton(
onPressed: _initialized ? () {
Workmanager().registerOneOffTask(
fileUploadKey,
fileUploadKey,
inputData: {
'fileName': 'photo.jpg',
'attempt': 1,
},
constraints: Constraints(
networkType: NetworkType.connected,
),
backoffPolicy: BackoffPolicy.exponential,
);
} : null,
child: Text('Schedule Upload Task'),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: _initialized ? () async {
await Workmanager().cancelAll();
print('All tasks cancelled');
} : null,
child: Text('Cancel All Tasks'),
),
],
),
),
);
}
}
```
--------------------------------
### Configure iOS Info.plist for Periodic Tasks with Frequency
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Enable 'processing' background mode and list permitted identifiers in Info.plist for custom frequency periodic tasks.
```xml
UIBackgroundModes
processing
BGTaskSchedulerPermittedIdentifiers
com.yourapp.periodic_task
```
--------------------------------
### Configure iOS BGTaskScheduler Processing
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Register processing tasks in Info.plist and the AppDelegate.
```xml
UIBackgroundModes
processing
BGTaskSchedulerPermittedIdentifiers
com.yourapp.processing_task
```
```swift
import workmanager_apple
// In application didFinishLaunching
WorkmanagerPlugin.registerBGProcessingTask(
withIdentifier: "com.yourapp.processing_task"
)
```
--------------------------------
### Run Flutter Tests
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Execute all Dart tests within the Flutter project. This is a mandatory pre-commit check.
```bash
flutter test
```
--------------------------------
### Migrate Debug Initialization
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/task-status.mdx
Updates initialization logic by removing the deprecated isInDebugMode parameter in favor of platform-specific debug handlers.
```dart
// ❌ Old approach (deprecated)
await Workmanager().initialize(
callbackDispatcher,
isInDebugMode: true, // Deprecated
);
// ✅ New approach
await Workmanager().initialize(callbackDispatcher);
// Set up platform-specific debug handler
// Android: WorkmanagerDebug.setCurrent(NotificationDebugHandler())
// iOS: WorkmanagerDebug.setCurrent(LoggingDebugHandler())
```
--------------------------------
### Initialize and Register Background Tasks in Dart
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/workmanager/README.md
Defines the callback dispatcher for background execution and initializes the Workmanager plugin in the main application entry point.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
print("Background task: $task");
// Your background work here
return Future.value(true);
});
}
void main() {
Workmanager().initialize(callbackDispatcher);
Workmanager().registerOneOffTask("task-id", "simpleTask");
runApp(MyApp());
}
```
--------------------------------
### Schedule and Handle Tasks with Input Data
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Pass JSON-serializable data to background tasks and extract it within the callback dispatcher.
```dart
// Schedule task with input data
Workmanager().registerOneOffTask(
"upload-task",
"file_upload",
inputData: {
'fileName': 'document.pdf',
'uploadUrl': 'https://api.example.com/upload',
'retryCount': 3,
'userId': 12345,
},
);
// Access input data in your task
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
print('Task: $task');
print('Input: $inputData');
// Extract specific values
String? fileName = inputData?['fileName'];
String? uploadUrl = inputData?['uploadUrl'];
int retryCount = inputData?['retryCount'] ?? 0;
int userId = inputData?['userId'] ?? 0;
// Use the data in your task logic
await uploadFile(fileName, uploadUrl, userId);
return Future.value(true);
});
}
```
--------------------------------
### Configure Android Notification Debugging
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/task-status.mdx
Set up `NotificationDebugHandler` with custom channel ID and group key for Android. Ensure the notification channel is created if using a custom ID.
```kotlin
// NotificationDebugHandler - shows status as notifications
WorkmanagerDebug.setCurrent(NotificationDebugHandler())
```
```kotlin
// Custom notification channel and grouping (you must create the channel first)
val channelId = "MyAppDebugChannel"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, "My App Debug", NotificationManager.IMPORTANCE_DEFAULT)
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(channel)
}
WorkmanagerDebug.setCurrent(NotificationDebugHandler(
channelId = channelId,
groupKey = "workmanager_debug_group"
))
```
```kotlin
// LoggingDebugHandler - writes to system log
WorkmanagerDebug.setCurrent(LoggingDebugHandler())
```
```kotlin
// Custom handler
class CustomDebugHandler : WorkmanagerDebug() {
override fun onTaskStatusUpdate(
context: Context,
taskInfo: TaskDebugInfo,
status: TaskStatus,
result: TaskResult?
) {
when (status) {
TaskStatus.SCHEDULED -> log("Task scheduled: ${taskInfo.taskName}")
TaskStatus.STARTED -> log("Task started: ${taskInfo.taskName}")
TaskStatus.RETRYING -> log("Task retrying (attempt ${taskInfo.runAttemptCount}): ${taskInfo.taskName}")
TaskStatus.RESCHEDULED -> log("Task rescheduled: ${taskInfo.taskName}")
TaskStatus.COMPLETED -> log("Task completed: ${taskInfo.taskName}")
TaskStatus.FAILED -> log("Task failed: ${taskInfo.taskName}, error: ${result?.error}")
TaskStatus.CANCELLED -> log("Task cancelled: ${taskInfo.taskName}")
}
}
}
```
--------------------------------
### Configure Android Debug Handlers
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Set up logging or notification handlers within the Android Application class to monitor background tasks.
```kotlin
// In your Application class
import dev.fluttercommunity.workmanager.WorkmanagerDebug
import dev.fluttercommunity.workmanager.LoggingDebugHandler
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
WorkmanagerDebug.setCurrent(LoggingDebugHandler())
}
}
```
```kotlin
import dev.fluttercommunity.workmanager.NotificationDebugHandler
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
WorkmanagerDebug.setCurrent(NotificationDebugHandler())
}
}
```
--------------------------------
### Configure iOS Info.plist for Processing Tasks
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Add 'processing' to UIBackgroundModes and specify permitted task identifiers in Info.plist for BGTaskScheduler.
```xml
UIBackgroundModes
processing
BGTaskSchedulerPermittedIdentifiers
com.yourapp.processing_task
```
--------------------------------
### Schedule One-time and Periodic Tasks
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Configure tasks with initial delays or recurring frequencies.
```dart
// One-time task with delay
Workmanager().registerOneOffTask(
"delayed-task",
"cleanup",
initialDelay: Duration(minutes: 30),
inputData: {'cleanupType': 'cache'}
);
// Periodic task with custom frequency
Workmanager().registerPeriodicTask(
"hourly-sync",
"data_sync",
frequency: Duration(hours: 1), // Android: minimum 15 minutes
initialDelay: Duration(minutes: 5), // Wait before first execution
inputData: {'syncType': 'incremental'}
);
```
--------------------------------
### Manage Resources in Background Isolates
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Initialize and clean up resources like `HttpClient` within the background task callback to ensure they are properly managed in the separate isolate.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
HttpClient? client;
try {
// Initialize resources in the background isolate
client = HttpClient();
// Perform task
await performNetworkOperation(client);
return Future.value(true);
} finally {
// Clean up resources
client?.close();
}
});
}
```
--------------------------------
### Schedule One-Time and Periodic Tasks
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Schedule tasks using `registerOneOffTask` for a single execution or `registerPeriodicTask` for recurring execution. Specify unique IDs, task names, and optional delays or frequencies.
```dart
// Schedule a one-time task
Workmanager().registerOneOffTask(
"sync-task",
"data_sync",
initialDelay: Duration(seconds: 10),
);
// Schedule a periodic task
Workmanager().registerPeriodicTask(
"cleanup-task",
"cleanup",
frequency: Duration(hours: 24),
);
```
--------------------------------
### Dart Code Formatting
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Format Dart files in the project, excluding generated files and hidden directories. This command ensures consistent code style.
```bash
find . -name "*.dart" ! -name "*.g.dart" ! -path "*/.*" -print0 | xargs -0 dart format --set-exit-if-changed
```
--------------------------------
### Define background task handler
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Registers the callback dispatcher to process scheduled tasks. Must be annotated with @pragma('vm:entry-point').
```dart
import 'package:workmanager/workmanager.dart';
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
final startTime = DateTime.now();
print('Task started: $task at $startTime');
print('Input data: $inputData');
try {
switch (task) {
case 'photo_upload':
final fileName = inputData?['fileName'] as String?;
final uploadUrl = inputData?['uploadUrl'] as String?;
await uploadPhoto(fileName!, uploadUrl!);
break;
case 'data_sync':
final syncType = inputData?['syncType'] ?? 'full';
await performDataSync(syncType);
break;
case 'cache_cleanup':
final maxAgeHours = inputData?['maxAgeHours'] ?? 24;
await cleanupCache(maxAgeHours);
break;
case Workmanager.iOSBackgroundTask:
// iOS Background Fetch - keep it quick (30 second limit)
await quickBackgroundRefresh();
break;
default:
print('Unknown task: $task');
return Future.value(false); // Return false for retry
}
final duration = DateTime.now().difference(startTime);
print('Task completed in ${duration.inSeconds}s');
return Future.value(true); // Success
} catch (e, stackTrace) {
print('Task failed: $e');
print('Stack trace: $stackTrace');
// Decide whether to retry based on error type
if (isRetryableError(e)) {
return Future.value(false); // Retry with backoff
} else {
throw Exception('Permanent failure: $e'); // Don't retry
}
}
});
}
bool isRetryableError(dynamic error) {
final errorString = error.toString().toLowerCase();
return errorString.contains('network') ||
errorString.contains('timeout') ||
errorString.contains('temporary');
}
```
--------------------------------
### Register One-Off Tasks
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Schedules a task to run once after an optional delay. Supports input data, constraints, and backoff policies.
```dart
import 'package:workmanager/workmanager.dart';
// Basic one-off task
Workmanager().registerOneOffTask(
"sync-task-1", // uniqueName - identifies the task
"data_sync", // taskName - passed to callback dispatcher
initialDelay: Duration(seconds: 10),
);
// One-off task with input data and constraints
Workmanager().registerOneOffTask(
"upload-task-${DateTime.now().millisecondsSinceEpoch}",
"file_upload",
inputData: {
'fileName': 'document.pdf',
'uploadUrl': 'https://api.example.com/upload',
'retryCount': 3,
'userId': 12345,
},
initialDelay: Duration(minutes: 5),
constraints: Constraints(
networkType: NetworkType.connected, // Require internet connection
requiresBatteryNotLow: true, // Don't run when battery is low
requiresCharging: false, // Can run when not charging
requiresDeviceIdle: false, // Can run when device is active
requiresStorageNotLow: true, // Don't run when storage is low
),
existingWorkPolicy: ExistingWorkPolicy.replace,
backoffPolicy: BackoffPolicy.exponential,
backoffPolicyDelay: Duration(seconds: 30),
tag: "uploads",
);
```
--------------------------------
### Run Dart Analyze
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Analyze Dart code for errors and potential issues. This is a mandatory pre-commit check.
```bash
dart analyze
```
--------------------------------
### Regenerate Pigeon API files
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CONTRIBUTING.md
Use this command after modifying the Pigeon API definition in the platform interface package.
```bash
# Regenerate Pigeon files
melos run generate:pigeon
```
--------------------------------
### Test Task Logic via UI
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Create a debug button in the UI to trigger and test background task logic manually.
```dart
// Add a debug button to test task logic
ElevatedButton(
onPressed: () async {
// Test the same logic that runs in background
final result = await performTask('test_task', {'debug': true});
print('Test result: $result');
},
child: Text('Test Task Logic'),
)
```
--------------------------------
### Implement Custom Debug Handlers
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Create custom handlers to manage task status updates and exceptions on Android and iOS.
```kotlin
class CustomDebugHandler : WorkmanagerDebug() {
override fun onTaskStatusUpdate(context: Context, taskInfo: TaskDebugInfo, status: TaskStatus, result: TaskResult?) {
// Custom status handling logic
// See Task Status documentation for detailed status information
}
override fun onExceptionEncountered(context: Context, taskInfo: TaskDebugInfo?, exception: Throwable) {
// Handle exceptions
}
}
WorkmanagerDebug.setCurrent(CustomDebugHandler())
```
```swift
class CustomDebugHandler: WorkmanagerDebug {
override fun onTaskStatusUpdate(taskInfo: TaskDebugInfo, status: TaskStatus, result: TaskResult?) {
// Custom status handling logic
// See Task Status documentation for detailed status information
}
override fun onExceptionEncountered(taskInfo: TaskDebugInfo?, exception: Error) {
// Handle exceptions
}
}
WorkmanagerDebug.setCurrent(CustomDebugHandler())
```
--------------------------------
### Implement iOS Background Task Logging
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Use this callback dispatcher to log task execution status and errors specifically for iOS background tasks.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
print('[iOS BG] Task started: $task at ${DateTime.now()}');
try {
// Your task logic
final result = await performTask();
print('[iOS BG] Task completed successfully');
return true;
} catch (e) {
print('[iOS BG] Task failed: $e');
return false;
}
});
}
```
--------------------------------
### Generate Pigeon Files
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Use Melos to regenerate Pigeon interface files. This is part of the code generation process.
```bash
melos run generate:pigeon
```
--------------------------------
### Advanced Task Identification and Routing
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Use unique naming conventions and switch logic within the callback dispatcher to handle different task types.
```dart
// Good: Specific and unique
Workmanager().registerOneOffTask(
"user-${userId}-photo-upload-${timestamp}",
"upload_task",
inputData: {'userId': userId, 'type': 'photo'}
);
// Avoid: Generic names that might conflict
Workmanager().registerOneOffTask(
"task1",
"upload",
// ...
);
```
```dart
// Use descriptive task type names in your callback
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
switch (task) {
case 'photo_upload':
return await handlePhotoUpload(inputData);
case 'data_sync':
return await handleDataSync(inputData);
case 'cache_cleanup':
return await handleCacheCleanup(inputData);
case 'notification_check':
return await handleNotificationCheck(inputData);
default:
print('Unknown task: $task');
return Future.value(false);
}
});
}
```
--------------------------------
### Workmanager.registerOneOffTask
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Schedules a one-time background task that executes once after an optional initial delay. The task can be configured with constraints, backoff policies, and input data.
```APIDOC
## Workmanager.registerOneOffTask
### Description
Schedules a one-time background task that executes once after an optional initial delay. The task can be configured with constraints, backoff policies, and input data.
### Method
`Workmanager().registerOneOffTask()`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None (parameters are passed directly to the method)
- **uniqueName** (String) - Required - A unique identifier for the task.
- **taskName** (String) - Required - The name of the task, passed to the callback dispatcher.
- **initialDelay** (Duration) - Optional - The delay before the task can start.
- **inputData** (Map) - Optional - Data to be passed to the task.
- **constraints** (Constraints) - Optional - Conditions that must be met for the task to run.
- **networkType** (NetworkType) - Optional - Network requirements (e.g., `NetworkType.connected`, `NetworkType.notRequired`).
- **requiresBatteryNotLow** (bool) - Optional - Whether the task requires the battery not to be low.
- **requiresCharging** (bool) - Optional - Whether the task requires the device to be charging.
- **requiresDeviceIdle** (bool) - Optional - Whether the task requires the device to be idle.
- **requiresStorageNotLow** (bool) - Optional - Whether the task requires storage not to be low.
- **existingWorkPolicy** (ExistingWorkPolicy) - Optional - Policy for handling existing tasks with the same name (e.g., `ExistingWorkPolicy.replace`).
- **backoffPolicy** (BackoffPolicy) - Optional - The backoff policy for retries (e.g., `BackoffPolicy.exponential`).
- **backoffPolicyDelay** (Duration) - Optional - The delay for the backoff policy.
- **tag** (String) - Optional - A tag to associate with the task.
### Request Example
```dart
Workmanager().registerOneOffTask(
"sync-task-1",
"data_sync",
initialDelay: Duration(seconds: 10),
);
Workmanager().registerOneOffTask(
"upload-task-${DateTime.now().millisecondsSinceEpoch}",
"file_upload",
inputData: {
'fileName': 'document.pdf',
'uploadUrl': 'https://api.example.com/upload',
'retryCount': 3,
'userId': 12345,
},
initialDelay: Duration(minutes: 5),
constraints: Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: true,
requiresCharging: false,
requiresDeviceIdle: false,
requiresStorageNotLow: true,
),
existingWorkPolicy: ExistingWorkPolicy.replace,
backoffPolicy: BackoffPolicy.exponential,
backoffPolicyDelay: Duration(seconds: 30),
tag: "uploads",
);
```
### Response
No specific response body is detailed for this method, as it primarily schedules tasks.
```
--------------------------------
### Define Background Task Handler
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
The `callbackDispatcher` must be a top-level function as it runs in a separate isolate. It handles different task types defined by strings.
```dart
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
switch (task) {
case "data_sync":
await syncDataWithServer();
break;
case "cleanup":
await cleanupOldFiles();
break;
case Workmanager.iOSBackgroundTask:
// iOS Background Fetch task
await handleBackgroundFetch();
break;
default:
// Handle unknown task types
break;
}
return Future.value(true);
});
}
```
--------------------------------
### Print scheduled tasks
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Outputs details of scheduled tasks for debugging. Only available on iOS 13+.
```dart
import 'package:workmanager/workmanager.dart';
// Print scheduled tasks for debugging (iOS only)
if (Platform.isIOS) {
final tasksInfo = await Workmanager().printScheduledTasks();
print('Scheduled tasks:\n$tasksInfo');
// Output example:
// [BGTaskScheduler] Task Identifier: com.yourapp.task earliestBeginDate: 2023.10.10 PM 11:10:12
// [BGTaskScheduler] There are no scheduled tasks
}
```
--------------------------------
### Design Efficient Background Tasks
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/customization.mdx
Ensure background tasks are quick and focused to avoid timeouts, especially on iOS where there's a 30-second limit.
```dart
// Good: Quick, focused tasks
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
// Fast operation
await syncCriticalData();
return Future.value(true);
});
}
```
```dart
// Avoid: Long-running operations
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
// This might timeout on iOS (30-second limit)
await processLargeDataset(); // ❌ Too slow
return Future.value(true);
});
}
```
--------------------------------
### Simulate BGTaskScheduler Task in Xcode
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Trigger a specific background task manually from the Xcode console while the app is running.
```objc
// Trigger specific BGTaskScheduler task
e -l objc -- (void)[[BGTaskScheduler sharedScheduler]
_simulateLaunchForTaskWithIdentifier:@"com.yourapp.task.identifier"]
```
--------------------------------
### Generate Dart Files
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/CLAUDE.md
Use Melos to regenerate Dart files, including mocks. Ensure mocks are up-to-date before running tests in the workmanager package.
```bash
melos run generate:dart
```
--------------------------------
### Monitor Scheduled Tasks on iOS
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/debugging.mdx
Retrieve and print a list of tasks currently scheduled by the system on iOS 13+.
```dart
// iOS 13+ only
if (Platform.isIOS) {
final tasks = await Workmanager().printScheduledTasks();
print('Scheduled tasks: $tasks');
}
```
--------------------------------
### Define Battery and Device Constraints
Source: https://context7.com/fluttercommunity/flutter_workmanager/llms.txt
Configure constraints related to battery and device status. 'requiresBatteryNotLow' ensures the task runs only when the battery is not low, and 'requiresCharging' requires the device to be charging.
```dart
import 'package:workmanager/workmanager.dart';
// Battery-conscious task
final batteryConstraints = Constraints(
requiresBatteryNotLow: true,
requiresCharging: false,
);
```
--------------------------------
### Register Periodic Task with Frequency in AppDelegate.swift
Source: https://github.com/fluttercommunity/flutter_workmanager/blob/main/docs/quickstart.mdx
Register a periodic task identifier in AppDelegate.swift, specifying the desired frequency in seconds.
```swift
import workmanager_apple
// In application didFinishLaunching
WorkmanagerPlugin.registerPeriodicTask(
withIdentifier: "com.yourapp.periodic_task",
frequency: NSNumber(value: 20 * 60) // 20 minutes (15 min minimum)
)
```