flutter module打包成framework引入原生工程

Flutter - 将 Flutter 集成到现有项目(iOS - Framework篇)

本篇文章大幅参考了 caijinglong 大佬的总结文章: 把flutter作为framework添加到已存在的iOS中[1]

用 Flutter 来开发,从来都不可能是新开的一个纯 Flutter 项目,很大一部分都是 老项目接入 Flutter 来混编。

在 Flutter 官网 - Adding to an iOS app[2] 这里,官方也给出了一些将 Flutter 集成进入现有 iOS 项目的方法。但是,这些都多多少少的不符合我们的需求。

1. 从 Flutter Module 说起

想要把 Flutter 集成进现有 iOS 项目,我们就必须使用 Flutter Module

那就先用命令创建一个 Flutter Module:flutter create --template module flutter_test_module

Flutter APP 和 Flutter Module 的不同之处在于 pubspec.yaml 最后一段:

javascript 复制代码
# This section identifies your Flutter project as a module meant for
# embedding in a native host app.  These identifiers should _not_ ordinarily
# be changed after generation - they are used to ensure that the tooling can
# maintain consistency when adding or modifying assets and plugins.
# They also do not have any bearing on your native host application's
# identifiers, which may be completely independent or the same as these.
module:
androidX: true
androidPackage: com.example.flutter_test_module
iosBundleIdentifier: com.example.flutterTestModule

复制

这一段代码,把该 Flutter 项目标注为一个 module,用于嵌入到原生 app 里。

这里面设置了是否使用 androidx,Android 和 iOS 的 APP id。

2. iOS原生项目所需的文件

先说一下,iOS 原生项目引入 Flutter Module 需要如下 Framework:

1.Flutter.framework2.App.framework3.FlutterPluginRegistrant.framework (如果有用到原生的插件 - 非纯 dart 编写)4.Pods_Runner.framework(如果有用到原生的插件 - 非纯 dart 编写)5.*.framework(插件的 framework)

下面继续集成。

Flutter Module 创建完成后,先来给 iOS 打个包,命令如下:flutter build ios --release --no-codesign

然后看一下打包出来的东西,路径为 build->ios->Release-iphoneos

如果有第三方库的话,这里面应该是有上面说的 3、4、5 的 framework,但是我们刚创建项目,什么都没有加,所以是没有任何 framework的。

然后去 .ios/Flutter 里找 1、2:

但是我们写程序不可能什么插件都不用,所以加上一个shared_preferences[3],再来打包看一下 build 文件夹:

可以看到确实出现了我们上面说的 3、4、5 framework,这样我们所需的 framework 全部集齐。

3. 使用 cocoapods + git 来管理

因为 caijinglong 大佬 文章内说:

因为找遍了 podfile 的相关文档, 没有找到可以直接引用 framework 的方式 所以需要一个 pod 库作为"中转"

所以我们就要 跟着做!

使用命令 pod lib create flutter-lib 来创建一个名为 flutter-lib的私有库。

创建完成之后,打开 flutter-lib.podspec ,在 end 前面加入一行:

接着我们在该文件夹内创建一个名为 ios_frameworks 的文件夹,把我们刚才的那么多 framework 全都粘贴过来。

这个时候我们的iOS原生项目就可以引入本地这个库了:

javascript 复制代码
platform :ios, '8.0'
use_frameworks!

target 'xxx.xxx.xxx' do
   pod 'flutter-lib', :path => 'somepath/flutter-lib'
end

复制

当然,我们不可能都用本地路径来引入,所以我们把这整个 flutter-lib文件夹传到 git 上,然后这样引用:

javascript 复制代码
platform :ios, '8.0'
use_frameworks!

target 'xxx.xxx.xxx' do
   pod 'flutter-lib', :git => 'http://xxxx.git'
end

复制

这样我们就可以从 git 上来远程引用该私有库了。

如果运行有错误的话,可以去 caijinglong 大佬的博客查看解决办法。[4]

4. 编写脚本自动处理

上面都是手动来处理的,包括打包->移动文件->上传git等。

下面就写一个脚本来处理一下(基于 caijinglong 大佬):

javascript 复制代码
ios_project_name='xxx'    # 项目名称
ios_out_path='xxx/ios_frameworks'    # 文件输出路径
flutter_git_path='http://xxx/xxx/xxx.git'    # git 项目路径

function customEcho(){
  echo "\033[1;32m$1\033[0m"
}
customEcho '\n1. 执行 flutter clean'
flutter clean || exit -1

customEcho '\n2. 清空build文件夹'
rm -rf $ios_project_name
rm -rf build
echo '清空完成'

customEcho '\n3. 生成 iOS frameworks'
flutter build ios --release --no-codesign || exit -1 

customEcho "\n4. 从 git 上克隆 frameworks 项目"
git clone $flutter_git_path  || exit -1 

customEcho "\n5. 输出文件到 $ios_out_path"
rm -rf $ios_out_path
mkdir $ios_out_path


cp -r build/ios/Release-iphoneos/*/*.framework $ios_out_path
cp -r .ios/Flutter/App.framework $ios_out_path
# cp -r .ios/Flutter/engine/Flutter.framework $out
echo '输出完成'

customEcho "\n6. 提交文件到 git"
cd $ios_project_name
git add .
git commit -m 'update lib'
git push -u origin master


customEcho "\n7. 删除该文件夹"
cd ..
rm -rf $ios_project_name

customEcho "\nAll Done."

复制

解释就不用解释了,上面的输出都有写。

这里有一点,就是 Flutter.framework 超级大,有四五百兆,我们把它单独放在了一个 pod 里,而剩下的一些每次新增插件或变更代码都会跟着变动,所以他们是一个单独的 pod。

也就是说,该 Flutter Module 一共有三个 git 仓库:

1.Flutter Module 项目的仓库(编写代码等)2.Flutter Module 打包出来的 frameworks(不包含 Flutter.framework)3.Flutter.framework 仓库

这样的好处就是在我们编写完代码,运行 sh 文件的时候,不用去下载一个四五百兆的 flutter 引擎,脚本速度提升很快,并且其他的 iOS 项目也可以引用。

接着改一下 flutter-lib.podspec 文件,

把这一行改成如下:

javascript 复制代码
p = Dir::open("ios_frameworks")
arr = Array.new
p.each do |f|
  if f == '.' || f == '..'
  else
    arr.push('ios_frameworks/'+f)
  end
end
s.ios.vendored_frameworks = arr

复制

这样就完成了引入所有的 frameworks。

5. 总结

到这里 Flutter Module 就完全引入到了现有的 iOS 工程中,关于如何运行代码,可以去官方文档 - Adding a Flutter screen to an iOS app[5] 中查找。

这样集成的方案,感觉是目前最方便的了。(如有更佳方案,烦请告知)

Flutter 端写完代码直接运行 ./build_module.sh 就可以了。

iOS 端直接 pod install,超级简单。

如有缺陷,希望大家提出,共同学习!?

References

[1] 把flutter作为framework添加到已存在的iOS中: https://www.kikt.top/posts/flutter/exists/add-flutter-to-ios/ [2] Flutter 官网 - Adding to an iOS app: https://flutter.dev/docs/development/add-to-app/ios/project-setup [3] shared_preferences: https://pub.dev/packages/shared_preferences [4] caijinglong 大佬的博客查看解决办法。: https://www.kikt.top/posts/flutter/exists/add-flutter-to-ios/#使用-cocoapod-管理原生工程 [5] 官方文档 - Adding a Flutter screen to an iOS app: https://flutter.dev/docs/development/add-to-app/ios/add-flutter-screen?tab=vc-objective-c-tab

相关推荐
火柴就是我8 小时前
flutter 之真手势冲突处理
android·flutter
Speed1238 小时前
`mockito` 的核心“打桩”规则
flutter·dart
法的空间8 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
恋猫de小郭8 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
玲珑Felone9 小时前
从flutter源码看其渲染机制
android·flutter
ALLIN1 天前
Flutter 三种方式实现页面切换后保持原页面状态
flutter
Dabei1 天前
Flutter 国际化
flutter
Dabei1 天前
Flutter MQTT 通信文档
flutter
Dabei1 天前
Flutter 中实现 TCP 通信
flutter
孤鸿玉1 天前
ios flutter_echarts 不在当前屏幕 白屏修复
flutter