1. 相对于单独开发Flutter应用,混合开发对于线上项目更具有实际意义,可以把风险控制到最低,也可以进行实战上线。所以介绍 集成已有项目

  2. 混合开发涉及原生Native和Flutter进行通信传输,还有插件编写,所以介绍 两端通信Flutter Platform Channel的使用

WanAndroid客户端简单Flutter版 Apk

集成已有项目

官方方案 | 闲鱼团队方案 | 头条团队方案

采用官方的实现方式,对个人和小团队相对简单易用,并没有实践闲鱼和头条等大项目的方式。个中利弊上述推荐均有提到。

开始

  1. 在已有项目根目录运行命令

flutter create -t module my_flutter

不一定非在项目下创建,兼顾ios,位置路径寻址对即可

2.在项目的settings.gradle 文件添加如下代码

// MyApp/settings.gradle
include ':app' // assumed existing content
setBinding(new Binding([gradle: this])) // new
evaluate(new File( // new
settingsDir.parentFile, // new
'my_flutter/.android/include_flutter.groovy' // new
)) // new
Binding飘红不予理会,强迫症的不用导包
'my_flutter/.android/include_flutter.groovy'为my_flutter文件路径,报错找不到可写项目全路径'ChannelFlutterAndroid/my_flutter/.android/include_flutter.groovy'
3.在运行模块app的build.gradle添加依赖
// MyApp/app/build.gradle
dependencies {
implementation project(':flutter')
}

4.在原生Android端创建并添加flutterView

val flutterView = Flutter.createView(this, lifecycle, "route1")
val layoutParams = FrameLayout.LayoutParams(-, -)
addContentView(flutterView, layoutParams)

5.在Flutter端入口操作

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
switch (route) {
case 'route1':
return SomeWidget(...);
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}
  1. 至此,集成完毕

两端通信Flutter Platform Channel的使用

本文主要是介绍使用方式,闲鱼团队详尽的介绍了实现原理

Flutter提供 MethodChannelEventChannelBasicMessageChannel 三种方式

  1. 类似注册监听,发送的模式 原则
  2. 使用顺序:先注册,后发送,否则接收不到。尤其使用 MethodChannelEventChannel 不符合该原则会抛出异常,BasicMessageChannel方式只是收不到消息

方式一 MethodChannel

应用场景:Flutter端 调用 Native端

Flutter端代码:

var result = await MethodChannel("com.simple.channelflutterandroid/method",
StandardMethodCodec())
.invokeMethod("toast", {"msg": msg})

Android端代码:

MethodChannel(flutterView, "com.simple.channelflutterandroid/method",
StandardMethodCodec.INSTANCE)
.setMethodCallHandler { methodCall, result ->
when (methodCall.method) {
"toast" -> {
//调用传来的参数"msg"对应的值
val msg = methodCall.argument<String>("msg")
//调用本地Toast的方法
Toast.makeText(cxt, msg, Toast.LENGTH_SHORT).show()
//回调给客户端
result.success("native android toast success")
}
"other" -> {
// ...
}
else -> {
// ...
}
}
}
  • 注意点1:两端需要对应一致的点
    方法名称:com.simple.channelflutterandroid/method,可以不采取包名,对应一致即可,不同的方式最好不要重复
    传参key:"msg"

  • 注意点2:以下为Flutter为例,Android同理
    StandardMethodCodec() 非必传,默认是 StandardMethodCodec(),是一种消息编解码器

    对于 MethodChannelEventChannel 两种方式,有两种编解码器,均实现自MethodCodec ,分别为 StandardMethodCodecJsonMethodCodec

    对于 BasicMessageChannel 方式,有四种编解码器,均实现自MessageCodec ,分别为 StandardMessageCodecJSONMessageCodecStringCodecBinaryCodec

  • 注意点3:setMethodCallHandler(),针对三种方式一一对应,属于监听
    MethodChannel - setMethodCallHandler()
    EventChannel - setStreamHandler()
    BasicMessageChannel - setMessageHandler()
    其中setStreamHandler()方式稍微特殊,具体查看上面提的闲鱼文章

  • 注意点4:FlutterView 实现 BinaryMessenger 接口

以上,以下两种方法不再赘述

方式二 EventChannel

应用场景:Native端 调用 Flutter端,方式稍微特殊

Flutter端代码:属于接收方

EventChannel("com.simple.channelflutterandroid/event")
.receiveBroadcastStream()
.listen((event){
print("It is Flutter - receiveBroadcastStream $event");
})

注意 receiveBroadcastStream

Android端代码:属于发送方

EventChannel(flutterView, "com.simple.channelflutterandroid/event")
.setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(o: Any?, eventSink: EventChannel.EventSink) {
eventSink.success("我是发送Native的消息")
} override fun onCancel(o: Any?) {
// ...
}
})

方式三 BasicMessageChannel

应用场景:互相调用

两种使用方式,创建方式和格式不一样

第一种

Flutter端

_basicMessageChannel = BasicMessageChannel("com.simple.channelflutterandroid/basic",
StringCodec()) // 发送消息
_basicMessageChannel.send("我是Flutter发送的消息"); // 接收消息
_basicMessageChannel.setMessageHandler((str){
print("It is Flutter - receive str");
});

Android端

val basicMessageChannel = BasicMessageChannel<String>(flutterView, "com.simple.channelflutterandroid/basic",
StringCodec.INSTANCE) // 发送消息
basicMessageChannel.send("我是Native发送的消息") // 接收消息
basicMessageChannel.setMessageHandler { o, reply ->
println("It is Native - setMessageHandler $o")
reply.reply("It is reply from native")
}

其中StringCodec(),四种方式可选

第二种

Flutter端

static const BASIC_BINARY_NAME = "com.simple.channelflutterandroid/basic/binary";

   // 发送消息
val res = await BinaryMessages.send(BASIC_BINARY_NAME, ByteData()) // 接收消息
BinaryMessages.setMessageHandler(BASIC_BINARY_NAME, (byteData){
println("It is Flutter - setMessageHandler $byteData")
});

Android端

const val BASIC_BINARY_NAME = "com.simple.channelflutterandroid/basic/binary"

   // 发送消息
flutterView.send(BASIC_BINARY_NAME,ByteBuffer.allocate()); // 接收消息
flutterView.setMessageHandler(BASIC_BINARY_NAME) { byteBuffer, binaryReply ->
println("It is Native - setMessageHandler $byteBuffer")
binaryReply.reply(ByteBuffer.allocate())
}

此组合可以进行图片的传递

help 在操作中使用此方式传输数据总报错,所以只传了默认ByteBuffer。还是姿势不对???目前未发现,求大神指教

如有错误之处,万望各位指出!谢谢

其他

  1. Native端接收方收到消息后都能进行回传信息,在Flutter进行异步接收
    MethodChannel:result.success("我是回传信息");
    EventChannel:eventSink.success("我是回传信息");
    BasicMessageChannel:binaryReply.reply(-);- Flutter端:ByteData;Android端:ByteBuffer

Q&A

以上均为理想情况,过程中还是存在许多问题,以下提供参考

Q:使用命令行flutter create创建的project或者module,文件android/ios为隐藏打点开头的.android/.ios文件
A:所以有的时候会出现问题,寻找不到文件的情况

Q: flutter create module 和project的区别
A: ?? 目前没发现

Q:couldn't locate lint-gradle-api-26.1.2.jar for flutter project
A: https://stackoverflow.com/questions/52945041/couldnt-locate-lint-gradle-api-26-1-2-jar-for-flutter-project

Q: Could not resolve all files for configuration ':app:androidApis'.
Failed to transform file 'android.jar' to match attributes {artifactType=android-mockable-jar, returnDefaultValues=false} using transform MockableJarTransform
A:https://github.com/anggrayudi/android-hidden-api/issues/46

Q: Flutter Error: Navigator operation requested with a context that does not include a Navigator
A: https://github.com/flutter/flutter/issues/15919

Flutter与Android混合开发及Platform Channel的使用的更多相关文章

  1. flutter 与 android 混合开发

    现有的混合开发方式,都是存flutter项目在android系统或者iOS上面跑. 但是,实际情况是,我们需要在一个成熟的native项目上面,跑几个flutter页面,逐步的进行flutter的融合 ...

  2. uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式

    前言: 关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式. 一.H5+方法调用android原生方法 H5+ Android开发规范官 ...

  3. android混合开发,webview的java与js互操作

    android原生应用,用webview加载应用中的网页,并且java代码与js代码可以互相操作. 这是混合开发的基石,最基本也最重要的东西,实验代码在这里. 概括说说—— java调js:调用web ...

  4. Android 混合开发 的一些心得。

    其实所谓这个混合开发,也就是hybird,就是一些简单的,html5和native 代码之间的交互.很多电商之类的app里面都有类似的功能, 这种东西其实还是蛮重要的,主要就是你有什么功能都可以进行热 ...

  5. Android混合开发,html5自己主动更新爬过的坑

    如今使用混合开发的公司越来越多,尽管出现了一些新技术,比方Facebook的react native.阿里的weex,但依旧阻挡不了一些公司採用h5的决心.当然,这也是从多方面考虑的选择. 在三年前就 ...

  6. [Hybrid App]--Android混合开发,Android、Js的交互

    AndroidJs通信 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !imp ...

  7. uni-app&H5&Android混合开发一 || 最全面的uni-app离线打包Android平台教程

    前言: 为什么会写这么一个教程,因为很久之前做过一个对接银行POS我们的系统是使用的H5开发的app应用.但是假如对结果银行相关业务的小伙伴应该都清楚,银行的业务相对于其他的对接方而言安全性比较高,而 ...

  8. Flutter + Android 混合开发

    JIT (Just In Time) 即时编译器, 边执行边编译 程序运行时,JIT 编译器选择将最频繁执行的方法编译成本地代码.运行时才进行本地代码编译而不是在程序运行前进行编译 AOT可以理解为“ ...

  9. Unity和Android混合开发

    通用的流程 https://blog.csdn.net/zhangdi2017/article/details/65629589 应用场景 Unity游戏中一些功能需要安卓系统的支持,如搜索wifi等 ...

随机推荐

  1. js04

    接着看一些js的基础,这里主要说一下js的对象. 1.对象:    js中的所有事物都可以看作是对象:字符串.数值.数组.函数...    内建对象:String    Date    Array   ...

  2. Maven私服架设(nexus / on windows)

    Maven私服可以用多个不同的产品可供选择,下面我们演示使用最为广泛的nexus来架设maven本地私服   Nexus的下载及安装请见官方下载页: http://www.sonatype.org/n ...

  3. Linux的管道命令

    Linux的管道命令 管道命令(Pipe) 管道命令用"|"来表示,管道命令需要接收前一个命令的输出来进行操作,但不能处理前一个命令的错误. //选取界面:cut,grep cut ...

  4. sql日期格式处理

    sql server中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-02-01 ...

  5. a标签发送邮件

    <a href="Mailto:292808135@qq.com?CC=292808135@qq.com&Subject=反馈&Body=花式求喷~%0A您的不满就是我 ...

  6. java8 学习之路之lambda

    前言 目前我们知道java的版本已经发布到12了,之前的项目用的是JDK1.7,听说JDK1.8的改动相对来说大一些,因此抽空学学JDK1.8的一些新特性.本人也是通过阅读Java8实战这本书做一些小 ...

  7. dynamic解析Http xml格式响应数据

    继续上一篇 构建RESTful风格的WCF服务 ,咱已经把服务端的数据和服务准备好了,客户端调用 wcf rest接口后如何解析xml?下面使用dynamic关键字解析来至于WCF REST XML响 ...

  8. 16-hadoop-mapreduce简介

    mapreduce是hadoop的核心组件, 设计理念是移动计算而不是移动数据, mapreduce的思想是'分而治之', 将复杂的任务分解成几个简单的任务去执行 1, 数据和计算规模大大减少 2, ...

  9. Linux-文件和目录属性

    文件系统的是用来组织和排列文件存取的,所以它是可见的,在Linux中,我们可以通过ls等工具来查看其结构,在Linux系统中,见到的都是树形结构:比如操作系统安装在一个文件系统中,他表现为由/ 起始的 ...

  10. C++运行时动态类型

    RTTI 运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast typeid操作符的实现 静态类 ...