Search code examples
flutterdartbackground-service

Flutter background service: onStart method must be a top-level or static function


E/flutter (28533): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: onStart method must be a top-level or static function E/flutter (28533): #0 FlutterBackgroundServiceAndroid.configure (package:flutter_background_service_android/flutter_background_service_android.dart:60:7) E/flutter (28533): #1 FlutterBackgroundService.configure (package:flutter_background_service/flutter_background_service.dart:20:17) E/flutter (28533): #2 initializeService (package:park_space/tow_home/tow_home_screen.dart:68:17) E/flutter (28533): #3 _TowHomeScreenState.getData.. (package:park_space/tow_home/tow_home_screen.dart:126:15) E/flutter (28533):

Here's my code:

Future<void> initializeService() async {
  print('sulod');
  final service = FlutterBackgroundService();

  @pragma('vm:entry-point')
  void onStart(ServiceInstance serviceInstance) async {
    DartPluginRegistrant.ensureInitialized();
    if (serviceInstance is AndroidServiceInstance) {
      serviceInstance.on('setAsForeground').listen((event) {
        serviceInstance.setAsForegroundService();
      });

      serviceInstance.on('setAsBackground').listen((event) {
        serviceInstance.setAsBackgroundService();
      });
    }

    serviceInstance.on('stopService').listen((event) {
      serviceInstance.stopSelf();
    });

    if (serviceInstance is AndroidServiceInstance) {
      serviceInstance.setForegroundNotificationInfo(
        title: "Background Service",
        content: "Park Space background service.",
      );
    }
  }

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onStart,
      autoStart: true,
      isForegroundMode: true,
    ),
    iosConfiguration: IosConfiguration(
      autoStart: true,
      onForeground: onStart,
      onBackground: (ServiceInstance serviceInstance) {
        return true;
      },
    ),

  );
  

  service.startService();
}

I formatted the code like this because I want to pass a callBack function to initializeService function. But I'm getting this error. Is there a way to pass a callBack function into onStart from 'service.configure'? Any suggestions will greatly be appreciated, thank you.


Solution

  • When using plugins that require a callback to be registered for background execution, you must define the callback as a static method in one of the two ways:

    // Top-level static methods
    void onStart(ServiceInstance serviceInstance) {
      // Your code here
    }
    
    bool onBackground(ServiceInstance serviceInstance) {
      return true;
    }
    
    class Foo {
      // Static methods in a class
      static void onStart(ServiceInstance serviceInstance) {
        // Your code here
      }
    
      static bool onBackground(ServiceInstance serviceInstance) {
        return true;
      }
    }
    
    Future<void> initializeService() async {
      final service = FlutterBackgroundService();
      await service.configure(
        androidConfiguration: AndroidConfiguration(
          onStart: onStart,
          autoStart: true,
          isForegroundMode: true,
        ),
        iosConfiguration: IosConfiguration(
          autoStart: true,
          onForeground: onStart,
          onBackground: onBackground,
        ),
      );
      service.startService();
    }
    
    

    This is because the Flutter engine needs to be able to look up the callback by name, which isn't possible for callbacks associated with a specific instance of an object or non-static context (e.g., functions declared within other functions). I go into this in more detail in the Medium article on Flutter background execution, which I wrote when I implemented background execution support in Flutter a few years back.