问题
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