stop flutter_background_service when app is killed flutter

125 Views Asked by At

How can I stop the flutter_background_service when the app is killed by the user?

final _androidConfiguration = AndroidConfiguration(
   onStart: _onStart,
   autoStart: true,
   isForegroundMode: true,
   initialNotificationTitle: 'App is running',
   initialNotificationContent: '');
final _iosConfiguration = IosConfiguration(
   autoStart: true,
   onForeground: _onStart,
);

_onStart is just a test for now.

@pragma('vm:entry-point')
void _onStart(ServiceInstance service) async {
  DartPluginRegistrant.ensureInitialized();

  if (service is AndroidServiceInstance) {
    service.on(BackGroundServiceOperations.setAsForeground).listen((event) {
    service.setAsForegroundService();
  });

  service.on(BackGroundServiceOperations.setAsBackground).listen((event) {
  service.setAsBackgroundService();
 });
}

 service.on(BackGroundServiceOperations.stopService).listen((event) {
 service.stopSelf();
});

  Timer.periodic(const Duration(seconds: 5), (timer) {
    debugPrint("background service is running!");
 });
}

I still get the background service is running! print when I kill the app. If the app is closed normally (user confirm via the alert dialog that their want to close the app) I call

final service = FlutterBackgroundService();
var isRunning = await service.isRunning();
if (isRunning) {
  service.invoke(BackGroundServiceOperations.stopService);
}

and the background service stops, as wanted.

1

There are 1 best solutions below

6
Dhafin Rayhan On

In your top widget, make it a StatefulWidget and add WidgetsBindingObserver:

class App extends StatefulWidget {
  const App({Key? key}) : super(key: key);

  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> with WidgetsBindingObserver { // (1) Use this mixin
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this); // (2) Add this line
  }

  // (3) Add this overriding method
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.detached) {
      // (4) Add one of the methods to stop background service; see below
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this); // (5) Add this line
    super.dispose();
  }

  // ...
}

Now, there are options to stop the background service:

  • backgroundService.invoke('stopService'), with backgroundService being an instance of FlutterBackgroundService and stopService is a method that calls service.stopSelf(); inside the entry onStart callback *)
  • exit(0) (may be dangerous: see reasons from the answers of this post)
  • Other methods that can kill isolates or stop the service

While using exit(0) can be dangerous and not a good practice to have, I found out (in my case) that this is the only method that works.

Also it might be a good idea to implement a logic that checks if the app is actually detached as a result of a normal exit (in your case, when the user confirms via alert dialog), so that this method is only called when really necessary.


*) Example implementation:

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  service.on('stopService').listen((event) {
    service.stopSelf();
  });

  // ...
}

See also: