PaxLee
PaxLee学无止境
Назад к списку
 Полное руководство: адаптация Flutter под HarmonyOS — от нуля до публикации в AppGallery
FlutterHarmonyOS从零到上架的踩坑指南

Полное руководство: адаптация Flutter под HarmonyOS — от нуля до публикации в AppGallery

Опубликовано 14 июля 2026 г.17 min read
> Для инженеров, которые уже выпускают Flutter-приложения на Android / iOS.
> После прочтения вы сможете: поднять toolchain HarmonyOS → собрать первый HAP из существующего проекта → закрыть совместимость плагинов и фич → собрать `.app` для магазина.

Это не очередной Hello World, а практический путь по опыту реального релиза. Пример имени пакета — com.example.myapp; замените на своё.

Также доступно: 中文 · English


Чему вы научитесь

  • Почему обычного Flutter недостаточно и какую toolchain нужно использовать
  • По шагам: что ставить, что менять, какие команды запускать
  • Как настроить плагины, чтобы проект реально собрался (самый длинный «подводный камень»)
  • Как урезать возможности: логин, хранилище, WebView, уведомления, push и т.д.
  • Чем отличаются debug HAP и store APP
  • Как выровнять подпись и clientId Huawei Account, чтобы не «лечь» сразу после релиза

Сначала правильная модель (прочитайте до кода)

Перенос Flutter-приложения на HarmonyOS — это не «добавить flavor». Это ближе к «добавить целую новую платформенную toolchain»:

ОжиданиеРеальность
Достаточно flutter build apkВ обычном Flutter нет команд hap / HarmonyOS-app
Реализаций под Android хватитУ большинства federated-плагинов нет OHOS-реализации — нужен полный override цепочки
Пара проверок Platform.isAndroidНужна матрица возможностей: Firebase / уведомления / часть нативных библиотек деградируют
Release-сборка = в магазинДля отладки — .hap, для магазина — .app; подпись и OAuth должны совпадать

Одной фразой:

Форк OHOS Flutter + нативный проект ohos + полный override плагинов + гейтинг возможностей в Dart + release-подпись, согласованная с Huawei Account.

Идите по порядку. Многие «залипают» на третий день, потому что шаги 1–2 сделаны неправильно, а бизнес-код уже переписывают.


Обзор маршрута

Шаг 1   Установить DevEco Studio и подготовить каталог SDK HarmonyOS
Шаг 2   Установить / настроить форк OpenHarmony Flutter
Шаг 3   Сгенерировать / проверить проект ohos
Шаг 4   Прописать local.properties (пути SDK и Flutter)
Шаг 5   Настроить debug-подпись, чтобы работал SignHap
Шаг 6   Переработать pubspec: пакеты *_ohos + dependency_overrides
Шаг 7   Добавить абстракцию AppPlatform; пройти анализ
Шаг 8   Первый flutter build hap --debug; установка на устройство
Шаг 9   Адаптировать фичи (логин / хранилище / WebView / TTS / оплата…)
Шаг 10  Release-подпись + flutter build app --release для AppGallery

Шаг 1. Установка DevEco и подготовка каталога SDK

1.1 Что поставить

  1. Установите DevEco Studio с сайта разработчика Huawei (на macOS часто: /Applications/DevEco-Studio.app)
  2. Откройте DevEco и скачайте HarmonyOS SDK по мастеру (часто API 24 / HarmonyOS 6.1.1 — ориентируйтесь на доступные версии)
  3. Проверьте CLI:
# hdc: утилита устройства HarmonyOS, обычно в sdk/.../toolchains DevEco
hdc list targets

Устройство в списке — или пустой список при работающей команде — значит toolchain в целом на месте.

1.2 Ловушка: имя каталога SDK должно совпадать с ожиданиями hvigor

hvigor 6.x часто ждёт структуру вида:

~/Library/OpenHarmony/Sdk/HarmonyOS-6.1.1/
  ├── openharmony/
  │   ├── ets
  │   ├── native
  │   ├── toolchains
  │   └── ...
  └── hms/
      ├── ets
      ├── native
      └── ...

Симптом: сборка не находит HarmonyOS-6.1.1 / API 24. Причина: встроенный путь DevEco часто Contents/sdk/default/openharmony — это не та схема выше. Решение: сделать symlink (или копию) компонентов DevEco в ожидаемое дерево:

#!/usr/bin/env bash
set -euo pipefail

```text
DEVECO_APP="${DEVECO_APP:-/Applications/DevEco-Studio.app}"
SDK_HOME="${HOME}/Library/OpenHarmony/Sdk"
SOURCE_OH="${DEVECO_APP}/Contents/sdk/default/openharmony"
SOURCE_HMS="${DEVECO_APP}/Contents/sdk/default/hms"
TARGET_SDK="${SDK_HOME}/HarmonyOS-6.1.1"

mkdir -p "${TARGET_SDK}/openharmony" "${TARGET_SDK}/hms"

for component in ets js native previewer toolchains; do
  ln -sfn "${SOURCE_OH}/${component}" "${TARGET_SDK}/openharmony/${component}"
done
for component in ets native previewer toolchains; do
  ln -sfn "${SOURCE_HMS}/${component}" "${TARGET_SDK}/hms/${component}"
done

echo "SDK ready: ${TARGET_SDK}" ls -la "${TARGET_SDK}"


> На Windows настройте эквивалент по документации DevEco. Суть: hvigor должен видеть полный SDK с `openharmony/` и `hms/`.

**Критерий готовности:** существует `~/Library/OpenHarmony/Sdk/HarmonyOS-6.1.1` (или имя под ваш `compileSdkVersion`) с нужными подкаталогами.

---

## Шаг 2. Установка форка OpenHarmony Flutter

### 2.1 Почему нужно менять Flutter

**На обычном Flutter:**

```bash
flutter build -h

Обычно видны apk / appbundle / ios / web… — нет hap и HarmonyOS-app.

Сообщественный форк OpenHarmony (источники вроде openharmony-tpc/flutter_flutter — сверяйте актуальные docs) даёт:

flutter build hap    # debug / устанавливаемый HAP
flutter build app    # пакет .app для AppGallery

И поддержку в engine:

  • Platform.operatingSystem == 'ohos'
  • TargetPlatform.ohos

2.2 Как установить

FVM или ручной clone в отдельный каталог. Не перезаписывайте обычный Flutter для Android/iOS.

# Пример: отдельный OHOS Flutter через FVM (версию берите из текущих рекомендаций)
export OHOS_FLUTTER="$HOME/fvm/versions/openharmony_tpc/xxx/bin/flutter"

$OHOS_FLUTTER --version
$OHOS_FLUTTER build -h | grep -E 'hap|app'

Критерий готовности: $OHOS_FLUTTER build -h показывает и hap, и app.

2.3 Все команды HarmonyOS — только этим Flutter

# ❌ нельзя
flutter pub get
flutter build hap

```text
# ✅ нужно
$OHOS_FLUTTER pub get
$OHOS_FLUTTER build hap --debug

В IDE настройте отдельный Flutter SDK для сборок HarmonyOS, чтобы «одна кнопка» не брала неверный engine.

---

## Шаг 3. Подготовка проекта `ohos/` для существующего приложения

### 3.1 Как добавить HarmonyOS к существующему Flutter-проекту

**Типичная структура:**

```text
your_flutter_app/
├── android/
├── ios/
├── lib/
├── pubspec.yaml
└── ohos/                    # новый Stage-проект HarmonyOS
    ├── AppScope/
       └── app.json5        # bundleName, versionCode, versionName
    ├── entry/               # основной модуль (как android/app)
    ├── build-profile.json5  # подпись, compileSdk, products
    ├── hvigorfile.ts
    ├── local.properties     # локальные пути SDK / Flutter
    └── oh-package.json5

В зависимости от версии OHOS Flutter:

cd your_flutter_app
$OHOS_FLUTTER create --platforms=ohos .
# или команда «включить ohos в существующий проект» из docs вашего fork

Затем откройте каталог ohos/ в DevEco Studio (именно проект, а не просто просмотр файлов).

3.2 Проверьте три ключевых места

AppScope/app.json5

{
  "app": {
    "bundleName": "com.example.myapp",
    "vendor": "example",
    "versionCode": 100,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name"
  }
}

② product в build-profile.json5

{
  "app": {
    "products": [
      {
        "name": "default",
        "compileSdkVersion": "6.1.1(24)",
        "targetSdkVersion": "6.1.1(24)",
        "compatibleSdkVersion": "6.0.0(20)",
        "runtimeOS": "HarmonyOS",
        "signingConfig": "debug"   // позже: имя debug / release-конфига
      }
    ]
  }
}

hvigorfile.ts должен подключать Flutter-плагин

import path from 'path'
import { appTasks } from '@ohos/hvigor-ohos-plugin'
import { flutterHvigorPlugin } from 'flutter-hvigor-plugin'

```text
export default {
  system: appTasks,
  plugins: [flutterHvigorPlugin(path.dirname(__dirname))],
}

**Критерий готовности:** DevEco открывает `ohos/` с полным деревом (собрать пока не обязательно).

---

## Шаг 4. Настройка `local.properties`

В `ohos/local.properties` (пути подставьте свои):

```properties
hwsdk.dir=/Users/ВАШЕ_ИМЯ/Library/OpenHarmony/Sdk
sdk.dir=/Users/ВАШЕ_ИМЯ/Library/OpenHarmony/Sdk
flutter.sdk=/Users/ВАШЕ_ИМЯ/path/to/openharmony_tpc/flutter
flutter.versionName=1.0.0
flutter.versionCode=100

Пояснения:

  • flutter.sdkкорень OHOS-форка из шага 2 (родитель bin/flutter)
  • versionName / versionCode синхронизируйте с pubspec.yaml (x.y.z+code) и AppScope/app.json5

Критерий готовности: пути существуют, flutter.sdk/bin/flutter --version работает.


Шаг 5. Debug-подпись (иначе подписанного пакета не будет)

5.1 Автоподпись в DevEco

  1. Откройте проект ohos в DevEco
  2. FileProject StructureSigning Configs (названия меню зависят от версии)
  3. Включите автоматическую подпись, войдите в аккаунт Huawei, сгенерируйте debug-сертификат / profile
  4. Убедитесь, что в build-profile.json5 есть debug signingConfigs, а product указывает на него

5.2 Частая ловушка: нет signing/material

Симптом: SignHap с ENOENT по material. Причина: DevEco кладёт зашифрованный material в домашний каталог (напр. ~/.ohos/config/material), а проект ждёт другой путь. Решение: скопировать/сделать symlink по docs DevEco или заново выбрать пути в Signing Configs.

5.3 Release-подпись пока не трогайте

Только debug. Цель:

$OHOS_FLUTTER build hap --debug

должна дать подписанный HAP. Release — на шаге 10.

Критерий готовности: DevEco или CLI может пройти этап подписи (остальные ошибки компиляции допустимы).


Шаг 6. Переработка pubspec.yaml (самый длинный и коварный шаг)

6.1 В чём проблема

Больше всего времени на адаптацию уходит на плагины:

  • На pub.dev многие плагины имеют только android / ios / web
  • Сообщество публикует *_ohos (например на gitcode)
  • Одного foo_ohos в dependencies часто недостаточно — resolver всё равно может взять обычный foo без OHOS

Правильный подход:

  1. При необходимости объявить *_ohos
  2. Через dependency_overrides закрепить foo и foo_platform_interface (если есть) на ветку ohos

6.2 Шаблон

dependencies:
  flutter:
    sdk: flutter

```text
shared_preferences: ^2.5.4
  shared_preferences_ohos:
    git:
      url: https://gitcode.com/openharmony-tpc/flutter_packages.git
      path: packages/shared_preferences/shared_preferences_ohos
      ref: br_shared_preferences-v2.5.4_ohos   # актуальный ref у сообщества
path_provider: ^2.1.5
  path_provider_ohos:
    git:
      url: https://gitcode.com/openharmony-sig/flutter_packages.git
      path: packages/path_provider/path_provider_ohos
      ref: br_path_provider-v2.1.5_ohos
permission_handler: ^12.0.1
  permission_handler_ohos:
    git:
      url: https://gitcode.com/CPF-Flutter/flutter_permission_handler.git
      path: permission_handler_ohos
      ref: br_v12.0.1_ohos
# по необходимости:
  # audioplayers_ohos / open_file_ohos / file_picker_ohos / ветка record ohos и т.д.
dependency_overrides:
  shared_preferences:
    git:
      url: https://gitcode.com/openharmony-tpc/flutter_packages.git
      path: packages/shared_preferences/shared_preferences
      ref: br_shared_preferences-v2.5.4_ohos
path_provider:
    git:
      url: https://gitcode.com/openharmony-sig/flutter_packages.git
      path: packages/path_provider/path_provider
      ref: br_path_provider-v2.1.5_ohos
permission_handler:
    git:
      url: https://gitcode.com/CPF-Flutter/flutter_permission_handler.git
      path: permission_handler
      ref: br_v12.0.1_ohos
# platform_interface тоже override'ьте вместе с основным пакетом, например:
  # record + record_platform_interface
  # share_plus + share_plus_platform_interface
  # webview_flutter + webview_flutter_platform_interface
  # audioplayers + audioplayers_platform_interface

Зависимости всегда через OHOS Flutter:

```bash
$OHOS_FLUTTER pub get

6.3 Как понять, что ещё нужно override'ить

  1. Перечислите все плагины с нативной частью в pubspec.yaml
  2. Ищите на gitcode / openharmony-sig / openharmony-tpc / в сообществе *_ohos или br_*_ohos
  3. Если build hap падает с missing impl / MissingPluginException / ошибками анализатора — добавьте override
  4. Основной пакет и platform_interface — из одной семьи ref

6.4 Особая мина: исчерпывающий switch по TargetPlatform

В форке появился TargetPlatform.ohos. Код вида:

switch (Theme.of(context).platform) {
  case TargetPlatform.android:
  case TargetPlatform.iOS:
  // ...
  case TargetPlatform.linux:
    ...
  // нет ohos → падает анализ / сборка
}

Частые жертвы — некоторые UI-библиотеки плеера (например chewie).

Исправление:

  1. Vendor пакета в third_party/xxx
  2. Заменить exhaustive switch на if + default
  3. Направить dependency_overrides на local path
Widget build(BuildContext context) {
  final TargetPlatform platform = Theme.of(context).platform;
  if (platform == TargetPlatform.iOS) {
    return const CupertinoControls(/* ... */);
  }
  if (platform == TargetPlatform.macOS ||
      platform == TargetPlatform.windows ||
      platform == TargetPlatform.linux) {
    return const MaterialDesktopControls();
  }
  // Android / ohos / прочее → Material
  return const MaterialControls();
}

Критерий готовности: $OHOS_FLUTTER pub get успешен; анализатор больше не ругается на неполный TargetPlatform.


Шаг 7. Абстракция платформы — не размазывайте if (ohos) по всему коду

Сделайте сразу; вся дальнейшая адаптация — через неё.

7.1 Условный export (безопасно для Web)

// lib/utils/app_platform.dart
export 'app_platform_stub.dart'
    if (dart.library.io) 'app_platform_io.dart';

7.2 IO-реализация

// lib/utils/app_platform_io.dart
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';

```dart
abstract final class AppPlatform {
  AppPlatform._();
static bool get isOhos => Platform.operatingSystem == 'ohos';
  static bool get isWeb => kIsWeb;
  static String get operatingSystem => Platform.operatingSystem;
/// Подстройте флаги под продукт
  static bool get supportsFirebase =>
      Platform.isAndroid ||
      Platform.isIOS ||
      Platform.isMacOS ||
      Platform.isWindows;
static bool get supportsLocalNotifications =>
      Platform.isAndroid ||
      Platform.isIOS ||
      Platform.isLinux ||
      Platform.isWindows;
static bool get supportsInAppWebView =>
      Platform.isAndroid ||
      Platform.isIOS ||
      isOhos;
}

### 7.3 Web stub

```dart
// lib/utils/app_platform_stub.dart
import 'package:flutter/foundation.dart';

```dart
abstract final class AppPlatform {
  AppPlatform._();
static bool get isOhos => false;
  static bool get isWeb => kIsWeb;
  static String get operatingSystem => 'web';
  static bool get supportsFirebase => true;
  static bool get supportsLocalNotifications => false;
  static bool get supportsInAppWebView => false;
}

### 7.4 Сначала матрица возможностей, потом код

| Возможность | Подход на HarmonyOS | Типичная причина |
|-------------|---------------------|------------------|
| Firebase | Не инициализировать | Нет в официальном стеке |
| Локальные уведомления | Early-return в бизнес-коде | Плагин может быть, поведение — нет |
| In-app WebView | OK через fork + adapter | API может отставать от pub.dev |
| Push | Huawei Push и аналоги | Не рассчитывать на FCM |
| Часть offline-нативки | Принудительный online fallback | `.so` / engine не портированы |
| Соцлогин | Оценить; Huawei рекомендует Account Kit | Google и др. могут быть недоступны |

```dart
Future<void> initializeNotifications() async {
  if (!AppPlatform.supportsLocalNotifications) {
    debugPrint('skip local notifications on ${AppPlatform.operatingSystem}');
    return;
  }
  // init Android / iOS...
}

Критерий готовности: приложение импортирует AppPlatform, на старте отсекает неподдерживаемые SDK и не падает сразу.


Шаг 8. Первая сборка и установка на устройство

8.1 Окружение

export DEVECO_APP="/Applications/DevEco-Studio.app"
export DEVECO_SDK_HOME="$DEVECO_APP/Contents/sdk"
export OHOS_BASE_SDK_HOME="$HOME/Library/OpenHarmony/Sdk"
export OHOS_FLUTTER="$HOME/path/to/ohos-flutter/bin/flutter"
export PATH="$DEVECO_APP/Contents/tools/hvigor/bin:$DEVECO_APP/Contents/tools/ohpm/bin:$PATH"

cd your_flutter_app
$OHOS_FLUTTER pub get

8.2 Сборка debug HAP

$OHOS_FLUTTER build hap --debug

Обычный путь результата:

build/ohos/hap/entry-default-signed.hap

8.3 Установка и запуск

hdc list targets
hdc -t <deviceId> install -r build/ohos/hap/entry-default-signed.hap
hdc -t <deviceId> shell aa start -a EntryAbility -b com.example.myapp

Замените EntryAbility / com.example.myapp на значения из module.json5 / app.json5.

8.4 Как разбирать ошибки

СбойСмотреть сначала
SDK не найденШаги 1 и 4
Ошибка подписиШаг 5 Signing Configs / material
MissingPlugin / ошибка нативной сборкиШаг 6 overrides
Анализатор TargetPlatform.ohosП. 6.4 vendor-патч
Белый экран / краш при стартеШаг 7 гейтинг (Firebase и т.п.)

Критерий готовности: на устройстве открывается домашний экран (фичи могут быть неполными, но приложение стартует).


Шаг 9. Адаптация бизнес-фич (по приоритету)

Не правьте десять модулей параллельно. Рекомендуемый порядок:

9.1 Старт / отсечение крашей
9.2 Локальное хранилище
9.3 Сеть и логин
9.4 WebView / пути к файлам
9.5 Оплата и deep links
9.6 A/V, TTS, push и прочие вертикали

9.1 Старт: сначала не падать

Future<void> bootstrap() async {
  if (AppPlatform.supportsFirebase) {
    await initFirebase();
  }
  if (AppPlatform.supportsLocalNotifications) {
    await initNotifications();
  }
  // общая инициализация...
}

Правило: всё, что на Android всегда инициализируется, а на HarmonyOS нет аналога, должно быть перекрыто.

9.2 Хранилище: обёртка над SharedPreferences

Некоторые OHOS-реализации после успешной записи кидают RangeError. Общая обёртка:

Future<bool> setOhosCompatible(
  String key,
  Future<bool> Function() action,
) async {
  try {
    return await action();
  } catch (e) {
    if (AppPlatform.isOhos && e is RangeError) {
      debugPrint('OHOS preferences write quirk, treat as success: $key');
      return true;
    }
    rethrow;
  }
}

```dart
Future<bool> setString(String key, String value) {
  return setOhosCompatible(key, () => prefs.setString(key, value));
}

**Пути не копируйте с Android «в лоб»:**

```dart
Future<Directory> getAppDirectory() async {
  if (AppPlatform.isOhos) {
    final dir = Directory(
      '${Directory.systemTemp.path}${Platform.pathSeparator}my_app_cache',
    );
    if (!dir.existsSync()) {
      await dir.create(recursive: true);
    }
    return dir;
  }
  if (Platform.isIOS) {
    return getApplicationDocumentsDirectory();
  }
  return getApplicationSupportDirectory();
}

9.3 Вход через Huawei Account (рекомендуемый путь)

Google Sign-In обычно недоступен. Предпочтительно Account Kit:

  1. ArkTS-плагин — Account Kit; authCode / idToken через MethodChannel
  2. Dart-сервис — вызов channel и проверка state
  3. UI — кнопка Huawei только при AppPlatform.isOhos
  4. Бэкенд — обмен code / ID token на вашу сессию

Критично: свой плагин не попадает в GeneratedPluginRegistrant — регистрируйте вручную:

// entry/src/main/ets/entryability/EntryAbility.ets
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos'
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'
import HuaweiLoginPlugin from '../plugins/HuaweiLoginPlugin'

```text
export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)
    flutterEngine.getPlugins()?.add(new HuaweiLoginPlugin())
  }
}

**Набросок Dart:**

```dart
class HuaweiLoginService {
  static const _channel = MethodChannel('com.example.myapp/huawei_login');

```dart
Future<Map<String, String>?> auth() async {
    final state = _randomState();
    final raw = await _channel.invokeMethod<Map<dynamic, dynamic>>(
      'authById',
      {
        'forceLogin': false,
        'state': state,
        'nonce': _randomState(),
        'idTokenSignAlgorithm': 'PS256',
      },
    );
    if (raw == null) return null;
    if ((raw['errorCode'] as int? ?? -1) != 0) return null;
    if (raw['state'] != null && raw['state'] != state) return null;
    return {
      'authorizationCode': '${raw['authCode'] ?? ''}',
      'idToken': '${raw['idToken'] ?? ''}',
      'openId': '${raw['openID'] ?? ''}',
      'unionId': '${raw['unionID'] ?? ''}',
    };
  }
}

**UI:**

```dart
if (AppPlatform.isOhos)
  HuaweiLoginButton(onTap: controller.loginWithHuawei),

Ловушка уровня магазина: client_id в metadata Ability (module.json5) должен равняться appIdentifier текущего signing profile. Debug и release — разные ID. См. шаг 10.

"metadata": [
  { "name": "client_id", "value": "appIdentifier из текущего p7b profile" },
  { "name": "app_id", "value": "то же значение" }
]

9.4 WebView: слой-адаптер против дрейфа API

OHOS-форк webview_flutter может не иметь новых API pub.dev (например некоторых loadFileWithParams). Централизуйте:

class LocalHtmlLoader {
  static Future<void> loadFile({
    required WebViewController controller,
    required Uri fileUri,
  }) async {
    if (fileUri.scheme != 'file') {
      await controller.loadRequest(fileUri);
      return;
    }
    await controller.loadFile(fileUri.toFilePath());
  }
}

9.5 Оплата и deep links

  1. Настройте querySchemes и Ability skills / URI в module.json5
  2. Если платёжный SDK отдаёт маршруты без ArkTS-страниц — может понадобиться stub для сборки
  3. Продуктово сначала включайте только проверенные способы оплаты

9.6 A/V, TTS и прочая нативка

Future<void> speak(String text) async {
  if (AppPlatform.isOhos) {
    // Не грузите непортированный offline .so
    return speakWithCloudTts(text);
  }
  return speakWithOfflineEngine(text);
}

Скрывайте недоступные движки в настройках, чтобы пользователь не натыкался на краш.

Критерий готовности: логин, базовое сохранение данных и ключевые экраны работают на устройстве; неподдерживаемое явно деградирует.


Шаг 10. Release-подпись и .app для магазина

10.1 HAP vs APP

АртефактКомандаНазначение
.hapflutter build hap --releaseУстановка / бета
.appflutter build app --releaseПубликация в AppGallery

Сдавать в магазин release HAP нельзя — нужен пакет APP.

10.2 Получение и настройка release-сертификатов

  1. Создайте приложение в AppGallery Connect с тем же bundleName
  2. Закажите release-сертификат и profile (release / app_gallery)
  3. Настройте release (или своё имя) в Signing Configs DevEco
  4. Укажите его в product.signingConfig файла build-profile.json5

Минимум две конфигурации:

ИмяКогда
DebugЕжедневные сборки на устройство
ReleaseПакеты для магазина

10.3 После переключения на release сразу синхронизируйте Huawei clientId

  1. Прочитайте appIdentifier из текущего .p7b
  2. Запишите в module.json5 поля client_id / app_id
  3. Обновите строки вроде huawei_client_id, если есть
  4. На бэкенде OAuth переведите на release-учётные данные

Иначе: на debug Huawei-логин работает, всем пользователям из магазина — нет.

Автоматизируйте «смена подписи + sync clientId»; ручные правки запретите.

10.4 Сборка release APP

# 1) signingConfig = release
# 2) client_id совпадает с release profile
# 3) версии pubspec / AppScope / local.properties совпадают

```text
$OHOS_FLUTTER build app --release \
  --build-name=1.0.0 \
  --build-number=100

**Успех выглядит так:**

```text
✓ Built build/ohos/app/ohos-default-signed.app

Загрузите .app. Локально сохраните версионированный архив для отката.

10.5 Чеклист перед отправкой

  • Версии совпадают в трёх местах (pubspec / AppScope / параметры сборки)
  • Артефакт — release-подписанный .app
  • Huawei-логин проверен на release-пакете (debug не считается)
  • Оплата / возврат по deep link проверены на release
  • Деградации совпадают с продуктовым замыслом
  • Политика конфиденциальности / разрешения совпадают с карточкой магазина

Дополнительные ловушки (шпаргалка)

A. Коммерческие SDK без исходников страниц маршрутов

**Симптом:** ohpm-зависимость есть, route указывает на отсутствующий `.ts` → падает ArkTS.
**Подход:** минимальный stub-страница перед сборкой; в UI скрывать неготовые способы оплаты.

B. Зависимости HarmonyOS «протекают» в Android

Например после соцSDK падает Manifest Merger из‑за usesCleartextTraffic:

<application
    android:usesCleartextTraffic="false"
    tools:replace="android:usesCleartextTraffic">

Вывод: выбор зависимостей «ради ohos» бьёт по другим платформам — регрессируйте всю матрицу.

C. Плагин в Registrant ≠ возможность поддерживается

Уведомления в GeneratedPluginRegistrant не означают, что на HarmonyOS они работают. Обещания продукта стройте по вашим Dart-флагам supports*.

D. Цена долгоживущей второй ветки

Если основная разработка в dev, а HarmonyOS — на отдельной ветке:

  • Мержите часто, иначе отстанете на месяцы фич
  • После merge заново проверьте логин, оплату, WebView, хранилище и ручную регистрацию плагинов

Минимальный путь успеха (три вехи)

Веха A — окружение живое

  1. DevEco + корректная раскладка SDK
  2. OHOS Flutter умеет build hap
  3. DevEco открывает ohos/
  4. Debug-подпись работает

Веха B — пакет ставится

  1. Overrides в pubspec позволяют собрать проект
  2. AppPlatform + гейтинг старта: нет мгновенного краша
  3. build hap --debug ставится и запускается

Веха C — готово к магазину

  1. Ключевые сценарии работают (минимум логин + основная фича)
  2. Release-подпись + clientId выровнены
  3. build app --release даёт .app, проходящий проверки магазина

Заключение

Адаптация Flutter под HarmonyOS сложна из‑за:

  1. Смены toolchain (форк Flutter + DevEco + раскладка SDK)
  2. Пересборки цепочки плагинов (полные dependency_overrides)
  3. Переопределения границ возможностей (что поддерживать, что деградировать)
  4. Согласования release-подписи с аккаунт-системой (особенно Huawei clientId)

Идите от шага 1 к шагу 10. У каждого шага есть критерий «готово» — используйте его. Если застряли: сначала классифицируйте проблему как окружение / подпись / зависимости / гейтинг фич, и только потом снова лезьте в бизнес-код.

Удачи с первым релизным пакетом HarmonyOS для магазина.