How to use Flutter Method Channel in background (app minimised/closed)

5,048

I am collecting information/discussion that redirects us to run flutter engine in background.

void callbackDispatcher() {
WidgetsFlutterBinding.ensureInitialized();
print("Our background job ran!");

}

void main() {

 static const MethodChannel _channel = const MethodChannel("channel-name");

 Future<void> initialize(final Function callbackDispatcher) async {

  final callback = PluginUtilities.getCallbackHandle(callbackDispatcher);

 await _channel.invokeMethod('initialize', callback.toRawHandle());
 }
}

As stated here How to run Flutter in the background?

When a background job is started by native the Flutter engine is not active. So we are unable to run Dart. Can Android/iOS starts the Flutter engine in the background? Yes! We’ll first need to register a Dart callback function which will only be invoked whenever a background job is started by the native code. This callback function is referred to as a callbackDispatcher.

Also please check out these stackoverflow discussions.

Flutter : Run an app as a background service

How to create a service in Flutter to make an app to run always in background?

How to create a Flutter background service that works also when app closed

Executing Dart in the Background with Flutter Plugins and Geofencing

Share:
5,048
Shahbaz Hashmi
Author by

Shahbaz Hashmi

Updated on December 23, 2022

Comments

  • Shahbaz Hashmi
    Shahbaz Hashmi over 1 year

    I am working on a native Android widget in a Flutter App. In which there is refresh button, on click of that I have to call a method in the Flutter code. I am using Flutter Method Channel for the communication and it is working fine when app is in foreground. But it does not work when app is minimised or closed. I get error PlatformException(NO_ACTIVITY, null, null). Below is my code.

    Android (AppWidgetProvider)

    if (methodChannel == null && context != null) {
            FlutterMain.startInitialization(context)
            FlutterMain.ensureInitializationComplete(context, arrayOf())
    
            // Instantiate a FlutterEngine.
            val engine = FlutterEngine(context.applicationContext)
    
            // Define a DartEntrypoint
            val entrypoint: DartEntrypoint = DartEntrypoint.createDefault()
    
            // Execute the DartEntrypoint within the FlutterEngine.
            engine.dartExecutor.executeDartEntrypoint(entrypoint)
    
            // Register Plugins when in background. When there
            // is already an engine running, this will be ignored (although there will be some
            // warnings in the log).
            //GeneratedPluginRegistrant.registerWith(engine)
    
            methodChannel = MethodChannel(engine.dartExecutor.binaryMessenger, MainActivity.CHANNEL)
    }
    
    methodChannel!!.invokeMethod("fetchNewData", "", object : MethodChannel.Result {
            override fun notImplemented() {
                Toast.makeText(context, "method not implemented", Toast.LENGTH_SHORT).show()
            }
    
            override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
                Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
            }
    
            override fun success(result: Any?) {
                Toast.makeText(context, "success", Toast.LENGTH_SHORT).show()
            }
    })
    

    Flutter

    /// calling in main
    static Future<void> attachListeners() async {
        WidgetsFlutterBinding.ensureInitialized();
        var bloc = new AqiCnDashboardBloc();
        _channel.setMethodCallHandler((call) {
          switch (call.method) {
            case 'fetchNewData':
              bloc.getAqiCn(false);
              return null;
            default:
              throw MissingPluginException('notImplemented');
          }
        });
    }
    
  • Shahbaz Hashmi
    Shahbaz Hashmi over 3 years
    I have already gone through these articles. Can you post the code ?