Flutter在混合项目中的构建和集成

写在前头

在之前的一篇文章《Flutter的探索与实践》中关于Flutter如何构建到现有项目这一节没有详细说,这篇文章将会介绍Flutter在混合项目中的构建和集成方面踩过的坑以及解决方案。

目标

扇贝现有的项目是原生混合React Native,并且是以组件化的架构存在,现在想在一些页面上用Flutter进行重构,想要在新的Flutter项目上集成以前的所有代码肯定是不现实的,同时又不想将Flutter项目直接侵入到我们的项目结构中去,于是我们选择将重构好的Flutter代码单独编译成aar,以组件的形式被主工程依赖。

这样做的好处是显而易见的:
对Flutter进行探索开发的同学可以在自己的Flutter工程内编写dart代码,独立运行调试,发布版本的时候打包成aar集成到主工程中让写native代码的同学接入,两方可以协同工作,不会产生耦合。

探索过程

下面的构建和集成是以Android项目为例。

首先用Android Studio或者命令行新建一个Flutter Application项目。

得到如下项目结构

在命令行输入命令flutter build apk
会编译生成apk文件,位于build/app/outputs/apk/release/文件夹下。
将apk解压缩后就可以看到里面的结构组成。

这个apk里的产物实际上是在Android的app/build.gradle构建代码里引入了Flutter的构建代码。

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

通过阅读flutter构建源码我们发现在构建apk文件的时候,会将需要的文件构建到apk中。

1.assets文件夹

assets文件夹下面有flutter_assets文件夹、flutter_shared文件夹、isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr文件。

  • flutter_assets里是flutter工程产生的assets文件
  • flutter_shared里是封装在flutter.jar里面的处理字符编码的ICU库
  • isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr为特定平台的数据和指令
2.lib文件夹

lib文件夹下是特定平台(arm或者x86)的so文件。

flutter在Android平台下会默认生成arm-v7架构的的so库,flutter.gradle源码中会根据target-platform属性判断平台动态生成对应的so,官方注释目前flutter只支持在debug模式下生成x86的so。

扇贝应用集成了一部分三方的so库,而且只选用了arm架构的so库,x86的设备只占到1%左右,因此下面的操作都是默认为arm架构。对需要x86 so的同学下文会做说明。

抽取aar

上面通过编译命令得到了apk,那想要打包成aar,理论上只要把app/build.gradle中的apply plugin: 'com.android.application'修改为apply plugin: 'com.android.library',同时删除applicationId "com.shanbay.flutterapp"再次执行flutter build apk命令,便可以得到app-release.aar文件。

集成到现有项目

我们将得到的aar文件集成到现有的Android工程中供native的小伙伴使用,但是打开flutter页面却闪退了,同时flutter报出了error,错误是说aar里面缺少icudtl.dat文件。

解压缩aar查看文件结构,可以发现其中的问题。


在aar文件夹下的assets里面缺少了flutter_shared文件夹,icudtl.dat文件正是在该文件夹里面,也就是说flutter.gradle在编译流程中并没有将icudtl.dat文件打进aar包里面,这一点从flutter库的issue里面得到了证实,我们的办法是将apk里面得到的flutter_shared文件夹手动copy到flutter工程中,再次编译aar,这样就可以得到有icudtl.dat的aar文件。再次集成到Android项目中便可以成功运行,不会产生错误。

总结

这个方案需要两个步骤,第一步是先编译成apk取得icudtl.dat文件放入到工程中,第二步修改apply plugin: 'com.android.library'再次编译取得aar。

优点
  • 完全依赖flutter自己的编译流程,不会对其源码进行修改,侵入flutter编译流程,定制化的成分较少,适用于绝大部分场景,同时随着flutter更新,需要对这套流程做修改的可能性也比较小。
  • 可以直接接入CI系统,最小修改。
  • 在android工程中可以编写sample代码,通过flavor构建在release aar时移出sample代码,不需要另外建立host工程运行调试。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flutter项目申请存储的使用权限可以使用 `permission_handler` 插件来实现。 以下是申请存储权限的步骤: 1. 在项目的 `pubspec.yaml` 文件添加 `permission_handler` 依赖: ```yaml dependencies: permission_handler: ^8.0.0+2 ``` 然后执行 `flutter pub get` 命令安装依赖。 2. 在需要申请存储权限的位置,调用 `Permission.storage.request()` 方法来请求存储权限,例如: ```dart import 'package:permission_handler/permission_handler.dart'; Future<void> requestStoragePermission() async { final PermissionStatus status = await Permission.storage.request(); if (status == PermissionStatus.granted) { // 权限已经被授予 } else if (status == PermissionStatus.denied) { // 用户拒绝了权限请求 } else if (status == PermissionStatus.permanentlyDenied) { // 用户拒绝了权限请求,并且不会再次弹出权限请求对话框 } } ``` 在这里,我们首先调用 `Permission.storage.request()` 方法来请求存储权限,然后根据返回的 `PermissionStatus` 枚举值判断用户的授权情况。如果权限已经被授予,则可以执行相应的操作;如果用户拒绝了权限请求,则可以提示用户开启权限;如果用户拒绝了权限请求,并且不会再次弹出权限请求对话框,则可以引导用户手动开启权限。 3. 在你的应用程序,你应该在合适的地方请求存储权限,例如在用户需要保存或加载文件时。 例如,在用户点击保存按钮时,你可以调用 `requestStoragePermission()` 方法来请求存储权限: ```dart ElevatedButton( onPressed: () async { await requestStoragePermission(); // 用户已经授权 // 保存文件 }, child: Text('保存'), ); ``` 在这里,我们在用户点击保存按钮时调用 `requestStoragePermission()` 方法来请求存储权限。如果用户授权了权限,则可以执行相应的操作,例如保存文件。如果用户拒绝了权限请求,则可以在合适的地方提示用户开启权限。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值