Applications often need to sync data when they’re not in active use. This document explains background syncing implementations with PowerSync.
Background syncing has been tested in:
These examples can be adapted for other frameworks like React Native. For implementation questions or assistance, chat to us on Discord.
Flutter Implementation Guide
Prerequisites
- Complete the workmanager platform setup
- Review the Supabase To-Do List Demo for context
In main.dart
:
void main() async {
// ... existing setup code ...
const simpleTaskKey = "com.domain.myapp.taskId";
// Mandatory if the App is obfuscated or using Flutter 3.1+
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
switch (task) {
case simpleTaskKey:
// Initialize PowerSync database and connection
final currentConnector = await openDatabase();
db.connect(connector: currentConnector!);
// Perform database operations
await TodoList.create('New background task item');
await currentConnector.uploadData(db);
await TodoList.create('testing1111');
await currentConnector.uploadData(db);
// print("$simpleTaskKey was executed. inputData = $inputData");
break;
}
// Close database when done
await db.close();
return Future.value(true);
});
}
// Initialize the workmanager with your callback
Workmanager().initialize(
callbackDispatcher,
// Shows notifications during task execution (useful for debugging)
isInDebugMode: true
);
// ... rest of your app initialization ...
}
Note specifically in the switch statement:
// currentConnector is the connector to the remote DB
// openDatabase sets the db variable to the PowerSync database
final currentConnector = await openDatabase();
// connect PowerSync to the remote database
db.connect(connector: currentConnector!);
// a database write operation
await TodoList.create('Buy new shoes');
// Sync with the remote database
await currentConnector.uploadData(db);
- Since WorkManager executes in a new process, you need to set up the PowerSync local database and connect to the remote database using your connector.
- Run a write (in the case of this demo app, we create a ‘todo list’)
- Make sure to run
currentConnector.uploadData(db);
so that the local write is uploaded to the remote database.
Testing
Add a test button:
ElevatedButton(
title: const Text("Start the Flutter background service"),
onTap: () async {
await Workmanager().cancelAll();
// print("RUN BACKGROUND TASK");
await Workmanager().registerOneOffTask(
simpleTaskKey,
simpleTaskKey,
initialDelay: Duration(seconds: 10),
inputData: <String, dynamic>{
int': 1,
},
);
},
),
Press the button, background the app, wait 10 seconds, then verify new records in the remote database.
Android
- Implementation works as expected.
iOS
- At the time of last testing this (January 2024), we were only able to get part of this to work using the branch for this PR into workmanager.
- While testing we were not able to get iOS background fetching to work, however this is most likely an
issue with the package.