Flutter

We have done an initial investigation into how background syncing could be accomplished by using Flutter with workmanager. However, the flow for other frameworks (e.g. React Native) should be quite similar using an equivalent package. Please reach out on our Discord for more assistance.

Guide

We assume you have followed the platform setup guide in the workmanager README. Note we are running this in the context of our Supabase Todo List Demo app.

In main.dart:

void main() async {
 ...
  const simpleTaskKey = "com.domain.myapp.taskId";
  // Mandatory if the App is obfuscated or using Flutter 3.1+
  ('vm:entry-point')
  void callbackDispatcher() {
    Workmanager().executeTask((task, inputData) async {
      switch (task) {
        case simpleTaskKey:
          final currentConnector = await openDatabase();
          db.connect(connector: currentConnector!);
          await TodoList.create('testing1234');
          await currentConnector.uploadData(db);
          await TodoList.create('testing1111');
          await currentConnector.uploadData(db);
          // print("$simpleTaskKey was executed. inputData = $inputData");
          break;
      }
      await db.close();
      return Future.value(true);
    });
  }

  Workmanager().initialize(
    callbackDispatcher,
    // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
    isInDebugMode: true
  );

  ...
}

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);
  1. 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.
  2. Run a write (in the case of this demo app, we create a ‘todo list’)
  3. Make sure to run currentConnector.uploadData(db); so that the local write is uploaded to the remote database.

Create a way to test this, e.g. by using a 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,
      },
    );
  },
),

Put your app in the background and wait 10 seconds, then check your remote database and it should have the new record.

Android

This worked with Android.

iOS

At the time of writing (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.