Flutter与OpenHarmony跨平台密码加密集成实战:架构设计与HUKS应用
1. 项目概述:当Flutter遇见OpenHarmony,安全能力如何“跨”过去?
最近在折腾一个挺有意思的活儿:把一个Flutter应用适配到OpenHarmony上,并且要把原有的密码加密能力给集成进去。听起来像是把两个不同“星球”的技术拉到一起开会,一个是从Google来的跨平台UI框架,另一个是咱们国内开源的智能终端操作系统。这活儿干下来,感触最深的就是“跨平台”这三个字,说起来轻巧,做起来全是细节,尤其是在安全这种敏感领域。密码加密,这可不是简单的文本处理,它涉及到密钥管理、算法选型、平台适配,任何一个环节掉链子,都可能让“安全”变成“隐患”。如果你也在做类似的事情,比如想把Flutter应用上架到OpenHarmony的应用市场,或者需要为你的OpenHarmony设备开发一个带安全登录功能的Flutter应用,那这篇从一线踩坑填坑中总结出来的经验,或许能帮你省下不少折腾的时间。
简单来说,这个项目的核心目标就两个:第一,让Flutter应用能在OpenHarmony标准系统上顺畅跑起来;第二,确保应用中的密码等敏感信息,在存储和传输过程中是经过可靠加密的,而不是“裸奔”。这不仅仅是调用一个加密库那么简单,它涉及到从Flutter的Dart层,到与原生平台(这里是OpenHarmony)的通信桥接,再到最终在OpenHarmony的Native层(可能是C/C++或ArkTS)完成实际的加密运算。整个过程,就像是在为两个说不同方言的专家做翻译和协调工作。
2. 整体架构设计与技术选型背后的考量
当我们决定把Flutter应用部署到OpenHarmony,并集成原生密码加密能力时,首先得想清楚整个技术栈怎么搭。这不像在Android或iOS上,有现成且成熟的 flutter 插件生态,很多问题社区都踩过坑了。在OpenHarmony这块新大陆上,我们更多时候得自己当“拓荒者”。
2.1 为什么选择“桥接原生”而非纯Dart实现?
最直接的问题是:加密,到底在哪一层做?一种思路是全部用Dart实现,找一些纯Dart写的加密库。这听起来很“跨平台”,一份代码到处运行。但我实际评估后,很快否定了这个方案,原因有三:
-
性能与安全性 :加解密运算,尤其是非对称加密、哈希运算等,是计算密集型操作。纯Dart代码的执行效率,在复杂运算上通常不如利用操作系统底层原生库(如C/C++实现的开源库)来得高效。更重要的是,密码学算法的正确实现非常复杂,细微的错误就会导致严重的安全漏洞。使用经过广泛审计和长时间验证的原生库(如OpenSSL、BoringSSL,或OpenHarmony自身的密码学库),远比使用一个未经大规模实战检验的Dart移植版要可靠得多。
-
密钥安全存储 :加密的核心是密钥。密钥本身的安全存储,往往需要依赖操作系统提供的安全环境,比如Android的KeyStore、iOS的Keychain。在OpenHarmony上,同样有类似的 HUKS(Hardware Unified Key Store) 硬件密钥库服务。这是纯Dart环境根本无法触及的领域。我们必须通过平台通道(Platform Channel)调用OpenHarmony的原生API,才能把密钥存到最安全的地方。
-
合规与认证 :在一些对安全性要求极高的行业(如金融、政务),使用的加密模块可能需要符合特定的国家标准或行业规范。OpenHarmony作为面向全场景的国产操作系统,其内置的密码学服务很可能已经针对国密算法(如SM2, SM3, SM4)做了深度集成和优化,并满足相关合规要求。直接调用这些服务,是最稳妥的路径。
所以,结论很明确: 加密的核心逻辑必须下沉到OpenHarmony原生侧实现 。Flutter的Dart层只负责业务逻辑的触发(例如,用户点击“登录”时传入密码明文)和结果的接收(拿到加密后的密文或哈希值)。
2.2 通信桥梁:Platform Channel 还是 FFI?
确定了原生实现,下一个问题是怎么通信。Flutter提供了两种主要方式与原生代码交互: Platform Channel 和 FFI(Foreign Function Interface) 。
- Platform Channel :这是Flutter官方主推的异步消息传递机制。Dart端发送一个消息(包含方法和参数)到“通道”,原生端监听这个通道,收到消息后执行对应的方法,然后将结果异步返回给Dart端。它的优点是成熟、稳定、文档丰富,适合大多数“请求-响应”式的交互。
- FFI :允许Dart代码直接调用C语言风格的API(动态库)。这更像是一种“函数直接调用”,延迟更低,适合对性能要求极高的场景。
在这个密码加密项目中,我选择了 Platform Channel 。原因如下:
- 开发复杂度 :FFI需要你手动管理C数据结构和内存,在Dart和C之间进行类型转换,调试起来更复杂。而Platform Channel使用标准的消息编解码(如JSON),上手更快。
- 安全性 :异步的Channel机制天然避免了在Dart侧长时间阻塞UI线程,而加密运算可能在原生侧耗时,异步处理更合理。
- 生态兼容 :OpenHarmony的应用开发,目前主推ArkTS/JS。通过Platform Channel,我们可以用ArkTS来编写原生侧的加密模块,与OpenHarmony的API结合更顺畅。虽然FFI理论上也能调用C库,但中间还需要一层Native API(NAPI)的封装,链路更长。
因此,我们的架构就清晰了: Flutter (Dart) <--(Platform Channel)--> OpenHarmony (ArkTS/JS) <--> OpenHarmony 密码学服务 (HUKS等) 。
2.3 加密方案选型:对称、非对称还是哈希?
这不是一个二选一的问题,而是一个组合拳。根据密码使用的不同场景,我们需要不同的加密策略:
-
本地存储密码的哈希(Hash) :这是最基本的原则。用户的密码 绝对不应该 以明文形式存储在本地数据库或文件中。正确的做法是存储密码的哈希值(例如使用SHA-256或SM3)。当用户登录时,将输入的密码再次进行哈希运算,与存储的哈希值比对。为了抵御彩虹表攻击,必须 加盐(Salt) 。这个盐值应该是每个用户独立、随机生成的,并和哈希值一起存储。
注意 :哈希是单向的,无法解密。这用于验证密码正确性,而不是用于“解密”出原始密码。
-
网络传输加密(非对称/对称结合) :如果密码需要发送到服务器,必须使用HTTPS(TLS)来保证传输通道的安全。在客户端,我们通常不直接加密密码本身,而是依赖TLS。但在一些特殊协议中,可能会用到非对称加密(如RSA或SM2)来加密一个临时生成的对称密钥(会话密钥)。
-
本地敏感配置加密(对称加密) :应用内一些其他的敏感配置信息(如API Token的加密存储),可以使用对称加密算法(如AES或SM4)。这里的关键是 密钥从哪里来 ?绝不能硬编码在代码里。最佳实践是,密钥本身由用户密码派生的密钥加密后存储,或者直接使用系统密钥库(HUKS)来生成和保管加密密钥。
在我们的集成项目中,重点会放在 场景1(密码哈希) 和 场景3(利用HUKS进行密钥管理) 上,因为这是移动端应用最普遍、最核心的安全需求。
3. 实操步骤:搭建Flutter-OpenHarmony加密桥梁
理论说完了,我们动手搭起来。这里我会假设你已经有一个基本的Flutter项目,并且OpenHarmony的开发环境(DevEco Studio)也已经就绪。
3.1 第一步:创建Flutter插件模块
我们不直接把原生代码写在主工程里,而是创建一个Flutter插件(Plugin),这样加密能力可以独立维护和复用。
# 在项目根目录外,创建插件
flutter create --template=plugin --platforms=android,ios,ohos maaath_password_encryption
cd maaath_password_encryption
这个命令会创建一个插件工程结构,其中 lib/ 下是Dart代码, android/ 、 ios/ 和** ohos/ ** 分别是各平台的原生实现目录。OpenHarmony(ohos)平台的支持需要特定版本的Flutter SDK和模板,确保你的Flutter环境已支持OpenHarmony。
3.2 第二步:实现Dart层接口(Channel调用方)
在 lib/ 目录下,我们定义插件的对外接口。首先编辑 lib/maaath_password_encryption.dart :
import 'dart:async';
import 'package:flutter/services.dart';
class MaaathPasswordEncryption {
// 单例模式,方便全局调用
static final MaaathPasswordEncryption _instance = MaaathPasswordEncryption._internal();
factory MaaathPasswordEncryption() => _instance;
MaaathPasswordEncryption._internal();
// 定义与原生端通信的Channel,名称必须唯一,两端保持一致
static const MethodChannel _channel = MethodChannel('maaath_password_encryption');
// 1. 哈希密码(加盐)
// 参数:password - 明文密码
// 返回:一个Map,包含 'hash' (Base64编码的哈希值) 和 'salt' (Base64编码的盐值)
// 注意:首次调用时生成新盐,验证时需传入之前存储的盐
Future<Map<String, String>> hashPassword(String password, {String? existingSalt}) async {
try {
final Map<String, dynamic> arguments = {'password': password};
if (existingSalt != null) {
arguments['salt'] = existingSalt;
}
final Map<dynamic, dynamic> result = await _channel.invokeMethod('hashPassword', arguments);
// 将动态类型转换为明确的String类型返回
return {
'hash': result['hash'] as String,
'salt': result['salt'] as String,
};
} on PlatformException catch (e) {
print("调用哈希方法失败: ${e.message}");
rethrow; // 或者返回一个包含错误信息的Map,由业务层处理
}
}
// 2. 使用系统密钥库加密一段数据
Future<String> encryptWithKeyStore(String plaintext, String keyAlias) async {
try {
final String result = await _channel.invokeMethod('encryptWithKeyStore', {
'plaintext': plaintext,
'keyAlias': keyAlias,
});
return result; // 返回Base64编码的密文
} on PlatformException catch (e) {
print("加密失败: ${e.message}");
rethrow;
}
}
// 3. 使用系统密钥库解密
Future<String> decryptWithKeyStore(String ciphertext, String keyAlias) async {
try {
final String result = await _channel.invokeMethod('decryptWithKeyStore', {
'ciphertext': ciphertext,
'keyAlias': keyAlias,
});
return result; // 返回解密后的明文
} on PlatformException catch (e) {
print("解密失败: ${e.message}");
rethrow;
}
}
}
Dart层的代码相对清晰,主要就是定义 MethodChannel 和几个异步方法,它们负责将调用“打包”成消息发送给原生端。
3.3 第三步:实现OpenHarmony原生层(ArkTS)
这是最关键的一步。我们进入 ohos/ 目录。OpenHarmony插件的原生代码主要放在 ohos/src/main/ets/ 下。
首先,我们需要修改 ohos/src/main/ets/MaaathPasswordEncryption.ts (或.js),这是Channel的接收和处理方:
import crypto from '@ohos.security.crypto';
import util from '@ohos.util';
import huks from '@ohos.security.huks';
// 1. 定义Flutter Plugin的入口类,实现Channel方法分发
export class MaaathPasswordEncryption {
private methodChannel: any;
constructor() {
// 注意:这里的Channel名称必须与Dart端完全一致
this.methodChannel = new MethodChannel('maaath_password_encryption');
this._registerMethods();
}
private _registerMethods(): void {
this.methodChannel.onMethodCall = (method: string, args: Record<string, any>, callback: Function) => {
switch (method) {
case 'hashPassword':
this._handleHashPassword(args, callback);
break;
case 'encryptWithKeyStore':
this._handleEncryptWithKeyStore(args, callback);
break;
case 'decryptWithKeyStore':
this._handleDecryptWithKeyStore(args, callback);
break;
default:
callback(null, `未实现的方法: ${method}`);
}
};
}
// 2. 处理密码哈希
private async _handleHashPassword(args: Record<string, any>, callback: Function): Promise<void> {
const password: string = args.password;
let saltBase64: string | undefined = args.salt;
let salt: Uint8Array;
if (saltBase64) {
// 如果传入了盐,则使用传入的盐(验证场景)
salt = this._base64ToUint8Array(saltBase64);
} else {
// 否则生成新的随机盐(注册场景)
salt = crypto.createRandomBytes(32); // 生成32字节随机盐
}
// 将密码字符串转换为Uint8Array
const passwordBytes = new util.TextEncoder().encode(password);
// 拼接盐和密码(常见做法:salt + password)
const dataToHash = new Uint8Array(salt.length + passwordBytes.length);
dataToHash.set(salt, 0);
dataToHash.set(passwordBytes, salt.length);
// 使用SM3算法进行哈希(OpenHarmony内置支持国密)
const hashResult = await crypto.hash(crypto.Hash.SM3, dataToHash.buffer);
// 将结果转换为Base64字符串返回
const hashBase64 = this._arrayBufferToBase64(hashResult);
const saltBase64Result = this._arrayBufferToBase64(salt.buffer);
callback(null, {
hash: hashBase64,
salt: saltBase64Result
});
}
// 3. 处理使用HUKS加密
private async _handleEncryptWithKeyStore(args: Record<string, any>, callback: Function): Promise<void> {
const plaintext: string = args.plaintext;
const keyAlias: string = args.keyAlias;
// 这里简化流程,实际需要:
// a. 检查密钥是否存在,不存在则生成(需用户认证)
// b. 使用HUKS进行加密操作
// 以下为示例伪代码逻辑
try {
// 假设我们已经有一个初始化好的HUKS密钥
const cipherText = await this._huksEncrypt(keyAlias, plaintext);
callback(null, cipherText);
} catch (error) {
callback(`加密错误: ${error.message}`, null);
}
}
// 4. 处理使用HUKS解密
private async _handleDecryptWithKeyStore(args: Record<string, any>, callback: Function): Promise<void> {
const ciphertext: string = args.ciphertext;
const keyAlias: string = args.keyAlias;
try {
const plainText = await this._huksDecrypt(keyAlias, ciphertext);
callback(null, plainText);
} catch (error) {
callback(`解密错误: ${error.message}`, null);
}
}
// -------------------- 工具函数 --------------------
private _arrayBufferToBase64(buffer: ArrayBuffer): string {
// OpenHarmony util.base64Encode 用法
const uint8Array = new Uint8Array(buffer);
return util.base64Encode(uint8Array);
}
private _base64ToUint8Array(base64: string): Uint8Array {
return util.base64Decode(base64);
}
// -------------------- HUKS相关函数(示例框架)--------------------
private async _huksEncrypt(keyAlias: string, data: string): Promise<string> {
// 1. 构建加密参数
const properties: huks.HuksOptions = {
properties: [
{ tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
{ tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
{ tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT },
{ tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 },
{ tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_GCM }, // 使用GCM等认证模式更安全
{ tag: huks.HuksTag.HUKS_TAG_DIGEST, value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256 },
]
};
// 2. 初始化(Init)
const handle = await huks.init(keyAlias, properties);
// 3. 更新(Update)和结束(Finish)加密过程,处理数据
// ... 此处省略具体的分段加密逻辑,需将data转换为Uint8Array进行处理
// 4. 最终返回Base64编码的密文和可能的认证标签(GCM模式)
return 'encryptedBase64String';
}
private async _huksDecrypt(keyAlias: string, cipherTextBase64: string): Promise<string> {
// 解密流程与加密对称,参数中的 PURPOSE 改为 HUKS_KEY_PURPOSE_DECRYPT
// ...
return 'decryptedPlainText';
}
}
// 5. 插件注册
export default class MaaathPasswordEncryptionPlugin {
static register(): void {
new MaaathPasswordEncryption();
}
}
上面的ArkTS代码是一个高度简化的示例,重点展示了Channel通信、使用 @ohos.security.crypto 进行哈希、以及调用HUKS的框架。真实的HUKS操作涉及密钥生命周期管理(生成、导入、使用、删除)、分段加解密等复杂步骤,需要仔细阅读OpenHarmony的官方安全文档。
3.4 第四步:在Flutter主工程中集成插件
回到你的Flutter主项目,在 pubspec.yaml 中通过路径依赖引入我们刚写的插件:
dependencies:
flutter:
sdk: flutter
maaath_password_encryption:
path: ../path/to/maaath_password_encryption # 指向插件目录
然后执行 flutter pub get 。之后,你就可以在Dart代码中像下面这样使用了:
import 'package:maaath_password_encryption/maaath_password_encryption.dart';
// 用户注册时,哈希并存储密码
Future<void> registerUser(String username, String password) async {
final crypto = MaaathPasswordEncryption();
final result = await crypto.hashPassword(password);
// result['hash'] 和 result['salt'] 需要安全地存储到本地数据库或服务器
await _saveToLocalDB(username, result['hash'], result['salt']);
print('密码哈希完成,盐值: ${result['salt']}');
}
// 用户登录时,验证密码
Future<bool> verifyPassword(String username, String inputPassword) async {
// 1. 从本地取出之前存储的哈希值和盐值
final (storedHash, storedSalt) = await _getFromLocalDB(username);
// 2. 使用存储的盐值对输入密码进行哈希
final crypto = MaaathPasswordEncryption();
final result = await crypto.hashPassword(inputPassword, existingSalt: storedSalt);
// 3. 比较新生成的哈希值与存储的哈希值是否一致
return result['hash'] == storedHash;
}
4. 核心难点解析与避坑指南
集成过程看似步骤明确,但实际开发中会遇到不少“坑”。下面是我总结的几个关键难点和解决方案。
4.1 难点一:Flutter与OpenHarmony版本兼容性问题
这是最大的“玄学”问题。Flutter对OpenHarmony的支持仍在快速演进中,不同版本的Flutter SDK可能对应不同的OpenHarmony API版本和模板。
- 问题表现 :
flutter create --template=plugin --platforms=ohos命令执行失败,或者生成的ohos目录结构不对,缺少关键文件。 - 排查与解决 :
- 确认Flutter渠道和版本 :使用
flutter doctor -v查看你的Flutter版本。目前对OpenHarmony支持较好的通常是Flutter的特定版本或Master渠道。你需要查阅Flutter官方或OpenHarmony社区的最新文档,确认兼容矩阵。 - 检查OpenHarmony SDK路径 :确保DevEco Studio中安装的OpenHarmony SDK路径被正确配置。有时需要在
ohos目录下的build.gradle或ohos插件配置文件中手动指定SDK路径。 - 使用FVM管理多版本Flutter :强烈推荐使用
fvm(Flutter Version Management)来管理多个Flutter版本。你可以为OpenHarmony项目单独配置一个兼容的Flutter版本,而不会影响其他项目。# 安装fvm dart pub global activate fvm # 为项目指定一个Flutter版本(例如某个支持OH的commit) fvm use <version_or_channel>
- 确认Flutter渠道和版本 :使用
4.2 难点二:Platform Channel 数据类型映射
Dart和ArkTS/JS之间的数据类型并非一一对应,错误的类型会导致通信失败。
- 常见错误 :Dart端发送了一个
int,原生端期望的是string,或者Map/List的结构不一致。 - 最佳实践 :
- 使用简单、明确的数据结构 :尽量使用
String,int,bool,List<dynamic>,Map<String, dynamic>这些基本类型。复杂对象先序列化为JSON字符串再传递。 - 在两端定义协议文档 :哪怕只是注释,也要明确每个方法的参数名、类型、返回值结构。例如:
// Dart端协议 // 方法名: 'hashPassword' // 参数: {'password': String, 'salt': String?} // salt可选 // 返回: {'hash': String, 'salt': String} - 做好错误处理 :如前面Dart代码所示,一定要用
try-catch包裹invokeMethod调用,并处理PlatformException。原生端回调时,第一个参数是错误信息(成功时为null),第二个参数是结果,这个约定不能错。
- 使用简单、明确的数据结构 :尽量使用
4.3 难点三:OpenHarmony HUKS API的复杂性
HUKS功能强大,但API调用链较长,涉及异步操作和大量的参数配置,容易出错。
- 关键步骤 :一次完整的HUKS加密通常包括
generateKey(或importKey) ->init->update(可能多次)->finish。解密同理。 - 避坑技巧 :
- 仔细阅读官方示例 :OpenHarmony的
@ohos.security.huks文档会提供关键示例代码。先从示例代码跑通最简单的流程开始。 - 关注
HuksTag:密钥属性(算法、长度、用途、填充模式等)都通过HuksTag来设置。一个常见的错误是PURPOSE没配对,比如生成密钥时设置了ENCRYPT,解密时却用同一个别名去INIT,会失败。用于解密的密钥其PURPOSE必须包含DECRYPT。 - 处理异步与Promise :HUKS的API返回的是Promise,务必使用
async/await或.then().catch()正确处理异步和错误。 - 密钥别名(KeyAlias)管理 :密钥别名是访问密钥的句柄。要设计好别名的命名规则,防止冲突。应用卸载后,密钥库中对应的密钥是否清除,也取决于生成时的参数。
- 仔细阅读官方示例 :OpenHarmony的
4.4 难点四:调试与日志输出
跨层调试比较麻烦,你需要清楚问题出在Dart层、Channel通信层还是原生层。
- 分层调试法 :
- Dart层 :使用
print或debugPrint,在Flutter DevTools的Console里查看。 - Channel通信层 :在原生端(ArkTS)的方法入口处打印接收到的参数,确认数据是否正确送达。同样,在回调前打印要返回的数据。
- 原生层 :OpenHarmony应用可以使用
hilog命令输出日志到控制台。在ArkTS中可以使用console.log()或Logger模块。import hilog from '@ohos.hilog'; hilog.info(0x0000, 'MyTag', '加密方法被调用,参数: %{public}s', JSON.stringify(args)); - 使用DevEco Studio的调试器 :可以给ArkTS代码打断点,这是最有效的调试原生逻辑的方法。
- Dart层 :使用
5. 进阶思考与性能优化
当基础功能跑通后,我们可以考虑一些更深入的问题来提升安全性、用户体验和性能。
5.1 密钥管理策略:存哪?怎么存?
- 场景一:用户密码派生的密钥 。可以使用PBKDF2、Scrypt等算法,将用户密码和固定的应用唯一盐(App Salt)进行多次哈希迭代,生成一个加密密钥。这个密钥用于加密本地其他敏感数据。 切记 :这个派生过程应该在原生侧完成,避免密码在Channel中频繁传递。
- 场景二:设备绑定的密钥 。使用HUKS生成一个设备硬件绑定的密钥(设置
HUKS_TAG_ATTESTATION_ID等标签)。即使应用数据被完整拷贝到另一台设备,也无法解密。适合加密高敏感数据。 - 密钥轮换 :对于长期存储的数据,应考虑定期轮换加密密钥。新数据用新密钥加密,旧数据在访问时解密后用新密钥重新加密。
5.2 国密算法(SM2/SM3/SM4)的优先使用
在OpenHarmony环境下,应优先考虑使用国密算法。如上文代码所示, @ohos.security.crypto 直接支持SM3哈希。对于SM2/SM4,HUKS也提供了支持。在生成密钥或指定算法时,使用 HUKS_ALG_SM2 、 HUKS_ALG_SM4 等对应的枚举值即可。这不仅更符合国内一些项目的合规要求,其性能在OpenHarmony系统上也通常有更好的优化。
5.3 异步操作与UI响应
加密哈希和HUKS操作都可能耗时,尤其是在低端设备上。务必确保这些操作在非UI线程执行。
- 在Dart端 ,我们的
MethodChannel.invokeMethod本身就是异步的(返回Future),这很好。但要避免在compute或Isolate中再进行密集的Dart运算,应把计算压力完全交给原生侧。 - 在原生ArkTS侧 ,HUKS的API是异步的。但要小心,如果你的加密操作是在UI线程触发的,并且回调后需要更新Flutter UI,你需要确保回调能正确返回到Flutter的UI线程。Platform Channel的回调机制通常已经处理了这一点。
5.4 插件化与生态建设
我们是以插件形式开发加密模块的。一个好的插件还应该包括:
- 完善的文档 :README文件,说明安装、配置、API和常见问题。
- 单元测试 :为Dart接口和主要的原生功能编写测试用例。
- 示例应用 :一个完整的、可运行的示例应用,展示插件的典型用法。
- 发布到Pub.dev :如果希望共享给社区,可以发布到Flutter的包仓库。需要注意的是,由于包含原生代码,发布时需要为每个平台(android, ios, ohos)打包相应的产物。
最后,集成过程中如果遇到 waiting for another flutter command to release the startup lock 这类问题,通常是因为Flutter进程被意外锁住,去 flutter sdk 目录下的 bin/cache 里删除 .lockfile 文件即可。而 flutter pub get 卡在 resolving dependencies ,多半是网络问题,可以检查是否配置了国内镜像,或者尝试切换网络环境。
整个集成过程,就像是在Flutter的便捷与OpenHarmony的底层能力之间架起一座坚固且安全的桥梁。每踩过一个坑,对两个系统的理解就加深一层。当你看到Flutter界面上的一个按钮点击,能安全地触发OpenHarmony硬件密钥库里的加密操作时,那种成就感,就是跨平台开发最大的乐趣所在。
更多推荐

所有评论(0)