handleRequestAppExit method

  1. @override
Future<AppExitResponse> handleRequestAppExit()
override

Handles any requests for application exit that may be received on the SystemChannels.platform method channel.

By default, returns ui.AppExitResponse.exit.

Not all exits are cancelable, so not all exits will call this function. Do not rely on this function as a place to save critical data, because you will be disappointed. There are a number of ways that the application can exit without letting the application know first: power can be unplugged, the battery removed, the application can be killed in a task manager or command line, or the device could have a rapid unplanned disassembly (i.e. it could explode). In all of those cases (and probably others), no notification will be given to the application that it is about to exit.

This examples shows how an application can cancel (or not) OS requests for quitting an application. Currently this is only supported on macOS and Linux.
link

To create a local project with this code sample, run:
flutter create --sample=binding.ServicesBinding.handleRequestAppExit.1 mysample

import 'dart:ui';

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

/// Flutter code sample for [ServicesBinding.handleRequestAppExit].

void main() {
  runApp(const ApplicationExitExample());
}

class ApplicationExitExample extends StatelessWidget {
  const ApplicationExitExample({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(body: Body()),
    );
  }
}

class Body extends StatefulWidget {
  const Body({super.key});

  @override
  State<Body> createState() => _BodyState();
}

class _BodyState extends State<Body> with WidgetsBindingObserver {
  bool _shouldExit = false;
  String lastResponse = 'No exit requested yet';

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

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

  Future<void> _quit() async {
    final AppExitType exitType =
        _shouldExit ? AppExitType.required : AppExitType.cancelable;
    setState(() {
      lastResponse = 'App requesting ${exitType.name} exit';
    });
    await ServicesBinding.instance.exitApplication(exitType);
  }

  @override
  Future<AppExitResponse> didRequestAppExit() async {
    final AppExitResponse response =
        _shouldExit ? AppExitResponse.exit : AppExitResponse.cancel;
    setState(() {
      lastResponse = 'App responded ${response.name} to exit request';
    });
    return response;
  }

  void _radioChanged(bool? value) {
    value ??= true;
    if (_shouldExit == value) {
      return;
    }
    setState(() {
      _shouldExit = value!;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SizedBox(
        width: 300,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            RadioListTile<bool>(
              title: const Text('Do Not Allow Exit'),
              groupValue: _shouldExit,
              value: false,
              onChanged: _radioChanged,
            ),
            RadioListTile<bool>(
              title: const Text('Allow Exit'),
              groupValue: _shouldExit,
              value: true,
              onChanged: _radioChanged,
            ),
            const SizedBox(height: 30),
            ElevatedButton(
              onPressed: _quit,
              child: const Text('Quit'),
            ),
            const SizedBox(height: 30),
            Text(lastResponse),
          ],
        ),
      ),
    );
  }
}

See also:

Implementation

@override
Future<AppExitResponse> handleRequestAppExit() async {
  bool didCancel = false;
  for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.of(_observers)) {
    if ((await observer.didRequestAppExit()) == AppExitResponse.cancel) {
      didCancel = true;
      // Don't early return. For the case where someone is just using the
      // observer to know when exit happens, we want to call all the
      // observers, even if we already know we're going to cancel.
    }
  }
  return didCancel ? AppExitResponse.cancel : AppExitResponse.exit;
}