OpenHarmony开发者论坛

标题: Harmony,满天星光,共赴璀璨星河 [打印本页]

作者: zmtzawqlp    时间: 2024-7-4 09:42
标题: Harmony,满天星光,共赴璀璨星河
[md]
相关阅读:

* [Flutter Love Harmony - 掘金 (juejin.cn)](https://juejin.cn/post/7281948788483489804)
* [不是Harmony ArkUI 不会写,而是 Flutter 更有性价比 - 掘金 (juejin.cn)](https://juejin.cn/post/7329110277172985908)
* [Flutter Harmony化 在一起 就可以 - 掘金 (juejin.cn)](https://juejin.cn/post/7364698043910930443)
* [Flutter到Harmony,不是有手就行吗? (下拉刷新) - 掘金 (juejin.cn)](https://juejin.cn/post/7313161940283998260)
* [Flutter到Harmony,不是有手就行吗? (列表加载更多) - 掘金 (juejin.cn)](https://juejin.cn/post/7314189771378458659)
* [Flutter到Harmony,不是有手就行吗? (仿掘金点赞按钮) - 掘金 (juejin.cn)](https://juejin.cn/post/7330945097403220002)

## 前言

![DM_20241119092408_001.JPEG](https://forums-obs.openharmony.c ... rgpmjgbizb7m0m.jpeg "DM_20241119092408_001.JPEG")




随着 `HDC 2024` 的结束,`Harmony Next` 正式对个人开发者开放,个人开发者终于能够更简单地加入到`Harmony Next` 的体验中。(之前只有少数个人开发者能加入到预览中 [华为纯血Harmony HarmonyOS NEXT 开发者预览版首批 Beta 招募开启,支持 Mate 60 / Pro、X5 机型](https://www.ithome.com/0/745/256.htm))。

[最新工具 - 下载中心 - 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/download/)

> DevEco Studio NEXT Developer Beta1
>
> 面向HarmonyOS应用及元服务开发者提供的集成开发环境(IDE),助力高效开发。
>
> Build Version 5.0.3.403 发布日期 2024/06/21

## 真机和模拟器的区别

这一次除了开放下载 `DevEco Studio Next 版本`,还开放了模拟器下载,(当然,需要去申请一下,很快就会通过),那么真机和模拟器有什么区别呢?

[模拟器与真机的差异-概述-使用模拟器运行应用/服务-应用/服务运行-DevEco Studio | 华为开发者联盟 (huawei.com)](https://developer.huawei.com/con ... 0000001839876358-V5)

在 `ui` 层面,主要是一些效果,比如阴影或者3d效果的缺失。这里提前说这个,是因为后面要考。

![DM_20241119092408_002.JPEG](https://forums-obs.openharmony.c ... uldpichha19ax0.jpeg "DM_20241119092408_002.JPEG")

## Harmony玩家

如果你是一个Harmony开发者,就比较简单了,直接到 [最新工具 - 下载中心 - 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/download/) 下载符合你的设备的 `DevEco Studio`。

如果你第一次玩,需要创建一个华为开发者账号,后续需要用到。比如如果你使用真机,需要登录账号签名。比如你下载模拟器,需要登录账号,去申请模拟器下载权限。

![DM_20241119092408_003.JPEG](https://forums-obs.openharmony.c ... ywkazgdw9d76nn.jpeg "DM_20241119092408_003.JPEG")


点击链接,申请模拟器下载权限。

怎么编写Harmony应用,我这里不展开写了。大家可以查看下面的文章了解更多的信息。

* [Flutter到Harmony,不是有手就行吗? (下拉刷新) - 掘金 (juejin.cn)](https://juejin.cn/post/7313161940283998260)
* [Flutter到Harmony,不是有手就行吗? (列表加载更多) - 掘金 (juejin.cn)](https://juejin.cn/post/7314189771378458659)
* [Flutter到Harmony,不是有手就行吗? (仿掘金点赞按钮) - 掘金 (juejin.cn)](https://juejin.cn/post/7330945097403220002)

欢迎大家使用 [HarmonyCandies](https://ohpm.openharmony.cn/#/cn ... age=1&q=candies) 提供的Harmony组件,欢迎加入 [HarmonyCandies (github.com)](https://github.com/HarmonyCandies)。


## Flutter Harmony化玩家

作为 `Flutter` Harmony化的玩家,你没有阅读过下面的文章,也没有关系。 [OpenHarmony-SIG/flutter\_flutter (gitee.com)](https://gitee.com/openharmony-sig/flutter_flutter) Harmony化社区更新很快,之前文章里面的一些信息已经失效。

* [Flutter Love Harmony - 掘金 (juejin.cn)](https://juejin.cn/post/7281948788483489804)
* [不是Harmony ArkUI 不会写,而是 Flutter 更有性价比 - 掘金 (juejin.cn)](https://juejin.cn/post/7329110277172985908)
* [Flutter Harmony化 在一起 就可以 - 掘金 (juejin.cn)](https://juejin.cn/post/7364698043910930443)

> 后续内容全部基于 [OpenHarmony-SIG/flutter\_flutter (gitee.com)](https://gitee.com/openharmony-sig/flutter_flutter) 和 [OpenHarmony-SIG/flutter\_engine (gitee.com)](https://gitee.com/openharmony-sig/flutter_engine) 的 **dev** 分支。参考文档也以 **dev** 分支 的文档为准。另外最新支持的是 `ohos api12` 。

下面基于最新的社区进度,主要讲一下环境和一些注意事项。

### Mac

`Mac` 分 `X86` 和 `ARM` 芯片的。注意,由于目前 `Flutter for Harmony` 暂时不支持 `x86_x64` 架构,在 `X86` 芯片的 `Mac` 上面,你只能用**真机**开发。**ARM 芯片**(即 M1,M2,M3,M4) 可以使用**模拟器**。

### Windows

注意,由于目前 `Flutter for Harmony` 暂时不支持 `x86_x64` 架构,所以 `Windows` 上面你只能使用**真机**进行开发。

### 模拟器真机差异

前面说了模拟器与真机之间是有差异的,这导致 `Flutter` 在Harmony模拟器中,可能某些组件 `API `不能使用。

[模拟器与真机的差异-概述-使用模拟器运行应用/服务-应用/服务运行-DevEco Studio | 华为开发者联盟 (huawei.com)](https://developer.huawei.com/con ... 0000001839876358-V5)

![DM_20241119092408_002.JPEG](https://forums-obs.openharmony.c ... vmdpbxdpmemhd9.jpeg "DM_20241119092408_002.JPEG")


比如说 `FloatingActionButton` 包含阴影效果,就没法在模拟器中使用,会导致闪退。上图相关的 `API` 我们都要注意一下。

> 可以的话,做 Flutter Harmony化最好是使用真机。

### 环境配置

#### 准备工作

* 下载适配Harmony的 `flutter sdk`

`git clone -b dev git@gitee.com:openharmony-sig/flutter_flutter.git`

* 下载 `DevEco-Studio` [最新工具 - 下载中心 - 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/download/)

#### Mac 和 Linux

* 设置环境变量

我的Harmony相关的内容是放在 `/Users/zmtzawqlp/Documents/ohos/flutter/flutter_flutter` 中的。

```sh
export PATH=/Users/zmtzawqlp/Documents/ohos/flutter/flutter_flutter/binPATH
export PATH=/Users/zmtzawqlp/Documents/ohos/flutter/flutter_flutter/bin/cache/dart-sdk/binPATH

# ohos
export TOOL_HOME=/Applications/DevEco-Studio.app/Contents # mac环境
export DEVECO_SDK_HOME=$TOOL_HOME/sdk # command-line-tools/sdk
export PATH=$TOOL_HOME/tools/ohpm/binPATH # command-line-tools/ohpm/bin
export PATH=$TOOL_HOME/tools/hvigor/binPATH # command-line-tools/hvigor/bin
export PATH=$TOOL_HOME/tools/node/binPATH # command-line-tools/tool/node/bin
```

#### Windows

* 去环境变量中添加,下面的键值对。
![DM_20241119092408_004.JPEG](https://forums-obs.openharmony.c ... 47uu7pzuy4snss.jpeg "DM_20241119092408_004.JPEG")

![DM_20241119092408_006.JPEG](https://forums-obs.openharmony.c ... 68zaaxk1vhz1dv.jpeg "DM_20241119092408_006.JPEG")


* 去环境变量 `PATH` 中添加,下面的路径

![bf24d1144f5fdc6577b181e299cae9a2.png](https://p3-juejin.byteimg.com/to ... ;e=png&b=f8f8f8)

以及 `flutter` 和 `dart` 的路径,这里就不截图了。

### 引擎编译

目前,社区已经支持自动下载最新的**线上引擎**,所以对于不追求引擎代码随时最新的玩家,这部分内容可以跳过。

#### 环境准备

构建的基础配置请查考: [flutter/docs/engine/contributing/Setting-up-the-Engine-development-environment.md at master · flutter/flutter (github.com)](https://github.com/flutter/flutt ... ment-environment.md)

#### 编译问题

##### python 版本

如果你编译报错
`ModuleNotFoundError: No module named 'imp'`,请切换 `python` 版本到 `3.11` 以其以下。 `python3.12` 中 `imp` 已经不支持。

[python - ModuleNotFoundError: No module named 'imp' - Stack Overflow](https://stackoverflow.com/questi ... no-module-named-imp)

##### Xcode15

如果你的电脑升级了 `Xcode15`,在做编译引擎的时候,也许会遇到下面的错误。

```
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:657:37: error: use of undeclared identifier 'NSIntegerMax'
static const NSInteger NSNotFound = NSIntegerMax;
```

或者

```
../../third_party/dart/runtime/bin/security_context_macos.cc:188:17: error: use of undeclared identifier 'noErr'
  if (status != noErr) {
                ^
../../third_party/dart/runtime/bin/security_context_macos.cc:196:19: error: use of undeclared identifier 'noErr'
    if (status != noErr) {
                  ^
../../third_party/dart/runtime/bin/security_context_macos.cc:205:17: error: use of undeclared identifier 'noErr'
  if (status != noErr) {
                ^
../../third_party/dart/runtime/bin/security_context_macos.cc:303:21: error: use of undeclared identifier 'noErr'
  OSStatus status = noErr;
                    ^
../../third_party/dart/runtime/bin/security_context_macos.cc:319:23: error: use of undeclared identifier 'noErr'
            status == noErr && (trust_result == kSecTrustResultProceed ||
                      ^
```

解决办法是从下面地址选择 `13.3 sdk `中的 `TargetConditionals.h`

[macos-sdk/MacOSX13.3.sdk/usr/include/TargetConditionals.h at main · alexey-lysiuk/macos-sdk (github.com)](https://github.com/alexey-lysiuk ... argetConditionals.h)

替换掉你本地的,注意做备份。

`/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/TargetConditionals.h`

#### 运行调试引擎

##### 设置本地引擎

我们可以通过下面三种方法在运行调试项目的时候,设置我们编译出来的引擎。

###### launch.json

通过 `vscode` 我们可以创建 `launch.json`.

![DM_20241119092408_005.JPEG](https://forums-obs.openharmony.c ... udhqqdp8fs3pqs.jpeg "DM_20241119092408_005.JPEG")


其中
`--local-engine-src-path` 是你编译出来引擎目录下面 `src` 的路径。

`--local-engine` 是 `src` 下面 `out` 文件夹中

```json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "ohos_demo",
            "request": "launch",
            "type": "dart",
            "args": [
                "--local-engine-src-path",
                "/Users/xxx/Documents/ohos/flutter/engine/src",   
                "--local-engine",
                "ohos_debug_unopt_arm64",           
            ]
        },
        {
            "name": "ohos_demo (profile mode)",
            "request": "launch",
            "type": "dart",
            "flutterMode": "profile",
            "args": [
                "--local-engine-src-path",
                "/Users/xxx/Documents/ohos/flutter/engine/src",   
                "--local-engine",
                "ohos_profile_arm64",           
            ]
        },
        {
            "name": "ohos_demo (release mode)",
            "request": "launch",
            "type": "dart",
            "flutterMode": "release",
            "args": [
                "--local-engine-src-path",
                "/Users/xxx/Documents/ohos/flutter/engine/src",   
                "--local-engine",
                "ohos_release_arm64",           
            ]
        }
    ]
}
```

缺点每个项目都需要创建一个,并且只能点击这里的按钮启动。

###### 命令

直接使用命令运行,当然也需要配置参数。

`flutter run --local-engine-src-path /Users/xxx/Documents/ohos/flutter/engine/src --local-engine ohos_debug_unopt_arm64 `

###### 修改 flutter\_tools 的流程

* 创建一个 `ohos_local_engine.patch` 文件,将下面的内容复制到里面去。

```
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
index 28dc9f587a..bf94f57750 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

+import 'dart:io';
+
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:completion/completion.dart';
@@ -172,7 +174,54 @@ class FlutterCommandRunner extends CommandRunner<void> {
       }
     }

-    return super.run(args);
+ ArgResults argResults = super.parse(args);
+
+    var ohosArgs = <String>[];
+    // 没有设置过本地引擎
+    if (!args.contains('--local-engine-src-path') &&
+        !args.contains('--local-engine')) {
+      final String? flutterOhosEngine =
+          Platform.environment['FLUTTER_OHOS_ENGINE'];
+
+      print('FLUTTER_OHOS_ENGINE -----$flutterOhosEngine');
+      if (flutterOhosEngine != null) {
+        Directory outDirectory = globals.fs
+            .directory(globals.fs.path.join(flutterOhosEngine, 'out'));
+        var buildMode = 'debug';
+        var command = argResults.command;
+        if (command != null) {
+          if (command.options.contains('release') &&
+              command['release'] == true) {
+            buildMode = 'release';
+          } else if (command.options.contains('profile') &&
+              command['profile'] == true) {
+            buildMode = 'profile';
+          }
+        }
+        var localEngine = '';
+        if (outDirectory.existsSync()) {
+          for (final FileSystemEntity file in outDirectory.listSync()) {
+            if (file is Directory && file.basename.contains(buildMode)) {
+              localEngine = file.basename;
+            }
+          }
+        }
+        if (localEngine.isNotEmpty) {
+          ohosArgs = [
+            '--local-engine-src-path',
+            flutterOhosEngine,
+            '--local-engine',
+            localEngine,
+          ];
+          print('自动设置本地引擎位\n${ohosArgs.join('\n')}');
+        }
+      }
+    }
+
+    return super.run(<String>[
+      ...ohosArgs,
+      ...args,
+    ]);
   }

   @override
```

* 到你本地 `Flutter SDK` 的目录中去,执行 `git apply ohos_local_engine.patch`。
* 删除  `Flutter SDK` 目录下面 `bin\cache` 中的 `flutter_tools.stamp` 和 `flutter_tools.snapshot`, 执行 `flutter doctor` 命令,重新编译 `flutter_tools` 。
* 增加环境变量 `FLUTTER_OHOS_ENGINE` 指向本地引擎的 `src` 目录。

1. linux,macos

`export FLUTTER_OHOS_ENGINE=/Users/xxx/Documents/ohos/flutter/engine/src`

2. windows

![image.png](https://p9-juejin.byteimg.com/to ... 0:q75.image#?w=1011\&h=244\&s=16491\&e=png\&b=f5f2f2)

这样子就会根据你运行的模式自己设置本地引擎的参数了。

### 签名

如果在真机上面运行,需要签名。之前是使用工具进行签名的,但是对于需要频繁切换项目的情况下,不方便,我们可以使用 `Deveco Studio` 签名,对你想运行的项目进行签名。流程跟 `Flutter Ios` 端使用 `Xcode` 签名相似。

* 用 `Deveco Studio` 打开项目的 `ohos` 目录
* 单击 `File > Project Structure > Project > Signing Configs` 界面勾选 `Automatically generate signature`,等待自动签名完成即可,单击 `OK`。
* 查看 `build-profile.json5` 配置信息,配置信息中增加自动签名生成的证书信息。

## Harmony Flutter 插件

现阶段 `Flutter` 适配工作主要集中在Harmony原生插件的适配。下面介绍一下已知完成适配的插件。

### flutter\_packages

[OpenHarmony-SIG/flutter\_packages (gitee.com)](https://gitee.com/openharmony-sig/flutter_packages) 是适配官方 [flutter/packages: A collection of useful packages maintained by the Flutter team (github.com)](https://github.com/flutter/packages/) 仓库。

引用方式例子如下:

```yaml
dependencies:
  path_provider:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_packages.git"
      path: "packages/path_provider/path_provider"
```

| path\_provider      | 2.1.1        | 官方库 | 11月30日 |  |  |
| ------------------- | ------------ | ------ | -------- | - | - |
| shared\_preferences | 2.2.1        | 官方库 | 11月30日 |  |  |
| url\_launcher       | 6.1.11       | 官方库 | 11月30日 |  |  |
| image\_picker       | 1.0.4        | 官方库 | 12月30日 |  |  |
| local\_auth         | 2.1.6        | 官方库 | 12月30日 |  |  |
| pigeon              | 11.0.1       | 官方库 | 12月30日 |  |  |
| webview\_flutter    | 4.2.4、4.4.4 | 官方库 | 12月30日 |  |  |
| video\_player       | 2.7.2        | 官方库 | 3月30日  |  |  |
| file\_selector      | 1.0.1        | 官方库 | 12月30日 |  |  |
| camera              | 0.10.5       | 官方库 | 3月30日  |  |  |

### plus 插件

[\[Request\]: support HarmonyOS · Issue #2480 · fluttercommunity/plus\_plugins (github.com)](https://github.com/fluttercommunity/plus_plugins/issues/2480) 作者对于适配Harmony平台兴趣不大,所以这里决定 [HarmonyCandies (github.com)](https://github.com/HarmonyCandies) 来维护。

#### wakelock\_plus\_ohos

地址:[https://github.com/HarmonyCandies/wakelock_plus_ohos](https://github.com/HarmonyCandies/wakelock_plus_ohos)

引用:

```yaml
dependencies:
  wakelock_plus: 1.1.4
  wakelock_plus_ohos: any
```

#### device\_info\_plus\_ohos

地址:[https://github.com/HarmonyCandies/device_info_plus_ohos](https://github.com/HarmonyCandies/device_info_plus_ohos)

引用:

```yaml
dependencies:
  device_info_plus: any
  device_info_plus_ohos: any
```

注意,有 `2` 个 `uid` 是系统级别的,需要应用单独申请。

```dart
/// Requires permission: ohos.permission.sec.ACCESS_UDID (System permission, only open to system apps).
  /// Device serial number.
  /// 设备序列号。
  final String serial;

  /// Requires permission: ohos.permission.sec.ACCESS_UDID (System permission, only open to system apps).
  /// Device Udid.
  /// 设备Udid。
  final String udid;
```

使用

```dart
import 'package:device_info_plus_ohos/device_info_plus_ohos.dart';

final DeviceInfoOhosPlugin deviceInfoOhosPlugin = DeviceInfoOhosPlugin();

OhosDeviceInfo deviceInfo = await deviceInfoOhosPlugin.ohosDeviceInfo;

// Requires permission: ohos.permission.sec.ACCESS_UDID (System permission, only open to system apps).
OhosAccessUDIDInfo accessUDIDInfo = await deviceInfoOhosPlugin.ohosAccessUDIDInfo;
```

#### network\_info\_plus\_ohos

地址:[https://github.com/HarmonyCandies/network_info_plus_ohos](https://github.com/HarmonyCandies/network_info_plus_ohos)

引用:

```yaml
dependencies:
  network_info_plus: any
  network_info_plus_ohos: any
```

在你的项目的 `module.json5` 文件中增加以下权限设置。

```json
requestPermissions: [
      {"name" :  "ohos.permission.INTERNET"},
      {"name" :  "ohos.permission.GET_WIFI_INFO"},
    ],
```

#### sensors\_plus\_ohos

地址:[https://github.com/HarmonyCandies/sensors_plus_ohos](https://github.com/HarmonyCandies/sensors_plus_ohos)

引用:

```yaml
dependencies:
  sensors_plus: 4.0.2
  sensors_plus_ohos: any
```

在你的项目的 `module.json5` 文件中增加以下权限设置。

```json
requestPermissions: [
      {"name" :  "ohos.permission.ACCELEROMETER"},
      {"name" :  "ohos.permission.GYROSCOPE"},
    ],
```

#### connectivity\_plus\_ohos

地址:[https://github.com/HarmonyCandies/connectivity_plus_ohos](https://github.com/HarmonyCandies/connectivity_plus_ohos)

引用:

```yaml
dependencies:
  connectivity_plus: 5.0.2
  connectivity_plus_ohos: any
```

在你的项目的 `module.json5` 文件中增加以下权限设置。

```json
requestPermissions: [
      {"name" :  "ohos.permission.INTERNET"},
      {"name" :  "ohos.permission.GET_NETWORK_INFO"},
    ],
```

#### battery\_plus\_ohos

地址:[https://github.com/HarmonyCandies/battery_plus_ohos](https://github.com/HarmonyCandies/battery_plus_ohos)

引用:

```yaml
dependencies:
  battery_plus: 5.0.3
  battery_plus_ohos: any
```

#### package\_info\_plus\_ohos

地址:[https://github.com/HarmonyCandies/package_info_plus_ohos](https://github.com/HarmonyCandies/package_info_plus_ohos)

引用:

```yaml
dependencies:
  package_info_plus: 4.2.0
  package_info_plus_ohos: any
```

### 糖果插件

#### flutter_image_compress

地址:https://github.com/fluttercandies/flutter_image_compress

引用:

```yaml
dependencies:
  flutter_image_compress: ^2.2.0
```

| Feature                    | Android | iOS |           Web           | macOS | OpenHarmony |
| :------------------------- | :-----: | :-: | :----------------------: | :---: | :---------: |
| method: compressWithList   |   ✅   | ✅ |            ✅            |  ✅  |     ✅     |
| method: compressAssetImage |   ✅   | ✅ |            ✅            |  ✅  |     ✅     |
| method: compressWithFile   |   ✅   | ✅ |            ❌            |  ✅  |     ✅     |
| method: compressAndGetFile |   ✅   | ✅ |            ❌            |  ✅  |     ✅     |
| format: jpeg               |   ✅   | ✅ |            ✅            |  ✅  |     ✅     |
| format: png                |   ✅   | ✅ |            ✅            |  ✅  |     ✅     |
| format: webp               |   ✅   | ✅ | [🌐][webp-compatibility] |  ❌  |     ✅     |
| format: heic               |   ✅   | ✅ |            ❌            |  ✅  |     ✅     |
| param: quality             |   ✅   | ✅ | [🌐][webp-compatibility] |  ✅  |     ✅     |
| param: rotate              |   ✅   | ✅ |            ❌            |  ✅  |     ✅     |
| param: keepExif            |   ✅   | ✅ |            ❌            |  ✅  |     ❌     |

#### flutter_image_editor

地址:https://github.com/fluttercandies/flutter_image_editor

引用:

```yaml
dependencies:
  image_editor: ^2.2.0
```

| Feature           | Android | iOS | OpenHarmony |
| :---------------- | :-----: | :-: | :---------: |
| flip              |   ✅   | ✅ |     ✅     |
| crop              |   ✅   | ✅ |     ✅     |
| rotate            |   ✅   | ✅ |     ✅     |
| scale             |   ✅   | ✅ |     ✅     |
| matrix            |   ✅   | ✅ |     ❌     |
| mix image         |   ✅   | ✅ |     ✅     |
| merge multi image |   ✅   | ✅ |     ✅     |
| draw point        |   ✅   | ✅ |     ✅     |
| draw line         |   ✅   | ✅ |     ✅     |
| draw rect         |   ✅   | ✅ |     ✅     |
| draw circle       |   ✅   | ✅ |     ✅     |
| draw path         |   ✅   | ✅ |     ✅     |
| draw Bezier       |   ✅   | ✅ |     ✅     |
| Gaussian blur     |   ❌   | ❌ |     ❌     |

#### ~~flutter_photo_manager~~

> 注意,由于隐私设计的变更,该插件没法在后续的版本中使用了,Harmony将不再支持直接获取相册的图片文件。

地址:https://github.com/fluttercandies/flutter_photo_manager

引用:

注意 `photo_manager_image_provider` 需要限制一下版本。

```yaml
dependencies:
  photo_manager: ^3.1.0
dependency_overrides:
  photo_manager_image_provider: ^1.1.1
```

暂时支持下面的功能,目前Harmony只支持图片和视频 2 种资源类型。

| Feature                 | OpenHarmony |
| :---------------------- | :---------: |
| getAssetPathList        |     ✅     |
| getAssetCountFromPath   |     ✅     |
| fetchPathProperties     |     ✅     |
| getAssetCount           |     ✅     |
| getAssetListPaged       |     ✅     |
| getOriginBytes          |     ✅     |
| getThumb                |     ✅     |
| getAssetListRange       |     ✅     |
| getAssetsByRange        |     ✅     |
| deleteWithIds           |     ✅     |
| getColumnNames          |     ✅     |
| saveImage               |     ✅     |
| saveImageWithPath       |     ✅     |
| saveVideo               |     ✅     |
| requestPermissionExtend |     ✅     |
| ignorePermissionCheck   |     ✅     |
| log                     |     ✅     |
| notify                  |     ✅     |

### 其他插件

#### permission\_handler\_ohos

地址:[https://github.com/HarmonyCandies/permission_handler_ohos](https://github.com/HarmonyCandies/permission_handler_ohos)

引用:

```yaml
dependencies:
permission_handler_ohos: any
```

权限列表来自: [https://gitee.com/openharmony/do ... missions-for-all.md](https://gitee.com/openharmony/do ... missions-for-all.md)

##### 注意

由于 `OpenHarmony` 和 `HarmonyOS` 的权限差异以及Harmony版本的高速迭代,检查请求权限的 `api` 是传递的权限的字符串全称,如果你发现 `PermissionOhos` 枚举中没有某个权限,你可以直接传递权限的字符串全称。等Harmony版本稳定下来了,会再同步权限列表到枚举中。

权限枚举列表是由文档自动生成的。

```dart
// GENERATED CODE - DO NOT MODIFY MANUALLY
// **************************************************************************
// Auto generated by https://github.com/HarmonyCandie ... _ohos/bin/main.dart
// **************************************************************************
// https://gitee.com/openharmony/do ... missions-for-all.md
// ignore_for_file: constant_identifier_names,slash_for_doc_comments

/// The Permissions of OpenHarmony
/// total: 44
enum PermissionOhos {
  /// ohos.permission.USE_BLUETOOTH
  ///
  /// 允许应用查看蓝牙的配置。
  ///
  /// 权限级别:normal
  ///
  /// 授权方式:system_grant
  ///
  /// ACL使能:true
  ///
  /// 起始版本:8

  use_bluetooth(
    name: 'ohos.permission.USE_BLUETOOTH',
    permissionLevel: 'normal',
    grantType: 'system_grant',
    aclEnabled: true,
    startVersion: 8,
  ),
```

##### 使用

请认真阅读官方关于权限的文档 [https://gitee.com/openharmony/do ... 7%E6%A6%82%E8%BF%B0](https://gitee.com/openharmony/do ... 7%E6%A6%82%E8%BF%B0)

在你的项目的 `module.json5` 文件中增加对应需要权限设置,比如:

```json
requestPermissions: [
      { name: "ohos.permission.READ_CALENDAR" },
      { name: "ohos.permission.WRITE_CALENDAR" },
    ],
```

##### 例子

检查权限状态

```dart
import 'package:device_info_plus_ohos/device_info_plus_ohos.dart';

    final PermissionStatusOhos status =
        await PermissionHandlerOhos.checkPermissionStatus(
            PermissionOhos.read_calendar.name);
```

请求单个权限

```dart
final PermissionStatusOhos status =
        await PermissionHandlerOhos.requestPermission(
      PermissionOhos.read_calendar.name,
    );
```

请求多个权限

```dart
final Map<String, PermissionStatusOhos> statusMap =
        await PermissionHandlerOhos.requestPermissions([
      PermissionOhos.read_calendar.name,
      PermissionOhos.write_calendar.name,
    ]);
```

打开设置页面

```dart
PermissionHandlerOhos.openAppSettings();
```

#### audio_streamer_ohos

地址:https://github.com/HarmonyCandies/audio_streamer_ohos

引用:

```yaml
dependencies:
  audio_streamer: 4.1.1
  audio_streamer_ohos: any
```

[audio_streamer](https://pub.dev/packages/audio_streamer) 在 OpenHarmony 平台上的实现

在 OpenHarmony 项目的 `module.json` 文件中添加 `ohos.permission.MICROPHONE` 权限

```json
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.MICROPHONE",
        "reason": "Microphone permission is required to record audio."
      }
    ]
  }
}
```

#### geolocator

地址: [HarmonyCandies/geolocator_ohos: The OpenHarmony implementation of geolocator. (github.com)](https://github.com/HarmonyCandies/geolocator_ohos)

引用:

```yaml
dependencies:
  geolocator: any
  geolocator_ohos: ^0.0.1
```

在你的项目的 `module.json5` 文件中增加以下权限设置。

```json
"requestPermissions": [
      {"name" :  "ohos.permission.KEEP_BACKGROUND_RUNNING"},
      {
        "name": "ohos.permission.LOCATION",
        "reason": "$string:EntryAbility_label",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.APPROXIMATELY_LOCATION",
        "reason": "$string:EntryAbility_label",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.LOCATION_IN_BACKGROUND",
        "reason": "$string:EntryAbility_label",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      },               
    ]
```

Harmony特有的方法

```dart
CountryCode? countryCode= await geolocatorOhos.getCountryCode();
```

(逆)地理编码转化

```dart
final position = await geolocatorOhos.getCurrentPosition(
      locationSettings: const CurrentLocationSettingsOhos(
        priority: LocationRequestPriority.firstFix,
        scenario: LocationRequestScenario.unset,
      ),
    );

    // ohos only
    if (await geolocatorOhos.isGeocoderAvailable()) {
      //
      var addresses = await geolocatorOhos.getAddressesFromLocation(
        ReverseGeoCodeRequest(
          latitude: position.latitude,
          longitude: position.longitude,
          locale: 'zh',
          maxItems: 1,
        ),
      );

      for (var address in addresses) {
        if (kDebugMode) {
          print('ReverseGeoCode addressaddress');
        }
        var position = await geolocatorOhos.getAddressesFromLocationName(
          GeoCodeRequest(description: address.placeName ?? ''),
        );
        if (kDebugMode) {
          print('geoCode positionposition');
        }
      }
    }
```

#### vibration

地址:[flutter_vibration/vibration_ohos at master · benjamindean/flutter_vibration (github.com)](https://github.com/benjamindean/ ... ster/vibration_ohos)

引用:

```yaml
dependencies:
  vibration: any
  vibration_ohos: any
```

在你的项目的 `module.json5` 文件中增加以下权限设置。

```json
"requestPermissions": [
         {"name" :  "ohos.permission.VIBRATE"},              
    ]
```

`vibrateEffect` and `vibrateAttribute` are only exist in `VibrationOhos`.

```dart
(VibrationPlatform.instance as VibrationOhos).vibrate(
   vibrateEffect: const VibratePreset(count: 100),
   vibrateAttribute: const VibrateAttribute(
     usage: 'alarm',
   ),
);
```

#### sqflite

地址:https://gitee.com/openharmony-sig/flutter_sqflite

引用:

```yaml
dependencies:
  sqflite:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_sqflite.git"
      path: "sqflite"
```

#### fluttertoast

地址:https://gitee.com/openharmony-sig/flutter_fluttertoast

引用:

```yaml
dependencies:
  fluttertoast:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_fluttertoast.git"
```

#### audio_session

地址:https://gitee.com/openharmony-sig/flutter_audio_session

引用:

```yaml
dependencies:
  audio_session:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_audio_session.git"
```

#### flutter_sound

地址:https://gitee.com/openharmony-sig/flutter_sound

引用:

```yaml
dependencies:
  flutter_sound:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_sound.git"
      path: "flutter_sound"
```

#### image_gallery_saver

地址:https://gitee.com/openharmony-sig/flutter_image_gallery_saver

引用:

```yaml
dependencies:
  image_gallery_saver:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_image_gallery_saver.git"
```

#### location

地址:https://gitee.com/openharmony-sig/flutter_location

引用:

```yaml
dependencies:
  location:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_location.git"
      path: "location"
```

#### power_image

地址:https://gitee.com/openharmony-sig/flutter_power_image

引用:

```yaml
dependencies:
  power_image:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_power_image.git"
```

#### flutter_native_image

地址:https://gitee.com/openharmony-sig/flutter_native_image

引用:

```yaml
dependencies:
  flutter_native_image:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_native_image.git"
```

#### audioplayers

地址:https://gitee.com/openharmony-sig/flutter_audioplayers

引用:

```yaml
dependencies:
  audioplayers:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_audioplayers.git"
```

#### image_crop

地址:https://gitee.com/openharmony-sig/flutter_image_crop

引用:

```yaml
dependencies:
  image_crop:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_image_crop.git"
```

#### bitmap

地址:https://gitee.com/openharmony-sig/flutter_bitmap

引用:

```yaml
dependencies:
  bitmap:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_bitmap.git"
```

#### leak_detector

地址:https://gitee.com/openharmony-sig/flutter_leak_detector

引用:

```yaml
dependencies:
  leak_detector:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_leak_detector.git"
```

#### flutter_contacts

地址:https://gitee.com/openharmony-sig/flutter_contacts

引用:

```yaml
dependencies:
  flutter_contacts:
    git:
      url: "https://gitee.com/openharmony-sig/flutter_contacts.git"
```

### 编写插件注意事项

#### 关于Harmony的 context

在制作插件中,你可能需要用到 `2` 种 `context`。

##### ApplicationContex

你可以直接从 `onAttachedToEngine` 方法中获取。

```js
private context: Context | null = null;

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.context = binding.getApplicationContext();
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.context = null;
  }
```

该 `context` 可以用于获取 `applicationInfo` 等属性。

`let applicationInfo = this.context.applicationInfo;`

##### UIAbilityContext

插件继承  `AbilityAware` 并且在  `onAttachedToAbility` 方法中获取。

```js
export default class XXXPlugin implements FlutterPlugin, MethodCallHandler, AbilityAware {
  private _uiContext: common.UIAbilityContext | null = null;

  onAttachedToAbility(binding: AbilityPluginBinding): void {
    this._uiContext = binding.getAbility().context;
  }

  onDetachedFromAbility(): void {
    this._uiContext = null;
  }
}
```

该 `uiContext` 可以用于获取 `applicationInfo` 等属性。

`photoAccessHelper.getPhotoAccessHelper(PhotoManagerPlugin.uiContext);`

#### 关于插件参数传递

按照以前的习惯,`dart` 端传递 `map` 参数,原生端根据 `map` 解析参数。

但由于 `ts` 支持将字符串直接转换成对应的 `interface` ,那么我们可以将 `dart` 的端的参数。

##### 参数定义

比如 `geolocator_ohos` 中的 [`CurrentLocationSettingsOhos`](https://github.com/zmtzawqlp/flu ... ttings_ohos.dart#L8) 在 `dart` 端的实现为如下:

```dart
Map<String, dynamic> toMap() {
    return {
      if (priority != null) 'priority': priority?.toInt(),
      if (scenario != null) 'scenario': scenario?.toInt(),
      if (maxAccuracy != null) 'maxAccuracy': maxAccuracy,
      if (timeoutMs != null) 'timeoutMs': timeoutMs,
    };
  }

  @override
  String toString() {
    return jsonEncode(toMap());
  }
```

而在Harmony原生端,对于的 `interface` 是 [`CurrentLocationRequest`](https://gitee.com/openharmony/do ... rentlocationrequest)

```js
export interface CurrentLocationRequest {
    priority?: LocationRequestPriority;
    scenario?: LocationRequestScenario;
    maxAccuracy?: number;
    timeoutMs?: number;
}
```

值得注意的是,如果参数为 `null`,不要传递过去,比如 `'priority': null` , 如果传递过去,Harmony原生端会解析错误。不传递过去的话,会解析为 `undefined`,这也对应了  `priority?: LocationRequestPriority` 可选的意思。

> 可以使用 `chatgpt` 直接将Harmony的 `interface` 转换成 `dart` 的类,并且增加 `toMap`,`fromMap`,和注释。

##### 插件传递

`dart` 端,将参数类以字符串的方式传递过去,并且用字符串的方式接受返回值。

```dart
@override
  Future<osition> getCurrentPosition({
    LocationSettings? locationSettings,
    String? requestId,
  }) async {
    assert(
      locationSettings == null ||
          locationSettings is CurrentLocationSettingsOhos,
      'locationSettings should be CurrentLocationSettingsOhos',
    );

    try {
      final Duration? timeLimit = locationSettings?.timeLimit;

      Future<dynamic> positionFuture =
          GeolocatorOhos._methodChannel.invokeMethod(
        'getCurrentPosition',
        locationSettings?.toString(),
      );

      if (timeLimit != null) {
        positionFuture = positionFuture.timeout(timeLimit);
      }

      return PositionOhos.fromString(await positionFuture);
    }
  }
```

在Harmony端, 将字符串直接转换成Harmony对应的 `interface` 。

`let request: geoLocationManager.CurrentLocationRequest = JSON.parse(args);`

并且将要返回的 `interface` 转换成字符串。

`result.success(JSON.stringify(location));`

当然了,这样有个问题,就是如果Harmony端修改了 `interface` 的属性名字,插件很难感知到(当然会报错)。

### 纯 Flutter 库

#### extended_text

```yaml
dependencies:
  extended_text: 10.0.1-ohos // 适配 3.7.12
  extended_text: 13.0.2      // 适配 3.22.0
```

#### extended_text_field

```yaml
dependencies:
  extended_text_field: 11.0.1-ohos // 适配 3.7.12
  extended_text_field: 15.0.0-ohos // 适配 3.22.0
```

#### flutter_platform_utils

[HarmonyCandies/flutter_platform_utils: A utility to check the platform for ohos (github.com)](https://github.com/HarmonyCandies/flutter_platform_utils)

如果您的库支持 `OpenHarmony` 平台,并且有 `Platform.isOhos` 的判断,那么建议换成 `PlatformUtils.isOhos` 避免对其他非Harmony用户在非Harmony分支编译的影响。

## 结语

> 独行快,众行远,加入Harmony正当时。

随着Harmony商店里面的应用越来越多,还在观望的你,与其犹豫不决,还不如笃定前行。

作为开发者,我们曾经骂过微软,骂过谷歌,骂过苹果,但这些抱怨其实源于我们对它们的期望,希望它们变得更好。同样的,**Harmony**也是如此。

> 最后,Harmony原生,启动!
![DM_20241119092408_007.JPEG](https://forums-obs.openharmony.c ... jtvzv9lgglojb8.jpeg "DM_20241119092408_007.JPEG")


爱 `Harmony`,爱 `糖果`,欢迎加入[Harmony Candies](https://github.com/HarmonyCandies),一起生产可爱的Harmony小糖果[![](https://p3-juejin.byteimg.com/to ... -zoom-1.image#?w=90\&h=22\&s=1827\&e=png\&b=1fa4e6)QQ群:981630644](https://qm.qq.com/q/ajfsyk2RcA)

![DM_20241119092408_008.PNG](https://forums-obs.openharmony.c ... kad7dauoh9sfy7h.png "DM_20241119092408_008.PNG")


## 相关链接

* [OpenHarmony 引擎源码](https://gitee.com/openharmony/arkui_ace_engine)
* [语法提示错误修复指导案例](https://gitee.com/openharmony/do ... arkts-more-cases.md)
* [开发者文档中心 | 应用推广/应用接入和技术支持 | 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/doc/)
* [OpenHarmony三方库中心仓](https://ohpm.openharmony.cn/#/cn/home)
* [OpenHarmony开发者论坛](https://forums.openharmony.cn/portal.php)
* [HarmonyOS NEXT仓颉语言开发者预览版 Beta招募- 华为开发者联盟 (huawei.com)](https://developer.huawei.com/con ... etail/cangjie-beta/)
* [DevEco CodeGenie 开发者预览版 Beta招募](https://developer.huawei.com/con ... 933685103243/signup)

![截屏2024-06-26 17.04.17.png](https://p9-juejin.byteimg.com/to ... ;e=png&b=fefefe)


[/md]
作者: yeyao    时间: 2024-11-20 10:14





欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5