3

I have created a custom MethodChannel "com.example.app/widget" that updates a home screen widget on Android after receiving a Firebase Cloud Message. It runs fine when it is called while the app is in the foreground, but I would also like to call it when a Firebase Cloud Message is received while the app is closed or in the background.

When the app is in the background, it gives me a MissingPluginException error, like below:

E/flutter (28540): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: MissingPluginException(No implementation found for method updateFromFlutter on channel com.example.app/widget)
E/flutter (28540): #0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:157:7)

... and so on. There are a lot of other threads about MissingPluginException errors that deal with adding a plugin to the registry, but I haven't been able to find any that address custom MethodChannels that are not part of another plugin. Is it possible to add my custom MethodChannel to the registry or do something similar that will result in the Dart code being able to call a method from that channel while in the background?

I have tried using workmanager and android_alarm_manager and they seem to run fine themselves, but they still can't get past this block with my custom channel.

My MainActivity.kt has the method details in it:

class MainActivity: FlutterActivity(), MethodChannel.MethodCallHandler {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.app/widget")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when (call.method) {
            "updateFromFlutter" -> {
                val views = RemoteViews(context.packageName, R.layout.appwidget).apply {
                    setTextViewText(R.id.text, call.argument("text"))
                }

                val manager = AppWidgetManager.getInstance(this)
                manager.updateAppWidget(call.argument("idNumber"), views)
            }
        }
    }
}

Then in main.dart I call:

Future<void> updateAndroidWidget(String text) async {
WidgetsFlutterBinding.ensureInitialized();
  const MethodChannel platform = MethodChannel('com.example.app/widget');

  try {
    platform.invokeMethod("updateFromFlutter", {
      "text": text,
      "idNumber": savedPreferences.androidWidgetID
    });
  } catch (e) {
    print("failed: $e");
  }
}

I already have Flutter Android Embedding V2 (Flutter Version >= 1.12).

Any help is greatly appreciated.

8will
  • 51
  • 6

0 Answers0