少湖说 | 科技自媒体

互联网,科技,数码,鸿蒙

1.环境搭建

参考文章鸿蒙Flutter实战:01-搭建开发环境搭建好开发环境。IDE 安装好 DevEco 和 VsCode/Android Studio。

2.配置

如果是 vscode, 可以在 .vscode/launch.json 文件中,增加以下配置

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "ohos-app (attach mode)",
"cwd": "packages/apps/ohos_app",
"request": "attach",
"type": "dart",
},
{
"name": "ohos_app",
"cwd": "packages/apps/ohos_app",
"request": "launch",
"type": "dart"
},

添加成功后,会在运行和调度的 Tab 栏目中,出现启动的选项。这里添加了两个配置,一个是 Attach 模式,一个是普通的运行模式。

3.查看日志

查看日志,可以在运行Flutter处的IDE调试控制台查看 Flutter 项目日志,可以使用 hdc hilog 命令或DevEco 查看系统日志。

4.调试 Flutter

主要有两种调试方案。

方案一

在IDE 中直接运行 Flutter 项目,IDE 可选择 Andriod Studio 或者 VsCode,在调试栏点击 Debug 运行。

方案二

适应DecEco运行鸿蒙项目,注意需要打开的是ohos鸿蒙目录代码,待IDE分析结束后,点击运行。

当app在鸿蒙设备上启动成功后,立即在 Vscode 中调出 Command Pallet,找到 Flutter Attach ,将 Flutter 调试器连接至宿主机

然后就是增加断点,使用hot reload 重新加载 Flutter,调试项目代码。

调试 ArkTs

需要使用 DevEcho 打开项目,点击运行旁边的 Debug Entry 按钮,开始程序调试。

调试 Webview

参考文章 鸿蒙Flutter实战:04-如何使用DevTools调试Webview进行 Webview 调试。

背景

原来使用Flutter开发的项目,需要适配鸿蒙。

环境搭建

见文章[鸿蒙Flutter适配指南],搭建开发环境,使用fvm管理多版本SDK。

模块化

原有项目保持模块化,拆分为 apps/common/components/modules/plugins等目录,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.
├── README.md
├── analysis_options.yaml
├── melos.yaml
├── melos_ogw-flutter.iml
├── node_modules
├── packages
│ ├── README.md
│ ├── apps
│ │ ├── app
│ │ ├── dsm_app
│ │ ├── ohos_app
│ │ └── web
│ ├── common
│ │ ├── domains
│ │ ├── extensions
│ │ ├── services
│ │ └── widgets
│ ├── components
│ │ ├── image_uploader
│ │ ├── player
│ │ └── scroll_banner
│ ├── modules
│ │ ├── address
│ │ ├── community
│ │ ├── home
│ │ ├── invoice
│ │ ├── me
│ │ ├── message
│ │ ├── order
│ │ ├── shop
│ │ ├── support
│ │ ├── updater
│ └── plugins
│ ├── image_picker
│ ├── printer
├── pubspec.lock
├── pubspec.yaml
└── yarn.lock
  1. plugins 是依赖于原生平台的插件,

  2. components 是平台无关的组件,

  3. common 里面是领域对象,小组件,服务类,扩展等,平台无关,里面均为纯 Dart 代码。

  4. apps 是应用外壳,通过组合不同的模块,向不同的平台打包。

  5. 使用 melos 管理多包仓库。

其中apps下的项目,则为需要打包成各平台,各app的入口项目。里面主要为项目配置代码,模块依赖配置,以及特定的平台适配代码。

在apps目录下新建鸿蒙项目,先把壳项目在鸿蒙中跑起来,确保没有问题。依次再添加依赖项,首先添加纯dart编写的包,再添加依赖于原生代码/插件的包。注意挨个添加依赖,不要一次添加太多依赖,方便排查定位问题,

解决版本依赖问题,鸿蒙 Flutter 项目目前需要依赖于3.7版本,如果原项目使用了更低的版本,则可将原项目SDK依赖升级至3.7;如果原项目SDK版本高于3.7,则有两种方案:一种是降级原项目SDK依赖为3.7;另外一种是使用多分支方案。

如果需要使用 Flutter 3.22 版本,参见文章 鸿蒙Flutter实战:11-使用 Flutter SDK 3.22.0

特定平台工程

在 apps 目录下新建一个项目,该项目运行鸿蒙平台适配和打包。

1
flutter create --platforms ohos ohos_app

目录结构如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
.
├── README.md
├── analysis_options.yaml
├── assets
│ ├── icons
│ │ ├── 2.0x
│ │ ├── 3.0x
│ │ └── placeholder.png
│ └── images
│ ├── 2.0x
│ └── 3.0x
├── build
│ ├── ...
├── env
├── lib
│ ├── config
│ │ ├── easy_refresh.dart
│ │ ├── routes.dart
│ │ └── theme.dart
│ └── main.dart
├── ohos
│ ├── AppScope
│ │ ├── app.json5
│ │ └── resources
│ ├── build-profile.json5
│ ├── entry
│ │ ├── build
│ │ ├── build-profile.json5
│ │ ├── hvigorfile.ts
│ │ ├── oh-package-lock.json5
│ │ ├── oh-package.json5
│ │ ├── oh_modules
│ │ └── src
│ ├── har
│ │ ├── ...
│ ├── hvigor
│ │ └── hvigor-config.json5
│ ├── hvigorfile.ts
│ ├── local.properties
│ ├── oh-package-lock.json5
│ ├── oh-package.json5
│ └── oh_modules
│ └── ...
├── pubspec.lock
└── pubspec.yaml

可以看到,该项目只是一个壳工程,没有太多代码,主要为项目的一些特定配置,如主题、路由等,以及App入口初始化配置。

编辑 pubspec.yaml 文件,添加组件和模块依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
environment:
sdk: '>=2.19.6 <3.0.0'
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# 下拉刷新
easy_refresh: ^3.0.4+2
flutter_dotenv: ^5.1.0
go_router: ^6.0.0

# 领域对象
domains:
path: '../../common/domains'
# 通用服务类
services:
path: '../../common/services'
# 纯 Dart UI 组件
widgets:
path: '../../common/widgets'
# 模块: 收货地址
address:
path: '../../modules/address'
# 模块: 帮助中心
support:
path: '../../modules/support'
# 模块:个人中心
me:
path: '../../modules/me'
# 模块:消息通知
message:
path: '../../modules/message'
# 模块:订单
order:
path: '../../modules/order'
# 模块:商城
shop:
path: '../../modules/shop'
# 模块:首页
home:
path: '../../modules/home'

插件鸿蒙化适配

部分第三方插件以及插件依赖的其他库,如果没有适配鸿蒙,则可以通过 override配置鸿蒙化的版本

1
2
3
4
5
6
dependency_overrides:
# ohos
path_provider:
git:
url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
path: "packages/path_provider/path_provider"

编译运行

运行 Flutter 项目,查看相关日志和运行界面,针对出现的问题再单独处理。

查看日志,可以在运行 Flutter 处的 IDE 调试控制台查看 Flutter 项目日志,可以使用 hdc hilog 命令或 DevEco 查看系统日志。

1. 学习路径应该是怎样的,需要掌握哪些技术才具备鸿蒙 Flutter 开发能力

1.1 学习和掌握 Flutter 开发技术,这块需要在Flutter社区学历 Flutter开发文档
1.2 学习鸿蒙基础概念和知识,推荐学习 鸿蒙生态应用开发白皮书, ArkTS 语言, ArkUI,
HarmonyOS 第一课

2. MatePad 应用适配问题

如果出现 app 在 Matepad 上无法全屏的问题,需要在 ohos/entry/main/module.json5中配置设备类型:

1
2
3
4
5
6
7
"deviceTypes": [
"phone",
"tablet",
"car",
"2in1",
'default'
],

需要增加 tablet 平板设备的适配。

如果在 Matepad 上运行时设备没有全屏,则可以需要删除 App 重装安装或者重启设备。因为相关的配置存在缓存,适配类型发生变化时,存在没有更新的问题,导致无法全屏。

3. 模拟器

模拟器与真机有较大差异,如果出现模拟器异常情况,优先确实真机是否正常运行,以排除模拟器自身问题。

4. debug 版本运行报错

Error while initializing the Dart VM

1
2
3
4
5
依次执行以下操作
设置环境变量 export FLUTTER_STORAGE_BASE_URL=https://flutter-ohos.obs.cn-south-1.myhuaweicloud.com
删除 /bin/cache 目录下的缓存
执行 flutter clean,清除项目编译缓存
运行 flutter run -d $DEVICE --debug

5. 如何更换 App 图标和名称

找到 ohos/AppScope/resources/base/media/app_icon.png,替换相应的文件

找到 ohos/AppScope/resources/base/element/string.json 文件,修改以下配置

1
2
3
4
5
6
7
8
{
"string": [
{
"name": "app_name",
"value": "中文名称"
}
]
}

6. flutter run 运行 App 报错,提示命令找不到

1
2
3
4
5
6
7
8
9
Launching lib/main.dart on 127.0.0.1:5555
start hap build..-e ERROR: node: /Applications/DevEco-Studio.app/Contents/tools/ohpm/bin/ohpm: line 7: node: commandnot found
-e ERROR: NODE_HOME: /Applications/DevEco-Studio.app/Contents/tools/ohpm/bin/ohpm: line 11: /node:
o such file or directory
-e ERROR: NODE_HOME: /Applications/DevEco-Studio.app/Contents/tools/ohpm/bin/ohpm: line 25: /bin/noc
e: No such file or directory
-e ERROR: Failed to find the executable 'node’ command, please check the following possible causes:e1. Node]s is not installed.e2.'node'command not added to PATH;
eand the 'NoDE HOME' variable is not set in the environment variables to match your NodeJsinstallation location.
ProcessException: The command failedCommand: ohpm clean

检查环境变量配置,配置成功后,检查是否已生效。通过 source ~/.zshrc 或重启命令行程序,甚至重启 IDE/系统,直至变量生效。

7.是否可以使用 Flutter 开发元服务

目前不行,元服务大小有限制 (2M),Flutter 构建产物过大,不符合这一要求

8. 如何自定义显示 DevEco 打开 ohos 后的项目名称

每个鸿蒙Flutter项目,用DevEco打开ohos工程后,默认显示的工程名称为 ohos,如果想自定义显示的工程名称,可以参考以下步骤:

在 ohos/.idea 目录下,新建一个 .name 文件,写入项目名称即可。

参考资料

SDK 安装

参考[鸿蒙Flutter实战:01-搭建开发环境]文章的说明,首先安装 Flutter SDK 3.22.0。

目前鸿蒙化Flutter SDK 3.22 还未正式发布,现在可以使用 https://gitee.com/harmonycommando_flutter/flutter 进行前期测试验证。

使用 FVM 进入 目录 ~/fvm/versions/, 克隆以上仓库。

1
git clone https://gitee.com/harmonycommando_flutter/flutter.git custom_3.22.0

接下来使用 fvm list 命令查看 SDK版本 列表。

1
2
3
4
5
6
7
┌───────────────┬─────────┬─────────────────┬──────────────┬──────────────┬────────┬───────┐
│ Version │ Channel │ Flutter Version │ Dart Version │ Release Date │ Global │ Local │
├───────────────┼─────────┼─────────────────┼──────────────┼──────────────┼────────┼───────┤
│ custom_3.22.0 │ │ Need setup │ │ │ │ │
├───────────────┼─────────┼─────────────────┼──────────────┼──────────────┼────────┼───────┤
│ 3.22.0 │ stable │ 3.22.0 │ 3.4.0 │ May 13, 2024 │ ● │ │
└───────────────┴─────────┴─────────────────┴──────────────┴──────────────┴────────┴───────┘

可以看到,SDK中出现了两个版本,其中使用命令 fvm global 3.22.0 将 官方的3.22.0 设置成了全局默认版本。鸿蒙化的 SDK 需要配置安装,我们稍后进入项目,执行安装。

项目配置

1.进入项目根目录,如果项目还未创建,则使用 flutter create 命令创建项目

1
flutter create my_app

2.在当前项目目录,设置使用的 Flutter SDK 版本

1
fvm use custom_3.22.0

此时会自动安装 sdk 版本,运行成功后如果再运行 fvm list, 可以看到 SDK 已经准备就绪。

1
2
3
4
5
┌───────────────┬─────────┬─────────────────┬──────────────┬──────────────┬────────┬───────┐
│ Version │ Channel │ Flutter Version │ Dart Version │ Release Date │ Global │ Local │
├───────────────┼─────────┼─────────────────┼──────────────┼──────────────┼────────┼───────┤
│ custom_3.22.0 │ │ 3.22.0-ohos │ 3.4.0 │ │ │ │
├───────────────┼─────────┼─────────────────┼──────────────┼──────────────┼────────┼───────┤

同时,配置命令执行完成后,将会在项目目录中创建 .fvm 目录,里面 flutter_sdk 会软连接到实际的 custom_3.22.0 SDK 目录。

查看 .vscode/settings.json 文件可以发现,自动创建了一条配置 flutter sdk 的项目:

1
"dart.flutterSdkPath": ".fvm/versions/custom_3.22.0"

如果项目使用了 melos, 则需要在 melos.yaml 文件的底部,添加以下配置,使得 melos 可以使用自定义的 flutter sdk

1
sdkPath: .fvm/versions/custom_3.22.0

3.如果项目已经创建,还未添加鸿蒙平台支持,则使用以下命令添加鸿蒙平台支持。

1
flutter create --platforms ohos .

其中,.代表当前目录。

目录结构类似如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
├── README.md
├── analysis_options.yaml
├── assets
├── build
├── env
├── lib
│ ├── config
│ └── main.dart
├── melos_ohos_app.iml
├── ohos
│ ├── AppScope
│ ├── build-profile.json5
│ ├── entry
│ ├── har
│ ├── hvigor
│ ├── hvigorfile.ts
│ ├── local.properties
│ ├── oh-package-lock.json5
│ ├── oh-package.json5
│ └── oh_modules
├── pubspec.lock
├── pubspec.yaml
└── pubspec_overrides.yaml

创建命令执行成功后,项目中会出现 ohos目录,这里面存放的就是鸿蒙平台的相关代码。

签名

1.在运行项目前,先对项目进行签名,否则在运行过程中会出现这样的错误

1
请通过DevEco Studio打开ohos工程后配置调试签名(File -> Project Structure -> Signing Configs 勾选Automatically generate signature)

2.用 DevEco 打开上面的 ohos 目录,注意不是项目目录,是项目下面的 ohos 鸿蒙目录,然后根据提示依次打开 File -> Project Structure -> Signing Configs, 点击自动签名即可。

3.签名成功后,文件 ohos/build-profile.json5 会自动更新,里面的字段 signingConfigs 出现相应的签名配置信息。

运行

运行 Flutter 项目,在项目根目录使用 fvm flutter run 或者在 IDE 中点击运行按钮

参考资料

SDK 选择前

  • ohos-3.7, 可以使用 X86 模拟器
  • ohos-3.22, 需要使用 ARM 架构 MAC 电脑的模拟器

创建项目

等开发环境搭建成功,使用 flutter create 命令创建项目

新项目

1
flutter create --platforms ohos ohos_app

旧项目增加鸿蒙平台支持

1
flutter create --platforms ohos .

签名

使用 DevEco 打开上面项目中的 ohos 目录,也就是我们的鸿蒙项目目录

打开 File -> Project Structure..., 点击 Siging Configs, 勾选 Automatically generate signature,

点击 Sign In, 登录华为账号,点击右下角 Apply, OK, 完成签名。

观察控制台会输出 Process finished with exit code 0的提示

1
2
3
4
5
> hvigor WARN: The current module 'ohos' has dependency which is not installed at its oh-package.json5.
> hvigor Finished :entry:init... after 1 ms
> hvigor Finished ::init... after 1 ms

Process finished with exit code 0

创建模拟器

1.打开 DevEco 中的 Device Manager(可以从右上角的运行按钮左侧下拉找到)

alt text

2.在右下角点击 + New Emulator, 弹出选择模拟器窗口,如果镜像还没有下载,方框处会出现下载按钮,先点击下载,下载完成后点击 Next 创建模拟器,再点击 Previous 创建成功

alt text

3.回到模拟器列表窗口,列表中出现了新建的模拟器,点击运行按钮, 模拟器运行成功。

运动 Flutter 项目

Vscode中右下角应当出现模拟器的设备,行如 127.0.0.1:5555(ohos-arm64), 如果没有出现参考注意事项中的说明 2 操作。

回到 Vscode 中的Flutter 项目,像普通的 flutter 项目那行,点击运行按钮。

注意事项

1. Flutter 运行 App,打包安装成功, 运行闪退 从以下方面检查:

1.1 如果是 X86电脑架构的模拟器,尝试删除 main.dart 中的 FloatingActionButton
1.2 如果 Flutter SDK 使用的 ohos-3.22, 尝试关闭 impeller 渲染方式,打开或创建文件 ohos/entry/src/main/resources/rawfile/buildinfo.json5, 增加以下配置

1
2
3
4
5
6
7
8
{
"string": [
{
"name": "enable_impeller",
"value": "true"
}
]
}

2.VSCode 中模拟器设备不显示

2.1 尝试使用 Deveco 打开项目的 ohos 目录(即鸿蒙项目文件),等待初始化分析成功
2.2 尝试重启 VSCode

3.使用 fvm 时,项目目录下 flutter –version 显示不正确,不是 ohos 版本

以次按以下的方式进行逐个尝试,直至成功。

3.1 尝试在 vscode 的命令行中运行 fvm use custom_3.22.0, 待命令创建 .vscode/setting.json 文件并在其中增加类似这样的配置

1
2
3
{
"dart.flutterSdkPath": ".fvm/versions/custom_3.22.0"
}

项目根目录中出现 .fvm/version/custom_3.22.0 这样的目录文件,项目根目录出现 .fvmrc 文件,其内容类似如下

1
2
3
{
"flutter": "custom_3.22.0"
}

3.2 尝试重启 VsCode 的命令行,或者重启整个 VsCode,待重新打开 VSCode 命令行以后,flutter --version 出现这样的输出

1
2
3
4
Flutter 3.22.0-ohos • channel oh-3.22.0 • https://gitee.com/harmonycommando_flutter/flutter.git
Framework • revision 85630b0330 (13 天前) • 2024-10-26 02:39:47 +0000
Engine • revision f6344b75dc
Tools • Dart 3.4.0 • DevTools 2.34.1

3.3 关闭全局 flutter 配置

~/.zshrc~/.bash_profile中,删除或者注释掉类似这样的配置,重启命令行/VSCode

1
#export PATH="/Users/zacksleo/flutter/bin:$PATH"

创建应用

新建项目

1.在 AppGalleryConnect,我的项目,添加项目。

alt text

新建APP ID

1.在 AppGalleryConnect,证书、APP ID 和 Profile 中。

alt text

选择所属项目

alt text

新建应用/元服务

在 APP ID 右侧,点击发布, 会弹出发布 HarmonyOS应用/元服务

alt text

按提示填写应用信息,上传应用图标,选择应用分类、标签,点击下一步

上传打包 App(见下方)。

填写应用信息,公司信息等。需要注意的是,App 需要提供软著,元服务则不需要。

打包签名

自动签名

如果是开发和测试,可以使用自动签名。(File -> Project Structure -> Signing Configs 勾选 Automatically generate signature)

如果是打包上架,则需要手动签名

打开Deveco,依次执行以下操作

  1. 在主菜单栏单击 Build > Generate Key and CSR

alt text

2.如果没有创建 Key Store,则点击 New 创建一个

alt text

选择需要存储的目录(文件扩展名使用.p12),输入密码8位以上的复杂密码,点击 OK。

3.设置 Key 的别名

alt text

点击 Next 进入下一步

alt text

设置 CSR 存储位置,注意文件名需要用 .csr 做为扩展名。

点击 Finished, 会创建 .p12密钥库文件以及 证书请求.csr 等文件。

alt text

登录 AppGallery Connect, 执行以下操作

1.点击 证书、App ID 和 Profile,在证书一栏,点击“新增证书”,上传上面创建的 CSR 文件,将生成 cer 文件,

点击下载按钮,将该证书文件保存,待 APP 打包使用。

alt text

2.证书、App ID 和 Profile 中的 Profile一栏,点击添加,创建 Profile 文件,选择刚才创建的证书

alt text

打包 App

在 Deveco中,打开 File -> Project Structure -> Signing Configs, 默认会有一个创建过的 default 签名配置,点击 + 添加按钮,

alt text

以此选择上面创建的 .p12文件、.p7b文件,以及下载的 .cer 文件,输入密码, 点击 Apply 生成配置。

alt text

点击红框处的 Product 🔘 按钮,Build model 选择 release, 同时 build-profile.json5 文件中配置使用哪个签名

1
2
3
4
5
6
"products": [
{
"name": "default",
"signingConfig": "release",
}
]

alt text

点击 Build-> Build Hap(s)/APP(s), 选择 Build APP(s), 开始 APP 打包。

打包成功后,会在项目根目录的 build/outputs/default 生成 .app文件,即为我们要在应用市场上传的文件包

常见问题

软件包解析失败,详细信息点击软件包管理列表中的错误码查看,请按照指导重新打包上传。
993,Profile文件非法

检查签名配置文件,是否使用是 release 配置

build-profile.json5

如下面的配置,这里添加了两个签名配置,一个用于开发调度,一个用于打包上架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"signingConfigs": [
{
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": "xx",
"storePassword": "xxx.cert",
"keyAlias": "debugKey",
"keyPassword": "xxx",
"profile": "xxx.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "xxx.p12"
}
},
{
"name": "release",
"type": "HarmonyOS",
"material": {
"certpath": "xx",
"storePassword": "xxx.cert",
"keyAlias": "release",
"keyPassword": "xxx",
"profile": "xxx.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "xxx.p12"
}
}
],
"products": [
{
"name": "default",
"signingConfig": "release",
"compatibleSdkVersion": "5.0.0(12)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],

在打包上架时,需要确保上面的 signingConfig 使用的是 name 为 release的签名配置

参考资料

-应用/服务签名

引言

在之前的文章鸿蒙Flutter实战:09-现有Flutter项目支持鸿蒙中,介绍了如何改造项目,适配鸿蒙平台。

文中讲述了整体的理念和思路,本文更进一步,结合可实操的项目代码,详细说明如何实施。

通过模块化、鸿蒙壳工程,结合 FVM 管理多版本 Flutter SDK,最终,保持原 Flutter 代码纯净,最小化修改,完成了鸿蒙化的适配示例。

本项目代码地址: https://gitee.com/zacks/flutter-ohos-demo

准备工作

1.安装 FVM 和 melos

安装 FVM,更多安装方式参考 fvm 官方文档

1
curl -fsSL https://fvm.app/install.sh | bash

安装melos

1
dart pub global activate melos

2.使用 FVM 安装 Flutter SDK

分别安装官方的3.22版本,以及鸿蒙社区的 3.22.0 版本

3.搭建 Flutter鸿蒙开发环境

参考文章《鸿蒙Flutter实战:01-搭建开发环境》

搭建项目架构

创建目录

1
2
# 创建项目目录
mkdir flutter-ohos-demo

设置使用的 Flutter SDK 版本
推荐在 VsCode 的命令行中执行以下命令,这将创建 .fvm 目录, .vscode/setting.json 文件, 和.fvmrc 文件

1
fvm use 3.22.0

初始化工作区间

创建目录,项目结构如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.
├── packages
│ ├── apps #该目录用于存放各端应用壳工程
│ ├── common #该目录用于存放公共库,均为纯 dart 代码,不依赖于 ios/android 等原生实现
│ │ ├── domains #领域对象,存放各类实体文件,如枚举/模型/vo/事件等
│ │ ├── extensions #存放扩展类文件,对于类的扩展方法/属性
│ │ ├── services #服务类:如请求服务/授权服务/缓存服务/平台调用服务/路由服务/工具类等
│ │ └── widgets #通用小型 widgets, 纯dart编写的 Flutter UI 组件
│ ├── components #封装组件库,可以依赖于第三方库/第三方插件,或依赖于 plugins中的插件
│ │ ├── image_uploader
│ │ └── player
│ ├── modules
│ │ ├── address
│ │ ├── home
│ │ ├── me
│ │ ├── message
│ │ ├── order
│ │ ├── shop
│ │ └── support
│ └── plugins #插件库,自行封装的插件库,依赖于原生平台(ios/android)的代码
│ └── printer
├── README.md
├── melos.yaml
└── pubspec.yaml

运行 melos bootstrap

1
melos bootstrap

开始编写代码

在各个 package 初始化代码,如在 packages/common/domains 目录运行

1
fvm flutter create --template package .

创建壳工程

新建两个壳工程,一个为 app,另外一个为 ohos_app

App 壳工程

进入 package/apps/app 目录, 创建 app 项目,该项目为一个 App 项目,用于各平台(ios/android/mac 等, 不包含鸿蒙)打包

1
fvm flutter create --template app --org com.shaohushuo.flutter app

增加依赖项

修改 pubspec.yaml,添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
path: '../../common/services'
domains:
path: '../../common/domains'
widgets:
path: '../../common/widgets'

home:
path: '../../modules/home'
me:
path: '../../modules/me'
support:
path: '../../modules/support'

安装依赖

运行以下命令,安装依赖

1
fvm flutter pub get

鸿蒙壳工程

切换鸿蒙 Flutter SDK

首先在 flutter-ohos-demo 项目根目录,将 Flutter 版本切换到鸿蒙化的版本

1
fvm use custom_3.22.0

SDK 变更以后,需要重启 IDE (或者 Dart:Restart Analysis Server),以便让 Flutter 插件重启

创建 ohos_app 项目

进入 packages/apps 目录,创建 ohos_app 项目

1
fvm flutter create --template app --platforms ohos --org com.shaohushuo.flutter ohos_app

增加依赖项

进入 packages/apps/ohos_app 目录中的 pubspec.yaml, 同样增加依赖项

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
path: '../../common/services'
domains:
path: '../../common/domains'
widgets:
path: '../../common/widgets'

home:
path: '../../modules/home'
me:
path: '../../modules/me'
support:
path: '../../modules/support'

三方库鸿蒙化适配

  1. 如果使用了 FVM,则编辑 pubspec.yaml 文件,增加以下配置,通过 dependency_overrides 来替换鸿蒙化的三方库,注意鸿蒙化的库与原库,保持版本统一
1
2
3
4
5
6
# 鸿蒙适配
dependency_overrides:
flutter_inappwebview:
git:
url: https://gitcode.com/openharmony-sig/flutter_inappwebview.git
path: "flutter_inappwebview"

编辑完运行 melos bootstrap, 这些更新 pubspec_overrides.yaml, 在里面添加相同的 dependency_overrides 内容。

  1. 如果没有使用 FVM,则直接编辑 pubspec_overrides.yaml 文件,没有则手动创建,添加以下内容:
1
2
3
4
5
6
# 鸿蒙适配
dependency_overrides:
flutter_inappwebview:
git:
url: https://gitcode.com/openharmony-sig/flutter_inappwebview.git
path: "flutter_inappwebview"

编辑完运行 flutter pub get 安装依赖。

以上两种方式执行成功后,观察 pubspec.lock 文件,可以发现,增加了类似 xxx_ohos 的插件依赖,本文中的例子为 flutter_inappwebview_ios

  1. 联合插件方式

除了上面使用 dependency_overrides 来配置鸿蒙适配库的两种方式以外,如果三方插件本身使用了联合插件的形式,也可以通过下面这种方式来添加鸿蒙平台的实现:

1
2
3
4
5
6
7
dependencies:

image_picker: ^1.1.2
image_picker_ohos:
git:
url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
path: "packages/image_picker/image_picker_ohos"

这种方式称作 “未整合的联合插件”, 在上面的配置中,
image_picker 是一个联合插件, 这里直接使用官方社区的最新版本,观察该插件的 pubspec.yaml 的文件,通过其结构可以发现联合插件的特点, 该插件的依赖项为:

1
2
3
4
5
dependencies:
image_picker_platform_interface: ^2.10.0
...
image_picker_android: ^0.8.7
image_picker_ios: ^0.8.8

image_picker_platform_interface 是一个抽象层,它定义了平台相关的接口,下面是各个平台的实现,通过拆分成包,以依赖的方式加载,那同样的原理,就可以再添加一条鸿蒙平台的实现包,就可以完成鸿蒙化适配, 也就是上面案例中的 image_picker_ohos

1
2
3
4
image_picker_ohos:
git:
url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
path: "packages/image_picker/image_picker_ohos"

运行调试

用 Deveco 打开apps/ohos_app/ohos 目录。

在 Deveco 左上角 打开 File -> Project Structure…, 点击 Siging Configs, 勾选 Automatically generate signature, 对鸿蒙项目签名。

在 ohos_app 目录下,使用 fvm flutter run,或者点击运行按钮,运行flutter项目。

注意事项

  1. melos.yaml 文件中的 sdkPath: .fvm/flutter_sdk 配置了 melos 使用的 flutter SDK 版本,即由FVM 配置的当前项目版本

  2. 每次切换 Flutter SDK 时,都会修改文件 .fvm/, vscode/settings.json 文件

  3. ohos_app/pubsec.yaml 中的 dependency_overrides, 仅添加需要鸿蒙化的三方库

  4. ohos-3.22 在 build 时,有的 har 包可能确实,建议保持 ohos-Flutter 版本最新,如果还是不行,可以考虑手动复制 har 包(使用 3.7 构建出来)

如何判断三方库是否需要鸿蒙化,简而言之,如果三方库由纯 Dart 实现,则不需要单独适配,直接使用;如果三方库依赖系统底层实现,则需要鸿蒙化适配。

三方库的适配情况,可以查询 Gitee/Github,或者查阅表格 Flutter三方库适配计划

  1. 已知插件删除问题,如果删除插件,可能需要在ohos里面手动修改代码,移除相关依赖

ohos/oh-package.json5

应用截图

首页 我的 帮助 播放器

插件使用示例

插件名 截图 使用示例
flutter_inappwebview 查看代码
video_player 查看代码
cached_network_image 查看代码
image_picker 查看代码

总结

  1. 通过 FVM 管理多个 Flutter SDK 版本,仅在鸿蒙调测打包时,切换到 ohos-flutter SDK
  2. 通过 apps 壳工程,将鸿蒙化适配的代码,尽量在 ohos_app 项目中完成。通过 pub 包管理的 dependency_overrides 配置,逐个替换鸿蒙化的三方库
  3. 通过 melos 管理多包项目,Flutter 项目进行模块化、组件化、插件化拆分,职责分离,平台抽象,不同平台组合打包,有效解决平台不一致问题

公众号

少湖说:少胡说,多观察。

关注公众号,加入交流群。

参考资料

Flutter 技术原理

Flutter 是一个主流的跨平台应用开发框架,基于 Dart 语言开发 UI 界面,它将描述界面的 Dart 代码直接编译成机器码,并使用渲染引擎调用 GPU/CPU 渲染。

渲染引擎的优势

使用自己的渲染引擎,这也是 Flutter 与其他跨平台框架最大的区别。

与 React Native 等高度依赖原生组件的框架不同,Flutter 摆脱了原生组件依赖,界面布局更加灵活,多端展示效果高度一致。由于渲染引擎自建,性能优化空间更大,这也是为什么Flutter 以流畅著称。

Impeller 渲染引擎由来

Flutter 的渲染引擎经历了多次迭代,早期全端使用 Skia, 后来为了解决 iOS 上着色器编译卡顿问题,Flutter 团队开发了新一代渲染引擎 Impeller。由于表现优异,Impeller 已经成为 Flutter 未来的发展方向。

渲染引擎将着色器编译成GPU指令,也就是二进制代码。

着色器是一种图形绘程序,它定义了如何绘制一个图形,比如颜色、形状、变换等。

Flutter在解决卡顿问题上,基于Skia做了多次努力和尝试,始终不尽人意,最终才有了Impeller。

Impeller 的设计目标包括: 消除首次卡顿、降低帧渲染驱动开销、利用现代 GPU 并行渲染能力

Impeller 与 Vulkan

Vulkan 是 OpenGL 推出的下一代图形 API,在安卓上,Flutter Impeller 调用 Vulkan 实现界面渲染。

  1. Impeller 实现了常用的着色器,支持参数化,通过预编译色器来避免编译卡顿问题
  2. 分层架构简化了渲染过程,每一层基于下层能力执行特定功能,高效且易用于维护更新
  3. 绘制命令容易聚合,易于拆分和并行
  4. 渲染设计与图形API解耦

Impeller 鸿蒙化

Impeller 的鸿蒙化基于 Vulkan, 通过 ArkUI 提供的 XComponent 组件承载 Flutter 视图。

与其他平台一样,通过 Method Channel , Dart 调用 ArkTS 来实现原生能力的调用。

XComponent 如何承载 Flutter 视图

通过 XComponet 获取到系统底层的 OHNativeWindow 实例, 这个就是鸿蒙的原生窗口,通过鸿蒙提供的扩展 VK_OHOS_surface, 将这个窗口转成一个 Vulkan 中的 VKSurface, 进而通过 VKSwapchain 实现了窗口绘制。

外接纹理:系统产生的图形图像如何嵌入 Flutter 显示

借助 XComponent,Flutter 绘制的界面可以显示在鸿蒙中。那么如果是非 Flutter 绘制的界面,如系统相机、视频等,如何嵌入到 Flutter 界面中呢?这就涉及到外接纹理了。

以相机为例,如果在 Flutter 中使用相机,当然最基础的可以通过 Method Channel 通信,将数据传递过来,但这个过程显然非常耗时,性能堪忧。另外一种方案是通过挖孔,叠加系统页面和 Flutter 画面,但这可能带来两套界面的操作、动画不一致问题。鸿蒙化采用了难度更高的数据导入方案,即将外部数据导入到 Flutter,将这些数据以纹理组件形式绘制。

鸿蒙化外接纹理涉及编码数据传输,如何解决性能问题

NativeBuffer 由鸿蒙提供, 通过它可以实现内存共享。那么外部导入的数据,通过 NativeBuffer,可以直接让 GPU 使用,避免了因数据拷贝造成的性能损失。

无论是 VKImage, 还是 GLTexture,都可以使用 NativeBuffer。

如何解决花屏问题

与安卓不同,Impeller 鸿蒙化方案采用了 GPU 硬件级的同步机制,保护数据读取,防止数据竞争,避免图像的花屏,通过 CPU 解耦,减少了空转时间,提高了性能。

Flutter 引擎侧不需要等待 Buffer 读写完成再调用绘制能力,只要保证 GPU 在绘制队列时,涉及 Buffer 数据的信号量状态为已读取即可,减少了 CPU 空等时间造成的性能损失。

渲染管线预加载

Impeller 通过预编译着色器避免了 Skia 中的运行时编译,但启动时需要加载这些着色器(也就是加载渲染管线),这就会出现明显的白屏时间。要解决这一问题,那就需要预加载渲染管线。

鸿蒙 Flutter 在运行时,首先创建 Dart 虚拟机解析 UI,在这个过程中同步进行渲染管线加载,从而实现首帧快速上屏,时延降低 50ms。

这部分不需要开发者操作,SDK 会自动完成。

混合开发加载优化:页面预加载

从原生 ArkUI 页面跳转到 Fluter 页面,需要先初始化 Flutter 引擎(这个过程耗时较长),再渲染首帧页面,这就会出现明显卡顿。

开发者可以提前手动调用 Flutter 引擎初始化 API,来解决这一卡顿问题。例如用户在触摸发生时,同步初始化 Flutter 引擎,等到用户抬手以后,就可以立即跳转到 Flutter 页面,整个过程会更加流程。

性能测试

通过预加载,可以节省一半的跳转时间。与 Skia 方案相比,Impeller 的转场流畅度提升显著。

与 Skia 方案相比,Impeller 方案在性能上表现更好。

鸿蒙 Flutter 的未来

鸿蒙 Flutter 适配团华为主导,计划每年推出 1-2 个比较大的版本,这两个大版本通过 fork 官方当时的主要版本来实现。至于能否将鸿蒙适配的部分合并到 Flutter 官方,还要看 Google 的态度。

结合前段时间 Flutter 社区版本 Flock 的推出,笔者持乐观态度。虽然 Google 在 Flutter 更新这方面进度缓慢,但社区版本带来不少想象力。多个 SDK 版本并存并不意味着分裂,竞争带来更多的活力。这点可以参考 Java,除了甲骨文主导的 OracleJDK, 还有 OpenJDK, AdoptOpenJDK 等十几种社区版本。

除了已有的插件开发方式,鸿蒙 Flutter 计划推出一种成本更低的方案,即通过一种统一接口描述,自动生成各端调用代码,省去开发者的编码工作。

总结

Flutter 作为一种流行的跨平台框架,支持鸿蒙是大势所趋。华为躬身入局,为 Flutter 社区带来了强劲动力。

从目前各方反馈来看,Flutter 应该是仅次于 ArkTs 的最佳适配方案。
不论是官方、还是开源社区、亦或是广大的开发者,都对 Flutter 有着强烈的诉求。
HarmonyOS 希望更多应用尽快适配鸿蒙,开发者或者是厂商,也希望以更低的成本最快上架;ArkTS 仍然有不少需要改进之处,就拿热重载一项与之对比,Flutter 不论从易用性、稳定性和成熟度已经遥遥领先。

对于平台独有的特性,如鸿蒙中的各种 Picker 组件、免权限按钮等,这与在其他平台上一样,是属于原生语言独有的优势所在。

虽然 Flutter 鸿蒙化已经初见成效,不少三方 Flutter 应用也快速适配上架,但生态建设仍需诸多时间,三方库还需要共建共享。

鸿蒙未来可期,Flutter 的鸿蒙化,为这个沉寂许久的框架,带来了新鲜血液。

参考资料

本文讲述如何通过 Flutter 开发鸿蒙原生应用。整个过程结合往期文章、实战经验、流程优化,体验丝滑、无痛。

无痛搭建开发环境

为了减少疼痛,这里使用全局唯一的 Flutter 版本开发。高阶用法可以参看往期同系列文章。

硬件准备

一台 Mac,一部 Mate60 Pro,两台显示器。

鸿蒙 Flutter SDK 开发人员爱用 Mac,使用相同设备(优先选择 Arm 版 Mac,X86 也可以,系统不要太老)无忧。

审核人员爱用 Mate60 系列,选择同款无忧。

显示器两台,左侧放别人的代码,右侧是自己的,方便参考(复制粘贴)。

环境准备

下载 DeEco

进入华为开发者联盟网站,https://developer.huawei.com/consumer/cn/download/,根据电脑机型点击下载。

下载 Flutter SDK

1
2
3
4
5
# 创建目录 ~/.fvm/versions
mkdir -p ~/.fvm/versions

# 克隆 Flutter SDK
git clone https://gitee.com/harmonycommando_flutter/flutter.git custom_3.22.0

配置环境变量

打开 ~/.bash_profile,增加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
# Flutter Mirror
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

# HarmonyOS SDK
export TOOL_HOME=/Applications/DevEco-Studio.app/Contents/
export DEVECO_SDK_HOME=$TOOL_HOME/sdk # command-line-tools/sdk
export PATH=$TOOL_HOME/tools/ohpm/bin:$PATH # command-line-tools/ohpm/bin
export PATH=$TOOL_HOME/tools/hvigor/bin:$PATH # command-line-tools/hvigor/bin
export PATH=$TOOL_HOME/tools/node/bin:$PATH # command-line-tools/tool/node/bin

export PATH="~/.fvm/versions/custom_3.22.0/bin:$PATH"

配置完成以后,关闭命令行工具,并重新打开,使之生效。使用 flutter doctor 命令查看是否有 3.22.0-ohos 字样。

创建项目

使用以下命令创建项目

1
flutter create --platforms ohos .

配置自动签名

使用 Deveco 打开项目,Mate60 Pro 手机连上电脑(必须)。

打开 File -> Project Structure -> Signing Configs 勾选 Automatically generate signature

点击 Apply 应用,OK 完成签名。此时可关闭 DevEco。

alt text

运行项目

  1. 使用 Flutter run 命令,或者在 IDE 中,点击运行按钮
1
2
# 查看设备编号
futter devices

出现以下类似输出

1
2
3
4
Found 3 connected devices:
FMR0224904009635 (mobile) • FMR0224904009635 • ohos-arm64 • Ohos OpenHarmony-5.0.1.115 (API 13)
macOS (desktop) • macos • darwin-x64 • macOS 14.6.1 23G93 darwin-x64
Chrome (web) • chrome • web-javascript • Google Chrome 131.0.6778.108

找到鸿蒙设备的 ID,如上所示为 FMR0224904009635。

1
2
# 运行
flutter run -d FMR0224904009635
  1. 在 IDE 中,点击运行按钮,以下是 VsCode 中的入口

确保安装了 Code Runner 插件

alt text

参考资料

在上期文章中,我们体验了无痛使用 Flutter 快速启动开发的过程,本期重点聚焦上架审核流程。

alt text

无痛打包

提前准备好生产证书。

具体步骤见“鸿蒙Flutter实战:13-鸿蒙应用打包上架流程”,在AGC平台证书栏,“新增证书”成功后,点击现在,得到一个xx.cer文件(数字证书文件);在Profile一栏,添加完之后,点击现在可以得到一个xx.p7b文件(Profile文件)。这两个文件将会在手动签名时使用。

使用最新的 IDE 自动上传功能。

DevEco Studio菜单栏,点击Build > Upload Product,登录开发者账号,进入上传界面。

alt text

选择 Generate app package and upload it to AppGallery Connect for test and publish。

无痛审核

审核实际上是一直非常重要的过程,不要以为开发完、打包上传就结束了,App Gallery 的审核十分严格,提前做好心理准备。

对于新应用,首次上架相对友好宽松,但也要明确没有明显问题,符合大致要求,不要存在侥幸心理。

名称

名字要确保唯一,提前在商城搜索,另外不要使用容易误解、太通用的的名称,如“文件管理”,“二维码生成”,建议增加品牌前缀,如有商标版权更加无痛。

图标

按规范设计,不要和系统图标相似,不要和其他应用雷同。

备案

提前对域名、App进行备案,应用名称、包名确保一一对应。

软著

使用电子软著,或者直接找中介全包,只需要提供名字等基础信息即可,全程无痛。

软著中的名称或简称要与App名称对应。

充分测试

确保充分测试,如果分发平台选择了平板,确保在平板上测试。

录制测试视频

审核人员测试很仔细,会帮你找bug,所以有测试视频也挺重要。
如果不具备平板测试条件,建议后期更新版本再勾选。上架只关注手机更无痛。

备注说明

如果应用有些特殊的设计理念,需要备注说明。不要指望审核人员能轻松理解你的意图。

测试账号

如果设计登录功能,最好提供一个可以正常使用的、甚至是有数据的测试账号,让审核人员也无痛。

提交时间

提前提交,避开周六。建议提交时间为周日-周四的每个晚上 。提交以后不要撤回,不然要重新排队。

参考资料

0%