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,果然奏效。

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

相关推荐
好的佩奇1 小时前
蓝牙之无线电与通信距离
android·flutter·蓝牙
vilya1 小时前
我把一套完整的 Python Agent 运行时塞进手机 APK:依赖闭包、Rust 轮子和三个真机坑
android
呆呆敲代码的小Y3 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
思想觉悟5 小时前
SEAndroid实战
android·linux·c++
思想觉悟5 小时前
Aosp开发磨刀石之ADB速查
android·c++
应用市场8 小时前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理
企业数字化笔记8 小时前
表单发布前怎么验收?版本引用、字段兼容和历史数据回归
android·数据挖掘·回归
生信分析笔记8 小时前
Nature 正刊 GPN-Star 基因组语言模型
android
渣渣盟8 小时前
Flink 状态管理深度剖析:从 KeyedState 到 RocksDB,状态如何存储、恢复与扩缩容
android·大数据·flink
avi91118 小时前
电影开源Jevdo - 源码介绍(vue版)没有android 和 没有wpf
android·wpf·框架·数据爬虫·meego·电影管理