Education

How to Schedule Android Background Services in Flutter App?

logo

DhiWise

June 25, 2022
image
Author
logo

DhiWise

{
June 25, 2022
}

In every Android or iOS application, there are a few important processes that keep running in the background without asking the user to open the application. Some examples of such services that can be executed from the background while the app remains closed are:

  • Calling the APIs to get data every 15 minutes.
  • Compacting the storage
  • Getting notifications for emails, news, and other things
  • Playing music

Well, in the context of Flutter, until now the application can only handle the background events using the platform code. Any plugins had no way to allow users to make a callback for handling the background events in Dart. 

That is the reason why Flutter users need to create platform-specific implementations for handling background events in the application.

So, how will you schedule an application task/service when the user isn’t focused on it, especially when the Android 8.0 (API Level 26) imposes some restrictions on what app could be run in the background.

However, recently Flutter started supporting the background execution of Dart code. Let’s explore more about the android background services and available options in Flutter that can help Android developers manage Flutter background services. 

But before going deep into the details of Android background services first, understand some basics of the background services in Android.

What are Android background services?

An app or a service is said to be running in the background if it satisfies the following conditions:

  1. App activities are not visible to users.
  2. The App isn’t running any foreground services initiated during app activity visible to the user. 

The background services fall into three categories:

  • Immediate: These need to be executed instantly and get completed very soon. 
  • Long-Running: It may take some time to complete.
  • Deferrable: doesn’t need to be run instantly.

All these background services can be persistent or impersistant:

  • Persistent: It remains scheduled through the app restart and when the device is rebooted.
  • Impersistant: No longer scheduled once the process ends.

The following table will help you to decide on the approach you should take for each kind of background service.

Image

Ways for scheduling Flutter background services in the app

For scheduling the background events Android and iOS follow very different approaches. With Android, there are various ways to schedule the Background services, few of the popular ways are,

  • Geofencing
  • Alarm Manager
  • JobService Class
  • Firebase JobDispatcher
  • Work Manager

In the case of iOS applications, the number of available options is much more limited. Its system decides when to allow an app to perform background fetch so that the application seems to remain alive. Also, it may decide to never start an app for performing background fetch. 

Now let’s look into each approach in detail.

1. Geofencing

Geofencing is nothing but using a virtual geographical boundary around the physical location. It enables users to detect when someone enters or leaves the location. It helps trigger events and notifications in real-time. 

To implement Geofencing in the Flutter application use flutter_geofence, a plugin for all your geofence interactions. It is compatible with both Android and iOS platforms.

Installation:

Run the following command

flutter pub add flutter_geofence

This will add the following dependencies to your pubspec.yaml file.

dependencies:
  flutter_geofence: ^0.4.4

Importing to dart code.

import 'package:flutter_geofence/Geolocation.dart';
import 'package:flutter_geofence/geofence.dart';

Example: Using Geofence to get current location

The following command provides you Future that resolves with the current Coordinate of the user. If there is one that's recent enough (< 60 seconds old), it'll return to this location.

Geofence.getCurrentLocation().then((coordinate) {
    print("Your latitude is ${coordinate.latitude} and longitude ${coordinate.longitude}");
});

2. Alarm Manager

Alarms are a special use case that does not come under the background work. Alarm managers are used to scheduling the exact alarm such as alarm clocks or calendar events. 

When used to schedule background work it wakes the device from Dzone mode and thus may have a negative impact on the battery life and overall system health. 

A Flutter plugin android_alarm_manager_plus is used for accessing the Android Alarm Mangerservicesand running Dart code in the background when the Alarm is fired.

Installation:

Run the following command

flutter pub add android_alarm_manager_plus

This will add the following dependencies to your pubspec.yaml file.

dependencies:
  android_alarm_manager_plus: ^2.0.6

Importing to the Dart code.

import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';

Example:

Here printHello will then run after every minute, even if the main app ends. However, it will not run in the same isolate as the main application. Because it doesn't share memory and communication between isolates must be done via message passing.

import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';

static void printHello() {
  final DateTime now = DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
}

main() async {
  // Be sure to add this line if initialize() call happens before runApp()
  WidgetsFlutterBinding.ensureInitialized();

  await AndroidAlarmManager.initialize();
  runApp(...);
  final int helloAlarmID = 0;
  await AndroidAlarmManager.periodic(const Duration(minutes: 1), helloAlarmID, printHello);
}

3. JobService Class

If you want to schedule a service it should be defined in the Job Service. The service is invoked for the tasks that are scheduled to be run depending on the system condition. 

It enables the system to perform your work regardless of if your app is active or idle. Also, you can write multiple Job services, where each one defines a different task, this helps you to modularise your code. 

For scheduling any Job Service you shall need to add this to the one of your AndoridManifest.xml.


It adds permission that will allow the Job Scheduler to call your jobs and be the only one that accesses your JobService.

4. Firebase JobDispatcher

The Firebase JobDispacher is the Library for scheduling background jobs in the Android app. It provides a JobShedular-Compatible  API that works on all the latest versions of Android (API level 9+) that have Google Play services installed. 

However, with the introduction of the Android Jetpack WorkManager, the developer team decided to deprecate the Firebase JobDispacher and focus completely on the WorkManager. The new Work Manager works with or without the Google Play Services, which FJD cannot do.

Work Manager - A new job management system in the Jetpack that incorporates the features of both Firebase JobDispacher and JobScheduler to provide consistent job scheduling services back to API level 14 and leverages the JobScheduler on the new devices.

5. Work Manager

Android WorkManger is a background processing library that is used to schedule and run background tasks, in a guaranteed way but not necessarily immediately. With it, the user can enqueue background processing even when the app is not running and the device is rebooted. 

A Flutter work Manager plugin is a wrapper around the Android’s WorkManger, iOS’ performFetchWithCompletionHandler, and iOS BGAppRefreshTask, effectively enabling headless execution of the Dart code in the background.

Installation

Run the command given below.

flutter pub add workmanager

This will add the following line to your pubspec.yaml file.

dependencies:
  workmanager: ^0.5.0

To import the plugin in the main.dart file adds the line below.

import 'package:workmanager/workmanager.dart';
Example:

The work manager must be initialized before registering any task.

void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) {
    print("Native called background task: $backgroundTask"); //simpleTask will be emitted here.
    return Future.value(true);
  });
}

void main() {
  Workmanager().initialize(
    callbackDispatcher, // The top level function, aka callbackDispatcher
    isInDebugMode: true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
  );
  Workmanager().registerOneOffTask("task-identifier", "simpleTask");
  runApp(MyApp());
}

Here the callbackDispacher needs to be either a static function or a top-level function that can be accessible as a Flutter entry point.

Summing Up:

In the post, you have learned about the Android background services and the effective ways to manage them in the Flutter applications. 

If you are developing an Android or iOS app with Flutter try using DhiWise to speed up the app development process. The LowCode/ ProCode platform aims to reduce repetitive tasks in application development without compromising the code quality. 

It is a multi-technology platform that supports various technologies and frameworks so that developers can build any application with the tech stack they love.

Try using DhiWise Flutter app builder to improve your team productivity. Sign up Now!