android蓝牙通信_Flutter通过BasicMessageChannel实现Flutter 与Android iOS 的双向通信

题记:

——不到最后时刻,千万别轻言放弃,无论结局成功与否,只要你拼博过,尽力过,一切问心无愧。

e35557757cf8054e653f68dcad540b6f.png


通过 Flutter 来进行移动应用开发,打包 Android 、iOS 双平台应用程序,在调用如相机、蓝牙、录音、闹钟、屏保等等系列功能时,需要与原生Android、iOS进行消息通信,或者可描述为把数据由 Flutter 传向 Android 、iOS,或者由原生的 Android 、iOS传向 Flutter。


Flutter 与 Android iOS 原生的通信有以下三种方式 

  • BasicMessageChannel 实现 Flutter 与 原生(Android 、iOS)双向通信

  • MethodChannel 实现 Flutter 与 原生原生(Android 、iOS)双向通信

  • EventChannel 实现 原生原生(Android 、iOS)向Flutter 发送消息


本文将实现:(通过 BasicMessageChannel)

  • 实现 Flutter 调用 Android 、iOS 原生的方法并回调Flutter

  • 实现 Flutter 调用 Android 、iOS 原生并打开Android 原生的一个Activity页面,iOS原生的一个ViewController 页面

  • 实现 Android 、iOS 原生主动发送消息到 Flutter 中

  • 实现 Android 、iOS 原生中的 TestActivity 页面主动发送消息到Flutter中


Android 中的效果761abc84402c4313dabfb367b92707a1.gif
ios 中的效果fab23361567a05e9526a7aa69e09797a.gif


前言

    例如我们要实现 A 调用 B,B就会触发,B再调用A,A就会触发这样的功能,
那么我们就需要在 A 中设置 被B调用的监听方法,在B中设置被A 调用的监听方法

1 实现Flutter 调用 Andoid iOS原生方法并回调

    在这里约定的数据格式为 {"code":100,"message":"消息","content":内容}
也就是说双向发送消息,可能会有多种消息类型来调用不同的功能,
统一约定数据格式 可以达到编码的规范性和代码的可维护性
1.1 实现 Flutter 中调用方法
  String recive = "";

//创建 BasicMessageChannel
// flutter_and_native_100 为通信标识
// StandardMessageCodec() 为参数传递的 编码方式
static const messageChannel = const BasicMessageChannel('flutter_and_native_100', StandardMessageCodec());

//发送消息
FuturesendMessage(Map arguments) async {
Map reply = await messageChannel.send(arguments);
//解析 原生发给 Flutter 的参数
int code = reply["code"];
String message = reply["message"];

//更新 Flutter 中页面显示
setState(() {
recive = "code:$code message:$message";
});
return reply;
}

触发调用 ,分别在 三个 Button 的点击事件中触发

//Flutter 向 Android iOS 中基本的发送消息方式
sendMessage({"method": "test", "ontent": "flutter 中的数据", "code": 100});
//用来实现 Android iOS 主动触发 向 Flutter 中发送消息
sendMessage({"method": "test2", "ontent": "flutter 中的数据", "code": 100});
//用来实现 Flutter 打开 Android iOS 中的一个新的页面
sendMessage({"method": "test3", "ontent": "flutter 中的数据", "code": 100});
1.2 实现实现 Android 中监听方法并回调

Android 的 MainActivity 中注册消息监听

flutter 更新之后 FlutterActivity 中没有 getFlutterView() 方法
使用 getFlutterEngine().getDartExecutor().getBinaryMessenger()代替。

  private BasicMessageChannel<Object> mMessageChannel;    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) {                Map<Object, Object> arguments = (Map<Object, Object>) o;                //方法名标识        String lMethod = (String) arguments.get("method");                //测试 reply.reply()方法 发消息给Flutter        if (lMethod.equals("test")) {          Toast.makeText(mContext, "flutter 调用到了 android test", Toast.LENGTH_SHORT).show();          //回调Flutter            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          //Android 可通过这个方法来主动向 Flutter中发送消息          //只有Flutter 中注册了消息监听 才能接收到这个方法向 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);        }      }    });      }  
1.3 实现实现 iOS 中监听方法 并回调

iOS 的 AppDelegate 中

#include "AppDelegate.h"#include "GeneratedPluginRegistrant.h"#import //TestViewController 是创建的一个 测试页面#import "TestViewController.h"@implementation AppDelegate{    FlutterBasicMessageChannel* messageChannel;}- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    [GeneratedPluginRegistrant registerWithRegistry:self];        ... ...     //FlutterBasicMessageChannel 与Flutter 之间的双向通信    [self BasicMessageChannelFunction];        ... ...                 return [super application:application didFinishLaunchingWithOptions:launchOptions];}-(void) BasicMessageChannelFunction{    //获取当前的 controller    FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;    // 初始化定义    // flutter_and_native_100 j     messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"flutter_and_native_100" binaryMessenger:controller];        // 接收消息监听    [messageChannel setMessageHandler:^(id message, FlutterReply callback) {                NSString *method=message[@"method"];        if ([method isEqualToString:@"test"]) {                        NSLog(@"flutter 调用到了 ios test");            NSMutableDictionary *dic = [NSMutableDictionary dictionary];                        [dic setObject:@"[messageChannel setMessageHandler:^(id message, FlutterReply callback)  返回给flutter的数据" forKey:@"message"];            [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"];                                    callback(dic);                    }else  if ([method isEqualToString:@"test2"]) {            NSLog(@"flutter 调用到了 ios test2");            NSMutableDictionary *dic = [NSMutableDictionary dictionary];            [dic setObject:@"[messageChannel sendMessage:dic] 返回给flutter的数据" forKey:@"message"];            [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"];            //通过这个方法 iOS可以主动多次 向 Flutter 发送消息            [messageChannel sendMessage:dic];        }else  if ([method isEqualToString:@"test3"]) {            NSLog(@"flutter 调用到了 ios test3 打开一个新的页面 ");            TestViewController *testController = [[TestViewController alloc]initWithNibName:@"TestViewController" bundle:nil];            [controller presentViewController:testController animated:YES completion:nil];        }    }];    }@end

2 Android 、iOS 原生主动发送消息到 Flutter 中

2.1 实现Android 中主动调动调用方法

在MainActivity中,创建了 BasicMessageChannel 的实例 mMessageChannel,可以在MainActivity 中直接使用 mMessageChannel 实例来向 Flutter 中发送消息。

   private void channelSendMessage() {        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);    //向 Flutter 中发送消息    //参数 二可以再次接收到 Flutter 中的回调    //也可以直接使用 mMessageChannel.send(resultMap)    mMessageChannel.send(resultMap, new BasicMessageChannel.Reply<Object>() {      @Override      public void reply(Object o) {                Log.d("mMessageChannel", "mMessageChannel send 回调 " + o);      }    });  }  

在其他的 Activity 页面中,我们就使用不到这个实例的,我这里的一个实现 Android 中新建的Activity 页面向 Flutter 中发送消息的方法 是广播机制 

在 MainActivity 中注册广播,在广播接收者中通过 BasicMessageChannel 的实例 mMessageChannel 来发送消息。

在 Android 中其他的页面中 发送广播到 MainActivity 中的广播接收者中,这样就实现了Android 中新建的Activity 页面向 Flutter 中发送消息

public class MainActivity extends FlutterActivity {      ... ...    Handler mHandler = new Handler(Looper.myLooper());  private MainReceiver mMainReceiver;    @Override  protected void onDestroy() {    super.onDestroy();    //注销广播    unregisterReceiver(mMainReceiver);  }    @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);        ... ...    //注册广播    mMainReceiver = new MainReceiver();    IntentFilter lIntentFilter = new IntentFilter("android.to.flutter");    registerReceiver(mMainReceiver, lIntentFilter);          }      public class MainReceiver extends BroadcastReceiver {    public MainReceiver() {    }        @Override    public void onReceive(Context context, Intent intent) {      Toast.makeText(context, "接收到自定义的广播", Toast.LENGTH_SHORT).show();      mHandler.post(new Runnable() {        @Override        public void run() {          Map resultMap2 = new HashMap<>();          resultMap2.put("message", "android 主动调用 flutter test 方法");          resultMap2.put("code", 200);                    if (mMessageChannel != null) {            // 向Flutter 发送消息            mMessageChannel.send(resultMap2, new BasicMessageChannel.Reply() {              @Override              public void reply(Object o) {                System.out.println("android onReply: " + o);              }            });          }                  }      });    }  }}
2.2 实现 Flutter 中监听调用方法
 //创建 BasicMessageChannel  // flutter_and_native_100 为通信标识  // StandardMessageCodec() 为参数传递的 编码方式  static const messageChannel = const BasicMessageChannel(      'flutter_and_native_100', StandardMessageCodec());  //接收消息监听  void receiveMessage() {    messageChannel.setMessageHandler((result) async {      //解析 原生发给 Flutter 的参数      int code = result["code"];      String message = result["message"];      setState(() {        recive = "receiveMessage: code:$code message:$message";      });      return 'Flutter 已收到消息';    });  }
2.3 实现 iOS 中主动调动调用方法
#include "AppDelegate.h"#include "GeneratedPluginRegistrant.h"#import #import "TestViewController.h"@implementation AppDelegate{    FlutterBasicMessageChannel* messageChannel;}- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    [GeneratedPluginRegistrant registerWithRegistry:self];            //注册通知    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationFuncion:) name:@"ios.to.flutter" object:nil];        ... ...        return [super application:application didFinishLaunchingWithOptions:launchOptions];}   ... ... - (void)notificationFuncion: (NSNotification *) notification {    // iOS 中其他页面向Flutter 中发送消息通过这里    // 本页中 可以直接使用   [messageChannel sendMessage:dic];    //处理消息    NSLog(@"notificationFuncion ");    NSMutableDictionary *dic = [NSMutableDictionary dictionary];    if (messageChannel!=nil) {        [dic setObject:@" [messageChannel sendMessage:dic]; 向Flutter 发送消息 " forKey:@"message"];        [dic setObject: [NSNumber numberWithInt:401] forKey:@"code"];        //主动向Flutter 中发送消息        [messageChannel sendMessage:dic];    }    }- (void)dealloc {    //单条移除观察者    //[[NSNotificationCenter defaultCenter] removeObserver:self name:@"REFRESH_TABLEVIEW" object:nil];    //移除所有观察者    [[NSNotificationCenter defaultCenter] removeObserver:self];}@end

3b6bc06d0c70eb40b30f53e8ffa60596.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

apache mysql php 安装配置_Windows下Apache,MySql,PHP安装配置

本文目标在Windows8.1 x64下 全手工安装Apache、PHP、MySQL&#xff0c;使用NetBeans调试第一个Hello,World!程序。安装Apache打开http://httpd.apache.org 左侧Download!点From a Mirror&#xff0c;看到当前最新稳定版本未2.4.12&#xff0c; 看到现在Windows的版本已经不像以…

MapReduce既是编程模型又是计算框架

learn from 从0开始学大数据&#xff08;极客时间&#xff09; MapReduce 编程模型 包含 Map 和 Reduce 两个过程 map 的主要输入是一对 <Key, Value> 值&#xff0c;输出一对 <Key, Value> 值将相同 Key 合并&#xff0c;形成 <Key, Value 集合 >再将这个…

python设置单元格宽度_Python xlwt-访问现有单元格内容,自动调整列宽

我刚刚实现了一个包装类&#xff0c;它跟踪输入项的宽度。看起来效果不错。import arial10 class FitSheetWrapper(object): """Try to fit columns to max size of any entry. To use, wrap this around a worksheet returned from the workbooks add_sheet me…

java mysql 流媒体_red5-rtmp-push

red5-rtmp-push介绍获取视频流 进行人脸识别后推送到red5服务器(人脸识别技术由虹软提供)整个系统共有两个项目组成启用说明1.主要是借用ifast框架,主要的服务类就一个,其他的都是多余的。2.首先修改 resources/application-dev.yml 中的 red5.url : rtmp://red5ip/oflaDemo/ 改…

工单更改历史记录(轉載)

一、自定义表结构 二、生产工单出口增强 三、查询报表 一、自定义表结构 表ZPCO02 MANDT MANDT CLNT 3 0 客户端 AUFNR AUFNR CHAR 12 0 订单号 MATNR MATNR CHAR 18 0 物料号 FILED FIELDNAME CHAR 30 0 字段名 AENAM AENAM CHAR 12 0 对象更改人员的名称 LAEDA LAEDA DATS 8 …

MapReduce 计算框架如何运作

learn from 从0开始学大数据&#xff08;极客时间&#xff09; 1. MapReduce 作业启动和运行机制 作业涉及三类关键进程&#xff1a; 大数据应用进程 这类进程是启动 MapReduce 程序的主入口&#xff0c;主要是指定 Map 和 Reduce 类、输入输出文件路径等&#xff0c;并提交作业…

python能做机器人吗_python深度学习 人工智能是做机器人吗?

我们经常听到”Python“与”人工智能“这两个词&#xff0c; 也很容易混淆这两个词&#xff0c; 那么Python和人工智能到底什么关系呢&#xff1f; Python人工智能工程师待遇怎么样&#xff1f; 通过这篇文章详细解答一下&#xff1a; 关于Python Python是一门计算机程序语言&a…

linux忘记mysql密码_Linux下忘记Mysql密码的找回方法(图)

Mysql隔一段时间不访问&#xff0c;也许你会忘记访问密码&#xff0c;这时该怎么办&#xff0c;重装mysql吗&#xff1f;这个代价也太大了&#xff0c;我们这里介绍两种恢复密码的方法。方法一&#xff1a;因为Mysql密码存储于数据库mysql中的user表中&#xff0c;所以我们只要…

单元测试的7种境界

1. 以各种借口拒绝单元测试Unit Test&#xff0c;比较常用的是“你没有足够的时间(进行单元测试)”。  无论是对单元测试的老手还是新手编写单元测试还是有一定得工作量的&#xff0c;而且单元测试也需要掌握大量的测试框架和工具(光一个junit或testng你很难工作地很happy)。…

Yarn 资源调度框架

learn from 从0开始学大数据&#xff08;极客时间&#xff09; Hadoop 主要是由三部分组成&#xff1a; 分布式文件系统 HDFS分布式计算框架 MapReduce分布式集群资源调度框架 Yarn Yarn 的架构

python连接sql数据库_python连接SQL数据库

前言 上次通过学习&#xff0c;懂得了如何通过不同的对象来定位页面的元素&#xff08;id,class_name,tag_name,xpath,css等&#xff09;&#xff0c;可以实现模拟点击的功能。当然&#xff0c;这只是初期的web自动化的一点小成绩。当你觉得这些都应用的差不多的情况下&#xf…

mysql mtop 使用_MYSQLMTOP监控环境搭建

MySQLMTOP是一个由PythonPHP开发的MySQL企业级监控系统。系统由Python实现多进程数据采集和告警&#xff0c;PHP实现WEB展示和管理。最重要是MySQL服务器无需安装任何Agent&#xff0c;只需在监控WEB界面配置相关数据库信息功能非常强大&#xff1a;可对上百台MySQL数据库的状态…

javascript正则表达式入门

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><title> RegExp对象</title><script>/*function validation(obj){//1.得到文本框的值//var …

Hive是如何让MapReduce实现SQL操作的?

learn from 从0开始学大数据&#xff08;极客时间&#xff09; 1. MapReduce 实现 SQL 的原理 SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;实现过程&#xff1a; 2. Hive 的架构 Hive 能够直接处理我们输入的 SQL 语句&#xff08;Hive SQL 语法与 标…

python脚本编程手册_Python 入门指南 — Python2.7 手册 2.7 documentation - 脚本之家在线手册...

Python 入门指南 Release:2.7 Date:December 06, 2014 Python 是一门简单易学且功能强大的编程语言。它拥有高效的高级数据结构&#xff0c;并且能够用简单而又高效的方式进行面向对象编程。Python 优雅的语法和动态类型&#xff0c;再结合它的解释性&#xff0c;使其在大多数平…

mysql spring隔离级别_MySQL事务与Spring隔离级别实现

1、事务具有ACID特性原子性(atomicity)&#xff1a;一个事务被事务不可分割的最小工作单元&#xff0c;要么全部提交&#xff0c;要么全部失败回滚。一致性(consistency)&#xff1a;数据库总是从一致性状态到另一个一致性状态&#xff0c;它只包含成功事务提交的结果隔离型(is…

关闭程序

System.Diagnostics.Process.GetCurrentProcess().Kill();//关闭程序转载于:https://www.cnblogs.com/CandiceW/p/4204564.html

Java JDK 安装配置

文章目录1. 下载安装2. 配置环境变量3. 检查安装成功1. 下载安装 下载地址&#xff1a;https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html&#xff08;需要注册下载&#xff09; 以下操作环境&#xff1a;WIN 10 2. 配置环境变量 JAVA_HOME 为…

mqtt如何判断设备离线_反渗透纯水设备膜元件如何离线清洗?

原标题&#xff1a;反渗透纯水设备膜元件如何离线清洗&#xff1f;在反渗透设备正常运行&#xff0c;无故障时&#xff0c;反渗透系统一般都用在线清洗保养、冲击性杀菌以及定期保护。但是&#xff0c;如果当反渗透膜元件重度污染时&#xff0c;在线清洗就显得无能为力了&#…

mysql的表servers_ERROR 1146 (42S02): Table 'mysql.servers' doesn't exist

修改用户权限&#xff0c;刷新权限表&#xff0c;报1146mysql> flush privileges;ERROR1146 (42S02): Table mysql.servers doesnt existmysql> use mysql;mysql> show tables;可以看到servers表&#xff0c;在系统mysql 目录下&#xff0c;可以看到server.ibd 和serv…