flutterbackground-serviceonstart

Flutter : No top-level getter 'onStart' declared


I modified the sample code given in the flutter_background_service: ^2.4.5 package to get BuildContext. From then, I get this error saying

[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: NoSuchMethodError: No top-level getter 'onStart' declared.
E/flutter (26872): Receiver: top-level
E/flutter (26872): Tried calling: onStart
E/flutter (26872): #0      NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:216:5)
E/flutter (26872): #1      _getCallbackFromHandle (dart:ui/natives.dart:94:76)
E/flutter (26872): #2      PluginUtilities.getCallbackFromHandle.<anonymous closure> (dart:ui/plugins.dart:82:23)
E/flutter (26872): #3      _LinkedHashMapMixin.putIfAbsent (dart:collection-patch/compact_hash.dart:524:23)
E/flutter (26872): #4      PluginUtilities.getCallbackFromHandle (dart:ui/plugins.dart:81:27)
E/flutter (26872): #5      _entrypoint (package:flutter_background_service_android/flutter_background_service_android.dart:13:35)
E/flutter (26872): <asynchronous suspension>

I guess it is because I changed the structure of the onStart method? But I really need to get access to the BuildContext, so I don't know how to solve this error.

my code :

Future<void> initializeBackgroundService(BuildContext buildContext) async {
  final service = FlutterBackgroundService();
  **** I need this ****
  BuildContext context = buildContext;

  void onStart(ServiceInstance service) async {
    // Only available for flutter 3.0.0 and later
    DartPluginRegistrant.ensureInitialized();

    Box box = Hive.box("dataBox");

    await mqttInit();

    client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) async {
      final recMess = c![0].payload as MqttPublishMessage;
      final pt = utf8.decode(recMess.payload.message);

      print('Notification: topic is <${c[0].topic}>, payload is <$pt>');

      context.read<SubTopic>().newTopic(c[0].topic);
      context.read<SubMessage>().newMessage(pt, pt);

    if (service is AndroidServiceInstance) {
      service.setAutoStartOnBootMode(true);

      service.on('setAsForeground').listen((event) {
        service.setAsForegroundService();
        print("^^ set as foreground service");
      });

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

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

    if (service is AndroidServiceInstance) {
      service.setForegroundNotificationInfo(
        title: "Background Service",
        content: "Service On",
      );
    }
  }

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onStart,
      autoStart: true,
      isForegroundMode: true,
    ),
    iosConfiguration: IosConfiguration(
      autoStart: true,
      // this will be executed when app is in foreground in separated isolate
      onForeground: onStart,

      // you have to enable background fetch capability on xcode project
      onBackground: (ServiceInstance serviceInstance) {
        print('FLUTTER BACKGROUND FETCH');
        return true;
      },
    ),
  );
  service.startService();
}

I searched for other answers, and they said 'put handlers in global scope' but no explanation on how I can do that.. Any ideas on how to solve this?


Solution

  • I have had the same error while trying to use the app in release mode, but it works while using the app in debug mode. What happens when u make your onStart function global ?

    Another solution (the best one I think) is to add @pragma('vm:entry-point') above ur onStart function which gives :

    @pragma('vm:entry-point')
    void onStart(ServiceInstance service){
    ...
    } 
    

    It should normally resolve your problem.

    Let me know if it works :)