Flutter踩坑:原生安卓页面向Flutter通信

Flutter踩坑:原生安卓页面向Flutter通信

前言

Flutter APP 的开发过程中,有时不仅需要使用 Flutter 提供的组件,还需要使用原生的组件。

例如在对接外部 SDK 时,如果自己重新实现 SDK 的逻辑,无疑是本末倒置。

前文中我们已经接入并且打开了原生安卓的页面,也就是说主动通信已经完成。

真实的项目中,肯定不可能只有 Flutter 向原生安卓通信,肯定也原生安卓向 Flutter 发送信息。

操作其实很简单,就是将 method channel 的调用,反过来,由原生执行 invokeMethod ,由 Flutter 接收 method

但是这里面有很多坑。

执行

在插件中实例化MethodChannel,并且注册 MethodCallHandler

同时将这个 MethodChannel 放到静态变量中,以便在 Java 页面中调用。

这个我在网上搜了很多方式,都是让实例化 Flutter Engine 或者实例化 plugin 插件,但是实际上都没能成功,估计重新实例化的已经不是当前的这个 Flutter Engine实例或者插件实例了。

java 复制代码
// 省略import
public class TestPlugin implements FlutterPlugin, MethodCallHandler,ActivityAware {
  static public MethodChannel channel;

  private Activity activity;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    TestPlugin.channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "test_plugin");
    TestPlugin.channel.setMethodCallHandler(this);
  }

  static public MethodChannel getChannel(){
    return TestPlugin.channel;
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    System.out.println( "================ 收到方法调用 ==========");
    System.out.println( call.method);
    if (call.method.equals("openNativePage")) {
      if (activity != null) {
        Intent intent = new Intent(activity, MainActivity.class);
        activity.startActivity(intent);
        result.success("Native page opened");
      } else {
        result.error("ACTIVITY_NOT_AVAILABLE", "Activity is not available", null);
      }
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    TestPlugin.channel.setMethodCallHandler(null);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    activity = null;
  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivity() {
    activity = null;
  }
}

Java 页面中的调用

java 复制代码
TestPlugin.getChannel().invokeMethod("onMessageReceived", "这里是发送的信息");

Flutter 页面中接收到信息

Dart 复制代码
MethodChannel("test_plugin").setMethodCallHandler((call) async {
  print("接到方法调用: ${call.method}");
  if (call.method == 'onMessageReceived') {
    final String message = call.arguments as String;
    print('========aaa Received message from android: $message');
    // TODO: 处理接收到的信息
  }
});

总结

原生向 Flutter 发送信息时,会遇到许多莫名其妙的问题,网上搜了很多方法,但是都无效。

例如安卓原生页面直接继承 FlutterActivity,重新拿到 FlutterEngine实例然后实例化MethodChannel,但是真机调试时报设备不支持GooglePlay服务。

还有直接实例化插件类等等方式都不能成功。

因此我换用了在插件中直接使用静态变量传递已经初始化好的 MethodChannel,果然奏效。

当然,我觉得这个问题应该有更好的解决方案,但是目前没有找到,先使用这个方式解决问题,以作记录。

相关推荐
louisgeek21 分钟前
Android NSD 网络服务发现
android
张可1 小时前
历时两年半开发,Fread 项目现在决定开源,基于 Kotlin Multiplatform 和 Compose Multiplatform 实现
android·前端·kotlin
余辉zmh1 小时前
【Linux系统篇】:信号的生命周期---从触发到保存与捕捉的底层逻辑
android·java·linux
ak啊2 小时前
Flutter项目架构设计方案
flutter
孤鸿玉2 小时前
[Flutter小试牛刀] 低配版signals,添加多层监听链
android·前端·响应式设计
雨和卡布奇诺2 小时前
LiveData源码浅析
android
淡蓝色_justin2 小时前
Hilt-plus 简介
android·android jetpack
app1e2343 小时前
ctfshow web入门 命令执行(29-77)
android·前端
JarvanMo4 小时前
在Dart泛型中应该优先使用dynamic还是Object?
前端·flutter·dart