把flutter项目作为aar添加到已有的Android工程上
对于已有工程想要尝鲜 Flutter, 很多公司给出了最佳实践方案, android 中是使用 aar 加入项目中, 这样原生开发对于 flutter 环境就没有要求了, 只要 flutter 打包后上传 maven 即可, 但是这部分的过程坑很多, 后面我会再补充这种方案
我也摸索了一个实践方案, 将所有项目的 aar 由 flutter 方打包 aar 后将 aar 置入某一个固定位置 ,并置入一个 git 库管理, 然后 android 原生方直接 pull 后引入项目即可
高能预警: 本篇会结合 flutter, android, aar, gradle, maven, docker 的知识来完成所有的步骤
并不是每一个都会详细说明, 如果有不明白的可以在 https://www.kikt.top 的本文下面留言, 我会更新文章或给予解答, 其他渠道的可能不会有时间看
开发环境
本人设备环境
MacOS 10.13.6 (17G65)
flutter: Flutter 1.5.4-hotfix.2 • channel stable
预计需要的环境
这些环境我默认你都有, 没有的话本篇不讲
windows 用户? 对不住, 自己找寻其中的差别吧…
flutter
创建 flutter module
使用命令行创建:
$ flutter create -t module flutter_module
这里理论上会生成一个 aar
嗯,就这个东西
我们其实可以直接把这个 aar 放在宿主中,然后通过配置 aar 本地引用来直接使用这个工程, 但是这样可能并不利于持续集成
所以我们要用到 maven 这个利器
ps: 这里有个坑, 就是纯 flutter 项目可以, 但是如果你的 flutter 项目包含了对于第三方项目的依赖, 则 aar 可能不会包含其他的内容, 我们放在最后面再想办法解决
maven 的处理方式(看看就行,作为错误尝试的步骤)
本篇主要讲的是 maven 的方式, 没有原生 plugin 的很简单, 但是有原生 plugin 的 flutter 步骤过于复杂, 最终没实现, 当然理论上肯定是可以实现的
因为本篇讲解的是本人解决 flutter 附着到已有工程的尝试,所以将放弃的过程也记录下来, 如果你只是想看最终的实现方案可以跳过本篇和后续所有涉及到 maven 的步骤
maven 是一个包管理工具
如果你公司有自己的私服, 则跳过这一章直接看下一章, 我这里只是使用 docker 创建一个 maven 私服环境
使用的镜像是 sonatype/nexus3
配置
可选: $ docker pull sonatype/nexus3
我比较熟悉的有两种方式:
命令行直接运行
使用 docker-compose
使用 docker-compose 就是类似于配置文件的方式
运行
在浏览器打开 http://localhost:8099
登录的用户名密码,默认是 admin admin123
点开 maven, 毛也没有
上传 aar
使用 gradle 上传 aar
使用 android studio 打开 flutter_module 下的.android 目录, 经过一顿同步得到的可能是这样的:一片空白毛都没有…
这时候请 close, 重新打开, 现在是这个鬼样子的
采用 project 视图模式
在.android 下增加一个 gradle 文件,名字自取
比如我的就叫 update_aar.gradle
这个文件呢, 就是上传用的 gradle 文件, 来源于网络
前几个 def 要根据你的 maven 来修改, 包名, 端口, 用户名,密码
接着引入 gradle 文件到项目中
修改: Flutter/build.gradle
按照下图点击
可能会报错
似乎是由于路径不对的原因, 请使用如下的方式修改 setting.gradle:
同步 gradle 后
接着双击
就可以上传成功了
然后打开 nexus 查看: http://localhost:8099/#browse/search/maven
有显示, 说明这个 aar 上传是成功的
后面再上传更改版本号即可
Android 项目(host)
新建项目
引入 maven 依赖
添加仓库
根目录 build.gradle, 根据节点增加一个 maven 仓库:
引入库, 在 nexus 的管理界面里可以查看引用方式:
接着在app/build.gradle
中修改
经过 sync 以后,使用 project 视图, 可以找到这个库:
编码
新建 MyFlutterActivity.java
添加到清单文件
修改 MainActivity.java
这里模拟一进来直接进 FlutterActivity 的场景
建议你的 Android 同事在合适的时机调用 Flutter.startInitialization(this.getApplicationContext());
这个是官方给出的初始化 flutter 引擎的代码, 否则首屏可能会慢
运行项目
初次运行可能会报错 提示一个 androidO 什么的玩意
两种方案
- minSDK 修改为 26, 这个简直不科学
- 在 app/build.gradle 下的 android 节点下增加这个代码
将源码和目标代码等级都设置为 1.8
嗯 这里插一句, 我的 host 使用的是 androidX, 而 flutter 使用的是 android.support, 所以需要按照 androidX 的迁移流程修改一下, 如果你新建项目的时候勾选了 androidX, 则这里应该不用修改
androidX 的问题可以查看我的另一篇文章, 虽然是 flutter 分类下的,但是对于普通 android 工程也适用
运行结果如下:
在 flutter 中添加带有原生功能的库
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
这里注意!!!!!!, 请先备份前面几个文件
因为一旦 flutter packages get, 则 前面的文件就木有了
在 flutter 中添加库
这里简单举例一下, 使用一个比较常用的shared_preferences
修改 flutter 的 yaml 文件
$ flutter packages get
这一步后, 之前的那几个文件没有了…
建议: 把 build.gradle 和 setting.gradle 复制到 module 级别的某个目录下, 比如叫 template
然后用脚本来做这个上传的事情
- 复制模板到对应目录
- 通过环境变量设置 aar 的版本号
- 使用 gradle 命令来完成插件的调用
上传新版本的 aar
修改版本号为 1.0.1
这里上传成功了
到 android host 中用了一下, 果不其然和网上的朋友们说的一样报错了
查看对应的 pom.xml(我这里是 1.0.2),道理是一样的
这里有一个 io.flutter.plugins.sharedpreferences 就是报错的元凶了
思考解决方案
看到这里我感觉有如下的方案
- 将所有文件打包到同一个 aar 库中, 然后再上传(也就是网上那个 fat-aar 的方案)
- 修改 flutter 打包脚本, 然后将中间的三方库产物(sp 插件)上传至私服 maven, flutter 项目使用 api 的方式依赖这些库, 完成 host=>flutter=>other plugin 的目的
- 不用 maven, 只用 aar
个人第一感觉, 觉得第一个实施起来可能会简单一些, 先尝试一下
fat-aar
这个找到了两个项目:
一个 gradle 文件的方式: https://github.com/adwiv/android-fat-aar
一个是 plugin 的方式: https://github.com/Vigi0303/fat-aar-plugin
但是都要用到一个类似embed
这样的关键字来替换 compile(api/implementation), 无奈找遍 gradle 没找到修改的地方, 只能暂时放弃
flutter 的插件库上传至 maven
这个初始来看很可行.. 但仔细一想, 因为那个版本号的作祟, 需要改动的地方不算很少
每个插件包内的 gradle 文件都需要修改:
- 修改 version 版本号,这个应该是可以通过 环境变量/gradle 命令 来指定为佳, 不能指定的话理论上和 pub 的版本号相同也可以, 如果是 git 依赖, 就用 ref, path 依赖就很比较难自动取了
- 上传脚本,这个要读取上面的版本号, 还要读取一个
为什么要修改版本号呢? flutter 依赖的插件的版本号会被带到 aar 对应的 maven 库中的 pom.xml 文件中
这里要插一句: pom.xml 中依赖的版本号是定义在每个插件自己的 build.gradle 中的,如下面的连接那样
我这里说需要修改的就是这个版本号,否则你上传 maven 的 flutter 库的版本号和插件的 maven 版本号没对上的话,依然会报错
修改版本号并上传需要遵循如下的步骤:
- 读取本地
.flutter-plugins
文件的内容,将其中的版本号字段取出来 - 找到插件文件夹,替换掉版本号字段的内容
- 将上传插件的脚本复制至对应文件夹,并将版本号,group 名与插件统一
- 启动上传脚本
- 将对原生文件的修改内容还原
为什么要做最后一步呢? 这种"从远端"镜像下来的东西,修改回去是一个好习惯, 因为修改了会破坏仓库本身版本的完整性
解决方案-使用 aar 和 git 管理
这个就是我开篇说的解决方案, 不使用 maven, 只是打包出 aar, 集中起来, 置入 git 仓库,如果有必要就打 tag 后 push 到远端, 方便根据版本来引用
然后作为 android 原生方, 在 project 的 gradle 中引入 aar 库即可, 当然如果你是大公司有自己的要求, 还是用上一种比较好
git 和 aar 引入也是很成熟的使用方案了, 无非就是如何拼接而已的问题, 何况这一步还可以通过 gradle 自动完成
处理 flutter 端
这次使用 dart 来作为脚本, 毕竟 dart 语言对于 flutter 开发者来说会很熟悉, 当然这一步可以用任何你熟悉的方式,比如: shell/python 等等, 这一步的执行需要将 dart 放入环境变量中
build_module.dart
: