Invoke Flutter (Dart) code from native Android home screen widget

为君一笑 提交于 2019-12-03 16:23:08

问题


I added a native Android home screen widget to my Flutter application.

In my AppWidgetProvider implementation, I'd like to call dart code in my onUpdate() method using a platform channel.

Is this possible? If so, how can this be achieved?

My current Android (Java) code:

package com.westy92.checkiday;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.util.Log;

import io.flutter.plugin.common.MethodChannel;
import io.flutter.view.FlutterNativeView;

public class HomeScreenWidget extends AppWidgetProvider {

    private static final String TAG = "HomeScreenWidget";
    private static final String CHANNEL = "com.westy92.checkiday/widget";

    private static FlutterNativeView backgroundFlutterView = null;
    private static MethodChannel channel = null;

    @Override
    public void onEnabled(Context context) {
        Log.i(TAG, "onEnabled!");
        backgroundFlutterView = new FlutterNativeView(context, true);
        channel = new MethodChannel(backgroundFlutterView, CHANNEL);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.i(TAG, "onUpdate!");
        if (channel != null) {
            Log.i(TAG, "channel not null, invoking dart method!");
            channel.invokeMethod("foo", "extraJunk");
            Log.i(TAG, "after invoke dart method!");
        }
    }
}

Dart code:

void main() {
  runApp(Checkiday());
}

class Checkiday extends StatefulWidget {
  @override
  _CheckidayState createState() => _CheckidayState();
}

class _CheckidayState extends State<Checkiday> {
  static const MethodChannel platform = MethodChannel('com.westy92.checkiday/widget');

  @override
  void initState() {
    super.initState();
    platform.setMethodCallHandler(nativeMethodCallHandler);
  }

  Future<dynamic> nativeMethodCallHandler(MethodCall methodCall) async {
    print('Native call!');
    switch (methodCall.method) {
      case 'foo':
        return 'some string';
      default:
      // todo - throw not implemented
    }
  }

  @override
  Widget build(BuildContext context) {
    // ...
  }
}

When I add the widget to my home screen, I see:

I/HomeScreenWidget(10999): onEnabled!
I/HomeScreenWidget(10999): onUpdate!
I/HomeScreenWidget(10999): channel not null, invoking dart method!
I/HomeScreenWidget(10999): after invoke dart method!

However, my dart code does not seem to be receiving the invocation.


回答1:


First, please ensure that you are invoking FlutterMain.startInitialization() and then FlutterMain.ensureInitializationComplete() before attempting to execute any Dart code. These calls are necessary to bootstrap Flutter.

Second, can you try this same goal using the new experimental Android embedding?

Here is a guide for executing Dart code using the new embedding: https://github.com/flutter/flutter/wiki/Experimental:-Reuse-FlutterEngine-across-screens

If your code still doesn't work as expected with the new Android embedding then it should be easier to debug what the problem is. Please post back with success, or any new error information.




回答2:


maybe you can use invokeMethod(String method, @Nullable Object arguments, MethodChannel.Result callback) and use callback to get the fail reason.




回答3:


You need to pass the getFlutterView() from the MainActivity instead of creating a new BackgroundFlutterView:

channel = new MethodChannel(MainActivity.This.getFlutterView(), CHANNEL);

"This" being like:

public class MainActivity extends FlutterActivity {
    public static MainActivity This;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        This = this;
        ...
    }


来源:https://stackoverflow.com/questions/53940400/invoke-flutter-dart-code-from-native-android-home-screen-widget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!