Flutter check if the application is on the background

Flutter Jul 27, 2023

In Flutter, determining whether the application is currently in the foreground or background is an essential aspect of managing the application's lifecycle. Being able to detect these states allows you to implement specific actions and behaviors when the application is actively being used by the user (in the foreground) or when it is not visible or not receiving user input (in the background). In this post, we will go over two approaches to check whether the application is in the foreground or background.

WidgetsBindingObserver

The first approach uses the WidgetsBindingObserver class to observe changes in the application's lifecycle. The AppLifecycleState enum is used to determine the current state of the application. The BackgroundDetector class is implemented to handle lifecycle changes and print a message when the app goes to the foreground or background.

widgets_binding_observer.dart

import 'package:flutter/material.dart';

class BackgroundDetector extends StatefulWidget {
  BackgroundDetector({required this.child});

  final Widget child;

  @override
  _BackgroundDetectorState createState() => _BackgroundDetectorState();
}

class _BackgroundDetectorState extends State<BackgroundDetector> with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      print("Application is in the foreground");
    } else if (state == AppLifecycleState.paused) {
      print("Application is in the background");
    }
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

In this code snippet, we create a BackgroundDetector widget, which helps detect changes in the application's lifecycle and identifies if the application is currently in the foreground or background.

The BackgroundDetector widget is stateful and requires a child widget to be provided. The child widget is the content that will be monitored for foreground and background events.

The widget extends WidgetsBindingObserver to listen to changes in the application's lifecycle. When inserted into the widget tree, the widget's initState() method adds itself as an observer to receive notifications about lifecycle changes.

Similarly, when removed from the widget tree, the dispose() method removes the observer to avoid memory leaks.

The didChangeAppLifecycleState() method is called whenever the application's lifecycle state changes. It uses the AppLifecycleState enum to determine the current state and prints a message indicating if the app is in the foreground or background.

main.dart

import 'package:codeonwards_demo/widgets_binding_observer.dart';
import 'package:flutter/material.dart';

void main() => runApp(BackgroundDetector(child: MyApp()));

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Application in background observer'),
        ),
      ),
    );
  }
}

In the main.dart file, we wrap the BackgroundDetector widget around our MyApp widget. This makes sure that the BackgroundDetector widget observes the whole application. So, when we close the application, the BackgroundDetector will notice that the application goes into the background.

In the GIF below, you can see this behavior in action. If you take a look at the command line interface, you will notice the state updates being printed, indicating when the application moves between the foreground and background.

flutter_opening_and_closing_application_and_observing_using_widgets_binding_observer
For demonstration purposes, I used the logger package to highlight the output in the command line interface. However, I excluded the logger setup from the code snippets to keep the focus on the essential code needed to achieve the functionality.

AppLifecycleState

So far, we have used two of the four entries from the AppLifecycleState enum, which represents the different states in which an application can exist. Here is a list explaining each state:

  1. resumed: The application is in the foreground and is visible to the user. It is the active state where the user can interact with the app.
  2. inactive: The application is in an inactive state. It occurs when the application is partially obscured by another app or when a phone call comes in. In this state, the app may still be visible but is not receiving user input.
  3. paused: The application is in the background. The app is not visible to the user, and it is not executing any code. It can occur when the user switches to another app or when the device goes into sleep mode.
  4. detached: The app is running without a visible screen at that specific moment. It is either in the process of showing something for the first time or after temporarily hiding a screen and just before it becomes visible again.

By using WidgetsBindingObserver class and the AppLifecycleState enum, you can easily keep track of the application's lifecycle state. However, there is an alternative approach you can take to observe the lifecycle state of the application using the flutter_fgbg package.

Flutter Foreground/Background Event Notifier

The second approach makes use of the flutter_fgbg package to achieve similar functionality. While the WidgetsBindingObserver lets you know when your application becomes active or inactive, it also considers changes in other parts of the application, which can lead to incorrect observations.

The flutter_fgbg package only focuses on your application and observes accurately when it goes to the background or foreground. It does this differently for iOS and Android to make sure the observations are correct.

Installing

To get started with the implementation, we need to install the flutter_fgbg package into our project. The installation process is simple. Just execute the following command: flutter pub add flutter_fgbg.

Once the command is executed, make sure to check your pubspec.yaml file for the added dependencies. You should see the flutter_fgbg package included in the dependencies section, like this:

dependencies:
  flutter:
    sdk: flutter
  flutter_fgbg: ^0.3.0

Implementation

The flutter_fgbg package provides a FGBGNotifier widget, which is used to listen to foreground/background events. When the application lifecycle state changes, the onEvent callback is triggered, allowing us to perform specific actions based on the application's current state.

import 'package:flutter/material.dart';
import 'package:flutter_fgbg/flutter_fgbg.dart';

void main() => runApp(
      FGBGNotifier(
        onEvent: (FGBGType type) {
          if (type == FGBGType.foreground) {
            print("Application is in the foreground using FGBGNotifier");
          } else {
            print("Application is in the background using FGBGNotifier");
          }
        },
        child: MyApp(),
      ),
    );

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Application in background observer'),
        ),
      ),
    );
  }
}

In the updated main.dart file, we implemented the FGBGNotifier widget to achieve similar functionality. This widget requires an onEvent property, which takes a callback function receiving a FGBGType, representing either FGBGType.foreground or FGBGType.background.

Inside the callback, we use a simple if statement to print different messages based on the received type. Additionally, the FGBGNotifier widget takes a child, and in this case, we set our MyApp widget as the child.

Running the application will show that we get the same behavior as the previous approach. However, this package simplifies the implementation, making it easier to achieve the same functionality.

flutter_opening_and_closing_application_and_observing_using_flutter_fgbg_package

Conclusion

Both approaches successfully detect if the application is in the foreground or background. The first approach uses WidgetsBindingObserver and AppLifecycleState to monitor the application's behavior. It is also worth noting that the AppLifecycleState has two additional states that can be useful for specific application functionalities.

On the other hand, the second approach is simpler and utilizes the flutter_fgbg package, offering the FGBGNotifier widget for tracking foreground and background events.

To make the right choice, consider these options and carefully evaluate your application's requirements before selecting the best approach.

Tags