Flutter与android原生通信

2023-11-17

 

Flutter 与 Android/iOS 之间信息交互通过 Platform Channel 进行桥接; Flutter 定义了三种不同的 Channel;但无论是传递方法还是传递事件,其本质上都是数据的传递;

  1. MethodChannel:用于传递方法调用;
  2.  EventChannel:用于数据流信息通信;
  3. BasicMessageChannel:用于传递字符串和半结构化的信息;

每种 Channel 均包含三个成员变量;

  1. name:代表 Channe 唯一标识符,Channel 可以包含多个,但 name 为唯一的;
  2. messager:代表消息发送与接收的工具 BinaryMessenger;
  3. codec:代表消息的编解码器

1、MethodChannel:

flutter代码:

// 调用原生方法
static const methodChannel = const MethodChannel('flutter_and_native_101');

static Future<dynamic> invokNative(String method, {Map arguments}) async {
  if (arguments == null) {
    return await methodChannel.invokeMethod(method);
  } else {
    return await methodChannel.invokeMethod(method, arguments);
  }
}

// 监听原生返回
Future<dynamic> nativeMessageListener() async {
    methodChannel.setMethodCallHandler((resultCall) {
      MethodCall call = resultCall;
      String method = call.method;
      Map arguments = call.arguments;

      int code = arguments["code"];
      String message = arguments["message"];
      setState(() {
        recive += " code $code message $message and method $method \n";
        print(recive);
      });
      return null;
    });
  }

// 调用
onPressed: () {
    invokNative("test")
    ..then((result) {
        int code = result["code"];
        String message = result["message"];
        setState(() {
        	recive = "invokNative 中的回调 code $code message $message ";
        });
    });
}

android代码:

private void methodChannelFunction() {
    mMethodChannel = new MethodChannel(getFlutterView(), "flutter_and_native_101");
    //设置监听
    mMethodChannel.setMethodCallHandler(
            new MethodChannel.MethodCallHandler() {
                @Override
                public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                    String lMethod = call.method;

                    if (lMethod.equals("test")) {
                        Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("message", "result.success 返回给flutter的数据");
                        resultMap.put("code", 300);
                        result.success(resultMap);

                    } else if (lMethod.equals("test2")) {
                        //Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("message", "android 主动调用 flutter test 方法");
                        resultMap.put("code", 301);
                        mMethodChannel.invokeMethod("test", resultMap);

                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                Map<String, Object> resultMap2 = new HashMap<>();
                                resultMap2.put("message", "android 主动调用 flutter test 方法 delay 2000ms");
                                resultMap2.put("code", 302);
                                mMethodChannel.invokeMethod("test2", resultMap2);
                            }
                        }, 2000);
                    } else if (lMethod.equals("test3")) {
                        //测试通过Flutter打开Android Activity
                        Toast.makeText(mContext, "flutter 调用到了 android test3", Toast.LENGTH_SHORT).show();
                        Intent lIntent = new Intent(MainActivity.this, TestMethodChannelActivity.class);
                        MainActivity.this.startActivity(lIntent);
                    } else {
                        result.notImplemented();
                    }
                }
            }
    );
}

通过 flutter_and_native_101 唯一标识将flutter和andorid之间的 channel 连接起来。flutter 传递对应的方法名称在native 接受方法后解析名称,在对比调用不同逻辑。

2、EventChannel:相当于接收来自native的通知

只能是原生发送消息给Flutter端,例如监听手机电量变化,网络变化,传感器等。

flutter 端:

//EventChannel( 用于数据流(event streams)的通信)
static const EventChannel _eventChannel = const EventChannel('flutter_and_native_102');

Future<dynamic> nativeMessageListener() async {
  _eventChannel.receiveBroadcastStream().listen((arguments) {
    int code = arguments["code"];
    String message = arguments["message"];
    setState(() {
      recive +=
          " code $code message $message \n";
      print(recive);
    });
  }, onError: (event) {
    print(event);
  });
}

android原生:

/**
 * 此方法适用于android 系统有通知通知到flutter的场景
 *
 * */
private void eventChannelFunction() {
    EventChannel lEventChannel = new EventChannel(getFlutterView(), "flutter_and_native_102");
    lEventChannel.setStreamHandler(
            new EventChannel.StreamHandler() {
                @Override
                public void onListen(Object o, EventChannel.EventSink eventSink) {
                    mEventSink = eventSink;
                    Log.d("zxzx","event sink = " + o);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            Map<String, Object> resultMap = new HashMap<>();
                            resultMap.put("message", "注册成功");
                            resultMap.put("code", 400);
                            eventSink.success(resultMap);
                        }
                    });
                }

                @Override
                public void onCancel(Object o) {

                }
            }
    );
}

同理,flutter注册监听,监听 flutter_and_native_102 channel来的广播。

3、BasicMessageChannel

它是可以双端通信的,flutter端可以给Android发送消息,Android也可以给Flutter发送消息。

flutter 端:

static const messageChannel = const BasicMessageChannel( 'flutter_and_native_100', StandardMessageCodec());

  //发送消息
  Future<Map> sendMessage(Map json) async {
    Map reply = await messageChannel.send(json);

    //解析 原生发给 Flutter 的参数
    int code = reply["code"];
    String message = reply["message"];

    setState(() {
      recive = "code:$code message:$message";
    });
    return reply;
  }

  //接收消息监听
  void receiveMessage() {
    messageChannel.setMessageHandler((result) async {
      //解析 原生发给 Flutter 的参数
      int code = result["code"];
      String message = result["message"];

      setState(() {
        recive = "receiveMessage: code:$code message:$message";
      });
      return 'Flutter 已收到消息';
    });
  }

android端:

private void messageChannelFunction() {
        //消息接收监听
        //BasicMessageChannel (主要是传递字符串和一些半结构体的数据)
        mMessageChannel = new BasicMessageChannel<Object>(getFlutterView(), "flutter_and_native_100", StandardMessageCodec.INSTANCE);
        // 接收消息监听
        mMessageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<Object>() {
            @Override
            public void onMessage(Object o, BasicMessageChannel.Reply<Object> reply) {

                System.out.println("onMessage: " + o.toString());
                Map lJSONObject = null;
                //解析Flutter 传递的参数
                lJSONObject = (HashMap) o;
                //方法名标识
                Object lMethod = lJSONObject.get("method");
                Log.d("MainActivity","lmethod = " + lMethod);
                //测试 reply.reply()方法 发消息给Flutter
                if (lMethod.equals("test")) {
                    Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("message", "reply.reply 返回给flutter的数据");
                    resultMap.put("code", 200);
                    reply.reply(resultMap);
                } else if (lMethod.equals("test2")) {
                    //测试 mMessageChannel.send 发消息给Flutter
                    channelSendMessage();
                } else if (lMethod.equals("test3")) {
                    //测试通过Flutter打开Android Activity
                    Toast.makeText(mContext, "flutter 调用到了 android test3", Toast.LENGTH_SHORT).show();
                    Intent lIntent = new Intent(MainActivity.this, TestBasicMessageActivity.class);
                    MainActivity.this.startActivity(lIntent);
                }
            }
        });
    }

    private void channelSendMessage() {
        Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", "message Channel.reply 返回给flutter的数据");
        resultMap.put("code", 201);

        mMessageChannel.send(resultMap, new BasicMessageChannel.Reply<Object>() {
            @Override
            public void reply(Object o) {
                Log.d("MainActivity", "mMessageChannel send 回调 " + o);
            }
        });
    }

具体的使用哪种通信方式,看具体的使用场景。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter与android原生通信 的相关文章

  • 如何使用 Android 版 Facebook 同步的联系人图片

    我的手机上安装了 Android 版 Facebook 它会自动将联系人列表中人员的 FB 个人资料图片同步到我的手机 我想在我访问的应用程序中使用这些图片ContactsContract PhoneLookup 我真的需要 Faceboo
  • Sqlite 查询检查 - 小于和大于

    return mDb query DATABASE TABLE new String KEY ROWID KEY LEVEL KEY LEVEL gt 3 lt 5 null null null null 我究竟做错了什么 它返回的值全部高
  • 如何使用 (a)smack 在 Android 上保持 XMPP 连接稳定?

    我使用适用于 Android 的 asmack android 7 beem 库 我有一个后台服务正在运行 例如我的应用程序保持活动状态 但 XMPP 连接迟早会在没有任何通知的情况下消失 服务器表示客户端仍然在线 但没有发送或接收数据包
  • android - 过度绘制布局允许通过 LinearLayout 进行触摸

    在下面的 UI 中 我将下面的 drabable 覆盖了整个屏幕 LinearLayout 是透明的 并允许其下方的控件可单击或可触摸 基本上我可以滚动此 LinearLayout 下面的列表以及单击控件 我如何禁用它 See attach
  • 不使用 CookieManager 的 Android 会话 cookie

    我的应用程序进行多次网络调用以获得身份验证 我需要将此会话存储在 cookie 中 我想使用 Cookie Manager 但经过一些研究后 我发现它仅适用于 API 9 及更高版本 并且我的应用程序需要向后兼容 我使用 HTTPURLCo
  • PhoneGap 是应用程序开发的好选择吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Android,语言文件不起作用

    我现在正在创建一个 Android 应用程序 并尝试为我的母语添加语言文件 但在某种程度上 这对我不起作用 我尝试在两部不同的手机中加载该应用程序 但结果相同 之前创建过语言文件 效果良好 但这次不行 手机设置为瑞典语 语言文件适用于我创建
  • 从Asynctask返回结果

    如果我的 Android 应用程序中有这个后台工作文件 并且它从我的数据库获取数据 我如何将字符串 结果 传递给另一个类 后台工作人员连接到我的服务器 然后使用 php 连接到数据库 public class BackgroundWorke
  • 使用 POST 将数据从 Android 发送到 AppEngine Datastore

    抱歉 如果这是一个简单的问题 但我只是不知道我应该做什么 而且我认为我有点超出了我的深度 我想将数据从 Android 应用程序发送到在 Google App Engine 上运行的应用程序 数据必须从那里写入数据存储区 我的数据主要采用对
  • Android Things 文件系统

    我正在 Android 上构建这个应用程序 我希望能够让它访问 U 盘上的媒体文件 甚至树莓派的 SD 卡上的媒体文件 我还不知道我将如何处理这些文件 但我只是想知道它是否可能 如果不是这样也没关系 我还有其他解决方案 但我想我会先从明显的
  • 将 ArrayList 保存在捆绑包 savingInstanceState 中

    ArrayList 是在类级别定义的 这些是我保存的实例方法 Override protected void onSaveInstanceState Bundle outState super onSaveInstanceState out
  • ImageButton 拉伸背景图像

    我正在尝试创建一个没有边框的 ImageButton 但遇到了图像按钮大小的问题 我使用 Eclipse ADT 将 ImageButton 拖到布局中并选择背景图像 图像按钮显示如下 正如您所看到的 背景图像和图像按钮周边之间有一个边框
  • 使用startActivityForResult,如何获取子活动中的requestCode?

    我有四项活动 即 A B C 和 D 我的情况是A将通过startActivityForResult启动活动B startActivityForResult new Intent this B class ONE 在另一种情况下 我将使用不
  • 对基本适配器类及其功能的疑问

    我正在尝试自定义列表视图 我使用数组列表添加对象列表 并将其发送到扩展基本适配器的类 当我扩展基本适配器类时 它实现了一些方法 例如 getView 等 在 getView 中 我将其发送到将名称 数据 分配给 XML 格式的自定义菜单的类
  • 如何在Android中隐藏应用程序标题? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想隐藏应用程序标题栏 您可以通过编程来完成 import android app Activity import android os
  • EditText 的高度不会扩展到其父级的高度

    我在滚动视图中放置了编辑文本 高度 match parent并期望它的高度等于滚动视图 但事实并非如此 它的高度就像wrap content这意味着如果 EditText 中没有文本 我必须将光标指向要弹出的软键盘的第一 行 我想要的是我可
  • Exif 方向标签返回 0

    我正在开发一个自定义相机应用程序 我面临以下问题 当我尝试使用检索方向时ExifInterface 它总是返回 0 ORIENTATION UNDEFINED 这使我无法将图像旋转到正确的状态 从而无法正确显示 我使用示例代码来设置相机旋转
  • Flutter/Dart:将十六进制颜色字符串转换为颜色?

    我们的数据库将颜色保存为String就像 AABBCC 所以我基本上正在寻找这样的函数 Color parseColor AABBCC 对于颤振 Color 类需要这样的东西Color 0xFF42A5F5 所以我需要转换 AABBCC t
  • SambaFileInputStream 和 FileInputStream 有什么不同?

    我需要从 samba 服务器流式传输视频 并且我使用 nanohttpd 在我的项目中创建简单的服务器 当我使用本地文件中的 fileinputstream 时 视频视图可以按设置播放视频 http localhost 8080 publi
  • 将数据放入短信发送意图中?

    我想发送短信 如果文字太长 我会将其分成多条消息 我试图将一些额外的信息放入 已发送 意图中 以了解哪个部分已发送 以及所有部分何时完成 ArrayList

随机推荐

  • 异步复位,同步释放的理解

    文章目录 什么情况下 复位信号需要做 异步复位 同步释放 处理 异步复位同步释放原理 利用前面两级触发器实现 特点 问题1 如果没有前面两级触发器的处理 异步信号直接驱动系统的触发器 会出现什么情况 问题2 复位信号存在亚稳态 有危险吗 问
  • Angular中的管道

    Angular同在在模板文件中使用一些管道 这些管道是用来对字符串 货币金额 日期等数据进行转换和格式化的 管道的本质是一些简单的函数 可以在模板表达式中用来接受输入值并返回一个按一定规则转换后的值 Angular内置管道 DatePipe
  • js数组的includes方法优化判断逻辑

    js数组的includes方法代替大量判断 优化前 function printAnimals animal if animal dog animal cat console log I have a animal printAnimals
  • Python 利用随机函数和电脑玩石头剪刀布

    首先导入第三方库 random import random 注意 使用前请先下载random函数 import random 从控制台出拳 拳头 剪刀 布 player input 请输入你要出的拳 石头 剪刀 布 电脑随机出拳 先假定电脑
  • vue+element-ui el-table组件二次封装(2023-09-03 TTable组件实现虚拟滚动,解决数据量大页面卡顿问题)

    2023 09 03 TTable组件实现虚拟滚动 解决数据量大页面卡顿问题 所有示例效果 1 简介 HTML一行代码 可以实现表格编辑 分页 表格内 外按钮操作 行内文字变色 动态字典展示 filters格式化数据 排序 显示隐藏表格内操
  • 三维旋转:旋转矩阵,欧拉角,四元数

    在介绍下面的文章前 大家如果接触到欧拉角的话 就一定要关注一个词 要顺规 在欧拉角体系里面 有12种顺规 这一点是好多文章没有让读书意识到 导致后面学习图形学里面的 heading pitch bank 时对不上号 一般百度百科里面说到的
  • 课程笔记2

    一 实现 1 区块链是去中心化的账本 比特币采用的是基于交易的账本模式 区块链的全节点需要维护一种名叫UTXO的数据结构 所有未花掉的交易的输出的集合 可以有效检测双花攻击 交易的总输入略微大于总输出 这是因为比特币的第二个激励机制 获得记
  • load data inpath出错原因及解决方法

    hive gt load data inpath hdfs Master hdp 9000 person txt into table Person1 FAILED SemanticException Error 10028 Line 1
  • java setcellvalue NA_java minioClient.setBucketPolicy 调用失败 折腾好几天了 求大佬解惑...

    方法调用后 提示 Request processing failed nested exception is java lang IllegalArgumentException unknown error code string Malf
  • 简要损益科目口诀,营业外收支和其他业务收支的区别

    一 损益科目口诀 三收三费所得税 两成三益外加减 三收 主营业务收入 其他业务收入 营业外收入 三费 管理费用 财务费用 销售费用 这是常用费用 某些企业可能还分有研究开发费用 两成 主营业务成本 其他业务成本 三益 投资收益 公允价值变动
  • java查看包的源代码

    把鼠标放在方法上 按Ctrl进去 打开的 class文件就是Java jdk1 7 0 src zip中的源码 但是在Java jdk1 7 0 src zip 中是以 java为扩展名
  • ios开发教程入门到精通

    第1集 初识macOS 点击观看 第2集 开发工具Xcode 点击观看 第3集 初识Objective C 点击观看 待续
  • 华为机试 牛客网 HJ1 字符串最后一个单词的长度

    华为机试 牛客网 HJ1 字符串最后一个单词的长度 描述 输入描述 输出描述 示例一 解法一 解法二 反思 描述 计算字符串最后一个单词的长度 单词以空格隔开 字符串长度小于5000 输入描述 输入一行 代表要计算的字符串 非空 长度小于5
  • shell简单脚本编写

    1 第一步 安装邮件服务 root server yum install s nail y 第二步 编辑配置文件 root server vim etc s nail rc set from 自己的qq邮箱地址 set smtp smtp
  • OpenCV - 基本知识

    1 读取并显示图片 namedWindow新建一个显示窗口 imshow输出图片 namedwindow可有可无 Mat image cv imread E 其他文档 图片 2 jpg 2 cv namedWindow 照片 CV WIND
  • window中gcc编译程序、编辑环境配置以及gcc编译程序的过程(含system函数以及CMD快捷键)

    1 system函数的使用 include
  • 关于rocketmq 中日志文件路径的配置

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 rocketmq 中的数据和日志文件默认都是存储在user home路径下面的 往往我们都需要修改这些路径到指定文件夹以便管理 服务端日志 网
  • ML-朴素贝叶斯

    参考 西瓜书 P151 以前对贝叶斯参数的计算过程不是很清楚 在西瓜书里讲的很详细 原来可以把X属性分为离散型与连续型 离散型的话可以直接按照频率计算 连续型的话 要用极大似然估计 首先假设概率密度函数满足一个分布 比如正态分布 然后利用已
  • 动态控制ToolStrip上ToolStripButton的大小(包括图标的大小)

    一 设置固定大小的ToolStripButton 设置固定大小的ToolStripButton很简单 ToolStripButton gt AutoSize属性设置为false size调整为自己想要的大小即可 同时配合的是ToolStri
  • Flutter与android原生通信

    Flutter 与 Android iOS 之间信息交互通过 Platform Channel 进行桥接 Flutter 定义了三种不同的 Channel 但无论是传递方法还是传递事件 其本质上都是数据的传递 MethodChannel 用