android应用程序类启动时运行flutter代码

Mah*_*alv 13 android flutter

我正在为 Flutter 制作一个插件,以使用 android 本机库处理 fcm 消息。

我们知道当FCM收到消息时,它会启动应用程序(它是应用程序类)并运行Application#onCreate块内的代码,因此当应用程序在后台通过fcm启动时,我们可以运行本机代码。

我的问题是,是否可以在应用程序启动时运行flutter代码?
例如,如果收到消息:

应用类:

public class Application extends FlutterApplication {

  @Override
  public void onCreate() {
    super.onCreate();
    // Start flutter engine
    // Invoke a dart code in the Plugin using methodChannel or etc.
  }
}
Run Code Online (Sandbox Code Playgroud)

Mah*_*alv 10

简短的回答,是的

您可以使用其句柄键在后台调用 Dart 方法。

1. 在后台注册您的插件

实现自定义应用程序类(覆盖FlutterApplication

public class MyApp extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {

    @Override
    public void registerWith(io.flutter.plugin.common.PluginRegistry registry) {
        // For apps using FlutterEmbedding v1
        GeneratedPluginRegistrant.registerWith(registry);
       // App with V2 will initialize plugins automatically, you might need to register your own however
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住AndroidManifest通过添加android:name=".MyApp"<application>属性在 中注册类。

什么是嵌入 v2?

2.在你的颤振代码中创建一个设置函数作为顶级函数

/// Define this TopLevel or static
void _setup() async {
  MethodChannel backgroundChannel = const MethodChannel('flutter_background');
  // Setup Flutter state needed for MethodChannels.
  WidgetsFlutterBinding.ensureInitialized();

  // This is where the magic happens and we handle background events from the
  // native portion of the plugin.
  backgroundChannel.setMethodCallHandler((MethodCall call) async {
    if (call.method == 'handleBackgroundMessage') {
      final CallbackHandle handle =
          CallbackHandle.fromRawHandle(call.arguments['handle']);
      final Function handlerFunction =
          PluginUtilities.getCallbackFromHandle(handle);
      try {
        var dataArg = call.arguments['message'];
        if (dataArg == null) {
          print('Data received from callback is null');
          return;
        }
        await handlerFunction(dataArg);
      } catch (e) {
        print('Unable to handle incoming background message.\n$e');
      }
    }
    return Future.value();
  });
Run Code Online (Sandbox Code Playgroud)

3.创建一个顶级回调,将获取后台消息并调用它

_bgFunction(dynamic message) {
    // Message received in background
    // Remember, this will be a different isolate. So, no widgets
}
Run Code Online (Sandbox Code Playgroud)

4.获取后台函数的handle key并设置并通过MethodChannel发送给native

// dart:ui needed
CallbackHandle setup PluginUtilities.getCallbackHandle(_setup);
CallbackHandle handle PluginUtilities.getCallbackHandle(_bgFunction);

_channel.invokeMethod<bool>(
  'handleFunction',
  <String, dynamic>{
    'handle': handle.toRawHandle(),
    'setup': setup.toRawHandle()
  },
);
Run Code Online (Sandbox Code Playgroud)

5.在native端保存到SharedPref中

public void onMethodCall(MethodCall call, MethodChannel.Result result) {
  String methodName = call.method
  if (methodName == "handleFunction") {
     long handle = call.argument("handle");
     long setup = call.argument("setup");
     // save them
  }
}

Run Code Online (Sandbox Code Playgroud)

6.当后台唤醒时,启动后台隔离

FlutterMain.ensureInitializationComplete(context, null)
val appBundlePath = FlutterMain.findAppBundlePath()
val flutterCallback = FlutterCallbackInformation.lookupCallbackInformation(setupHandleYouHadSaved)

FlutterNativeView backgroundFlutterView = FlutterNativeView(context, true)

val args = FlutterRunArguments()
args.bundlePath = appBundlePath
args.entrypoint = flutterCallback.callbackName
args.libraryPath = flutterCallback.callbackLibraryPath

backgroundFlutterView?.runFromBundle(args)

// Initialize your registrant in the app class
pluginRegistrantCallback?.registerWith(backgroundFlutterView?.pluginRegistry)
Run Code Online (Sandbox Code Playgroud)

7.当您的插件注册后,创建一个后台通道并将其传递给

val backgroundChannel = MethodChannel(messenger, "pushe_flutter_background")
Run Code Online (Sandbox Code Playgroud)

8. 调用设置方法,该方法会调用并将消息传递给您的回调

private fun sendBackgroundMessageToExecute(context: Context, message: String) {
    if (backgroundChannel == null) {
        return
    }

    val args: MutableMap<String, Any?> = HashMap()
    if (backgroundMessageHandle == null) {
        backgroundMessageHandle = getMessageHandle(context)
    }
    args["handle"] = backgroundMessageHandle
    args["message"] = message
    // The created background channel at step 7
    backgroundChannel?.invokeMethod("handleBackgroundMessage", args, null)
}
Run Code Online (Sandbox Code Playgroud)

sendBackgroundMessageToExecute会执行镖_setup功能和传递消息和回调句柄。在第 2 步中,将调用回调。

注意:您可能仍然需要考虑某些极端情况(例如线程等待和......)。签出示例并查看源代码。

有几个项目支持在后台启动应用程序时后台执行。

Firebase 消息传递

普什

工作经理


ath*_*hor 0

您可以使用 headless Runner 从应用程序类(或服务、广播接收器等)运行 dart 代码。

有一篇关于如何实现这一点的深入文章:https://medium.com/flutter/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124