flutter_background_service icon indicating copy to clipboard operation
flutter_background_service copied to clipboard

callback handle not found

Open amazement1 opened this issue 2 years ago • 7 comments

I just installed the plugin and exactly same problem like many other ppl

flutter --version

Flutter 3.0.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision fb57da5f94 (3 weeks ago) • 2022-05-19 15:50:29 -0700
Engine • revision caaafc5604
Tools • Dart 2.17.1 • DevTools 2.12.2

code are from sample

  Future<void> initializeService() async {
    backgroundServer = FlutterBackgroundService();
    await backgroundServer.configure(
      androidConfiguration: AndroidConfiguration(
        // this will executed when app is in foreground or background in separated isolate
        onStart: onStart,

        // auto start backgroundServer
        autoStart: true,
        isForegroundMode: true,
      ),
      iosConfiguration: IosConfiguration(
        // auto start backgroundServer
        autoStart: true,

        // this will executed when app is in foreground in separated isolate
        onForeground: onStart,

        // you have to enable background fetch capability on xcode project
        onBackground: onIosBackground,
      ),
    );
  }

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

    // For flutter prior to version 3.0.0
    // We have to register the plugin manually

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

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

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

    Timer.periodic(const Duration(seconds: 3), (timer) async {
      // bring to foreground
      if (service is AndroidServiceInstance) {
        service.setForegroundNotificationInfo(
          title: "My App Service",
          content: "Updated at ${DateTime.now()}",
        );
      }

      /// you can see this log in logcat
      print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');

      service.invoke(
        'update',
        {
          "current_date": DateTime.now().toIso8601String(),
        },
      );
    });
  }

logs in debug panel in VScode

E/BackgroundService(15312): callback handle not found
D/BackgroundService(15312): runService
E/BackgroundService(15312): callback handle not found
D/BackgroundService(15312): runService
E/BackgroundService(15312): callback handle not found
D/BackgroundService(15312): runService
E/BackgroundService(15312): callback handle not found
D/BackgroundService(15312): runService
E/BackgroundService(15312): callback handle not found```

amazement1 avatar Jun 07 '22 03:06 amazement1

@amazement1 you have to call initializeService() on main() method, so your application will update the callback handle when the app launch immediately.

ekasetiawans avatar Jun 07 '22 10:06 ekasetiawans

I'm having the same problem, I left my code the same as the example and the app keeps spitting this message infinitely

Flutter 3.0.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision fb57da5f94 (3 weeks ago) • 2022-05-19 15:50:29 -0700
Engine • revision caaafc5604
Tools • Dart 2.17.1 • DevTools 2.12.2
D/BackgroundService( 8823): runService
E/BackgroundService( 8823): callback handle not found
D/BackgroundService( 8823): runService
E/BackgroundService( 8823): callback handle not found
D/BackgroundService( 8823): runService
E/BackgroundService( 8823): callback handle not found
D/BackgroundService( 8823): runService
E/BackgroundService( 8823): callback handle not found
D/BackgroundService( 8823): runService
E/BackgroundService( 8823): callback handle not found
import 'dart:async';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:flutter_background_service_android/flutter_background_service_android.dart';

///
///
///
class BackgroundService {
  ///
  ///
  ///
  Future<void> initializeService() async {
    FlutterBackgroundService service = FlutterBackgroundService();
    await service.configure(
      androidConfiguration: AndroidConfiguration(
        // this will be executed when app is in foreground or background in separated isolate
        onStart: onStart,
        isForegroundMode: true,
      ),
      iosConfiguration: IosConfiguration(
        // 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: onIosBackground,
      ),
    );
    await service.startService();
  }

  // to ensure this is executed
  // run app from xcode, then from xcode menu, select Simulate Background Fetch
  bool onIosBackground(ServiceInstance service) {
    WidgetsFlutterBinding.ensureInitialized();
    print('FLUTTER BACKGROUND FETCH');

    return true;
  }

  ///
  ///
  ///
  Future<void> onStart(ServiceInstance service) async {
    print('onStart is running');
    // Only available for flutter 3.0.0 and later
    DartPluginRegistrant.ensureInitialized();

    // For flutter prior to version 3.0.0
    // We have to register the plugin manually

    if (service is AndroidServiceInstance) {
      service.on('setAsForeground').listen((Map<String, dynamic>? event) {
        service.setAsForegroundService();
      });

      service.on('setAsBackground').listen((Map<String, dynamic>? event) {
        service.setAsBackgroundService();
      });
    }

    service.on('stopService').listen((Map<String, dynamic>? event) {
      service.stopSelf();
    });

    // bring to foreground
    Timer.periodic(const Duration(seconds: 1), (Timer timer) async {
      if (service is AndroidServiceInstance) {
        await service.setForegroundNotificationInfo(
          title: 'My App Service',
          content: 'Updated at ${DateTime.now()}',
        );
      }

      /// you can see this log in logcat
      print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
    });
  }
}

///
///
///
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await BackgroundService().initializeService();
  runApp(const AppChamados());
}

Alvarocda avatar Jun 08 '22 21:06 Alvarocda

Well, a few minutes after posting that I was also having this problem, I ended up solving it.

I had created a specific class for the Background service but it didn't work. I put everything inside main.dart and it worked.

Alvarocda avatar Jun 08 '22 21:06 Alvarocda

@Alvarocda the 'onStart' method cannot be member of class. So, its must be a top level method.

ekasetiawans avatar Jun 08 '22 21:06 ekasetiawans

Just so everyone is aware, you could make it a member of the class, but it needs to be static.

Goddard avatar Jun 20 '22 15:06 Goddard

Hi all,

If you want to pass the dynamic data'in the background service or you want to run some dart function from other class, you have to mention that function in main dart file.

Without using context you can call the function by using Get it package from pub.dev https://pub.dev/packages/get_it version : 7.2.0 https://pub.dev/packages/flutter_background_service version : 2.1.3

Example Program

main.dart (Main File)

Future main() async { WidgetsFlutterBinding.ensureInitialized(); // The below one from getit.dart file await di.init(); await initializeService(); runApp(const MyApp()); }

Future initializeService() async { FlutterBackgroundService service = FlutterBackgroundService(); await service.configure( androidConfiguration: AndroidConfiguration( // this will be executed when app is in foreground or background in separated isolate onStart: onStart, isForegroundMode: true, ), iosConfiguration: IosConfiguration( // 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: onIosBackground,
  ),
);
await service.startService();

}

// to ensure this is executed // run app from xcode, then from xcode menu, select Simulate Background Fetch bool onIosBackground(ServiceInstance service) { WidgetsFlutterBinding.ensureInitialized(); print('FLUTTER BACKGROUND FETCH');

return true;

}

/// /// /// Future onStart(ServiceInstance service) async { print('onStart is running'); // Only available for flutter 3.0.0 and later DartPluginRegistrant.ensureInitialized();

// For flutter prior to version 3.0.0
// We have to register the plugin manually

if (service is AndroidServiceInstance) {
  service.on('setAsForeground').listen((Map<String, dynamic>? event) {
    service.setAsForegroundService();
  });

  service.on('setAsBackground').listen((Map<String, dynamic>? event) {
    service.setAsBackgroundService();
  });
}

service.on('stopService').listen((Map<String, dynamic>? event) {
  service.stopSelf();
});

// created one function for getting location from background even the app is closed service.on('locationService').listen((Map<String, dynamic>? event) { // The below three lines from other class, where the Get it class are created. final loc = di.init(); // The function will call authprovider class without context, when you call the service.invoke('locationservice') from //other class final loca = di.sl<AuthProvider>(); loca.location(); }); }

getitfile.dart (Another file) // In this file you have create an instance for that and you have to call that instance in main.dart file in void main // function

final GetIt sl = GetIt.instance;

Future init() async { sl.registerFactory(() => AuthProvider()); // you have register the class whatever you want. }

authProvider.dart (AuthProvider)

Future location() async { final position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high, ); // whatever you want to run in this function , you can done here. // You can use http request also in this method. }

I have provided my solution as my best.

Jai2796 avatar Jun 22 '22 09:06 Jai2796

@Jai2796 you can't do that, because onStart method will be executed by separated Dart Isolate which doesn't share memory with main Isolate that execute main method. In the other words, you can't using same object reference in main method and onStart method.

ekasetiawans avatar Jun 23 '22 02:06 ekasetiawans

Started from version 2.2.0 we don't using callback handle for entrypoint anymore, but use a static entrypoint that provided by the plugin. But, you still need to call configure() method, everytime you have changes your dart code in your project to make the Callback Handle (to your onStart method) updated.

ekasetiawans avatar Sep 13 '22 18:09 ekasetiawans