Search code examples
androidflutterflutter-method-channelflutter-workmanager

How to invoke method channel from Workmanager task


I have a method channel registered in the Android build's MainActivity class, which works fine when called from the foreground application.

I want to call this method channel from a task that Workmanager runs in the background, but I'm getting a MissingPluginException every time.

I'm guessing this doesn't work because a background task doesn't initialise the MainActivity, but I can't seem to find any information on how to register the channels in a place where the workmanager can call them.

My (simplified) setup is as follows: lib/main.dart:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
  Workmanager().registerPeriodicTask('uniquename', 'taskName',
    frequency: const Duration(minutes: 15),
    constraints: Constraints(networkType: NetworkType.connected));

  runApp(const MyApp());
}

void callbackDispatcher() {
  Workmanager().executeTask((taskName, inputData) async {
    bool result = await DeviceInfoModel().getDeviceInfo();
    return Future.value(result);
  });
}

lib/device_info.dart:

class DeviceInfoModel extends ChangeNotifier {
  static const platform = MethodChannel('deviceInfo');

  Future<void> getDeviceInfo() async {
    final int result = await platform.invokeMethod('getBatteryLevel');
    // And other similar calls to other methods
  }
}

android/app/src/main/kotlin/nl/myapp/MainActivity.kt:

package nl.myapp

class MainActivity : FlutterActivity() {
  private val DEVICE_INFO_CHANNEL = "deviceInfo"

  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)

    methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, DEVICE_INFO_CHANNEL)

    methodChannel?.setMethodCallHandler { call, result ->
      if (call.method == "getBatteryLevel") {
        result.success(100)
      }
    }
  }
}

Solution

  • It seems like this is not possible.

    The invokeMethod function is annotated with @UiThread, so it cannot be called from a worker thread at all.