In Flutter, background processing is crucial for executing tasks without interrupting the user interface (UI). The workmanager package is a popular choice for scheduling and managing background tasks efficiently. This article delves into how to effectively use the workmanager package in Flutter for background processing.
What is Background Processing in Flutter?
Background processing refers to running tasks outside the main thread, ensuring the UI remains responsive. Common use cases include:
- Syncing data
- Downloading files
- Processing images
- Performing scheduled updates
Why Use workmanager for Background Processing?
The workmanager package provides a robust and reliable way to handle background tasks because:
- It integrates with Android’s WorkManager and iOS’s BGTaskScheduler.
- It supports both one-off and periodic tasks.
- It handles device reboots and app restarts gracefully.
- It offers flexible constraints like network connectivity and device charging.
How to Implement Background Processing with workmanager in Flutter
To use the workmanager package, follow these steps:
Step 1: Add workmanager Dependency
Add the workmanager package to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
workmanager: ^0.5.1
Run flutter pub get to install the dependency.
Step 2: Configure the Native Platforms
For Android and iOS, additional configuration is required.
Android Configuration
- Update
AndroidManifest.xml:
Add the following to your android/app/src/main/AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="your_app_name"
android:icon="@mipmap/ic_launcher">
<!-- Add this receiver -->
<receiver
android:name="dev.fluttercommunity.workmanager.FlutterWorkerBootReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
- Update
build.gradle:
Ensure your android/build.gradle file has the necessary settings:
buildscript {
ext.kotlin_version = '1.7.1'
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
}
}
iOS Configuration
- Background Modes:
In Xcode, enable Background Modes for your project. Go to your target’s Signing & Capabilities tab, click + Capability, and add Background Modes. Check Background fetch and Background processing.

- Update
Info.plist:
Add the following key to your ios/Runner/Info.plist file:
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>your.app.identifier.task</string>
</array>
Replace your.app.identifier.task with a unique identifier for your background task.
Step 3: Initialize Workmanager
In your Flutter app, initialize the Workmanager in the main function before running the app:
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
Workmanager().initialize(
callbackDispatcher, // The top level function, aka callbackDispatcher
isInDebugMode: true, // If enabled it will post a notification whenever the work is running. Optional.
);
Workmanager().registerOneOffTask(
"task-identifier",
"simpleTask",
initialDelay: Duration(seconds: 5),
inputData: {'key': 'value'}); //android only
runApp(MyApp());
}
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
switch (task) {
case 'simpleTask':
print("[Flutter] Native platform is running task simpleTask");
// Do something (e.g. sync data, download files)
break;
}
return Future.value(true);
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Workmanager Example'),
),
body: Center(
child: Text('Running background task...'),
),
),
);
}
}
Step 4: Define the Callback Dispatcher
The callbackDispatcher function is crucial. It is a top-level function that WorkManager uses to find and execute tasks.
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
switch (task) {
case 'simpleTask':
print("[Flutter] Native platform is running task simpleTask");
// Do something (e.g. sync data, download files)
break;
}
return Future.value(true);
});
}
Step 5: Register a Task
You can register either a one-off task or a periodic task. Here’s how to register a one-off task:
Workmanager().registerOneOffTask(
"task-identifier",
"simpleTask",
initialDelay: Duration(seconds: 5),
inputData: {'key': 'value'} // Android-specific input data
);
For periodic tasks:
Workmanager().registerPeriodicTask(
"periodic-task-identifier",
"periodicTask",
initialDelay: Duration(minutes: 15), // First execution
frequency: Duration(hours: 1), // Recurring every hour
inputData: {'key': 'periodic value'} // Android-specific input data
);
Step 6: Handle Constraints (Optional)
You can add constraints to your tasks to specify when they should run. For example, run only when the device is connected to the internet:
Workmanager().registerOneOffTask(
"task-with-constraints",
"constrainedTask",
constraints: Constraints(
requiresNetworkType: NetworkType.connected,
requiresCharging: true,
)
);
Best Practices for Using workmanager
- Keep Tasks Short: Background tasks should be lightweight and complete quickly.
- Handle Errors: Implement robust error handling to manage failures gracefully.
- Battery Efficiency: Minimize the impact on battery life by avoiding unnecessary tasks.
- User Awareness: Provide feedback to the user about background activity.
Example Use Case: Periodic Data Sync
Consider an app that needs to periodically sync user data with a server.
void syncData() {
// Logic to sync data with the server
print('Syncing data in the background...');
}
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
switch (task) {
case 'syncTask':
syncData();
break;
}
return Future.value(true);
});
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
Workmanager().initialize(
callbackDispatcher,
isInDebugMode: true,
);
Workmanager().registerPeriodicTask(
"sync-data-task",
"syncTask",
frequency: Duration(hours: 6), // Sync every 6 hours
);
runApp(MyApp());
}
Conclusion
The workmanager package offers a reliable solution for managing background tasks in Flutter. By following the steps and best practices outlined in this article, you can efficiently schedule and execute tasks, ensuring your app remains responsive and effective.