React Native鸿蒙跨平台实战:从项目初始化到开源交付完整指南

React Native鸿蒙跨平台实战:从项目初始化到开源交付完整指南

前言:本文聚焦React Native for OpenHarmony项目的完整落地流程,涵盖从零开始搭建工程、多设备适配验证、到开源仓库标准化交付的全过程。每个环节都附带实际踩坑经验与解决方案,帮助开发者快速掌握鸿蒙跨平台开发实战技能。

一、项目初始化:工程结构规划与基础配置

1.1 工程目录设计

在开始编码前,合理的目录结构能大幅提升后续维护效率。以下是推荐的工程结构:

复制代码
rnoh-multidevice-demo/
├── rn/                          # React Native工程目录
│   ├── src/                     # 源码目录
│   ├── package.json             # RN依赖配置
│   └── metro.config.js          # Metro打包配置
├── harmony/                     # 鸿蒙工程目录
│   ├── entry/
│   │   ├── src/main/
│   │   │   ├── cpp/             # C++原生代码
│   │   │   ├── ets/             # ArkTS代码
│   │   │   └── resources/       # 资源文件
│   │   └── build-profile.json5  # 编译配置
│   └── oh-package.json5         # 鸿蒙依赖配置
├── docs/                        # 文档目录
│   ├── screenshots/             # 运行截图
│   └── logs/                    # 日志文件
├── .gitignore                   # Git忽略配置
└── README.md                    # 项目说明

1.2 创建React Native工程

bash 复制代码
# 使用0.72.5版本(当前RNOH稳定支持版本)
npx react-native@0.72.5 init RnohMultideviceDemo --version 0.72.5

# 进入项目目录
cd RnohMultideviceDemo

# 安装鸿蒙适配包
npm install @react-native-oh/react-native-harmony@0.72.90

1.3 配置Metro打包工具

修改metro.config.js文件,添加鸿蒙平台支持:

javascript 复制代码
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require("@react-native-oh/react-native-harmony/metro.config");

const config = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: true,
            },
        }),
    },
    resolver: {
        // 添加鸿蒙平台扩展解析
        sourceExts: ['jsx', 'js', 'ts', 'tsx', 'harmony.ts'],
    }
};

module.exports = mergeConfig(
    getDefaultConfig(__dirname),
    createHarmonyMetroConfig({
        reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
    }),
    config
);

1.4 创建鸿蒙工程

  1. 打开DevEco Studio,选择「Empty Ability」模板

  2. 工程存储位置设置为RN项目根目录下的harmony文件夹

  3. 配置项目信息:

    • 包名:com.example.rnoh.multidevice
    • 最低API版本:API 20
    • 设备类型:Phone
  4. entry目录下安装鸿蒙依赖:

bash 复制代码
cd harmony/entry
ohpm install @rnoh/react-native-openharmony@0.72.90

二、SDK环境配置:全量安装与工具链集成

2.1 全量SDK安装

问题:默认安装的Public SDK缺少系统级API,导致编译时报错"找不到类/方法"。

解决方案

  1. 打开DevEco Studio,进入「File → Settings → OpenHarmony SDK」
  2. 勾选API Version 20,选择「Full SDK」
  3. 同时安装「Toolchains」和「Emulator」组件

2.2 环境变量配置

配置系统环境变量,确保工具链全局可用:

变量名 变量值 说明
OH_SDK_HOME D:\Huawei\Sdk\default\openharmony SDK根目录
HDC_SERVER_PORT 7035 HDC服务端口
RNOH_C_API_ARCH 1 启用CAPI架构
PATH追加 %OH_SDK_HOME%\toolchains HDC命令路径

PowerShell配置示例

powershell 复制代码
# 设置SDK根目录
[Environment]::SetEnvironmentVariable("OH_SDK_HOME", "D:\Huawei\Sdk\default\openharmony", "User")

# 设置HDC端口
[Environment]::SetEnvironmentVariable("HDC_SERVER_PORT", "7035", "User")

# 启用CAPI架构
[Environment]::SetEnvironmentVariable("RNOH_C_API_ARCH", "1", "User")

# 追加PATH(需要手动编辑系统环境变量)

2.3 验证配置

bash 复制代码
# 验证HDC工具
hdc version
# 预期输出:hdc version 1.4.2

# 验证CAPI变量
echo %RNOH_C_API_ARCH%
# 预期输出:1

三、多终端适配配置

3.1 编译架构配置

修改harmony/entry/build-profile.json5,支持多种CPU架构:

json5 复制代码
{
  "apiType": "stageMode",
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "arguments": "",
      "cppFlags": "-fPIC -std=c++17",
      "abiFilters": [
        "arm64-v8a",    // 真机/开发板
        "x86_64"        // 模拟器
      ]
    }
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    }
  ]
}

3.2 设备类型与权限配置

修改harmony/entry/src/main/module.json5

json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": [
      "phone",           // 手机
      "tablet",          // 平板
      "2in1"             // 二合一设备
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.GET_NETWORK_INFO"
      }
    ]
  }
}

3.3 CMakeLists.txt配置

harmony/entry/src/main/cpp/CMakeLists.txt中配置编译选项:

cmake 复制代码
cmake_minimum_required(VERSION 3.4.1)
project(RnohMultideviceDemo)

set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")

set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -fPIE -pie")
add_compile_definitions(WITH_HITRACE_SYSTRACE)

add_subdirectory("${RNOH_CPP_DIR}" ./rn)

add_library(rnoh_app SHARED
    "${CMAKE_CURRENT_SOURCE_DIR}/PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)

target_link_libraries(rnoh_app PUBLIC rnoh)

# 添加架构特定配置
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
    target_compile_definitions(rnoh_app PRIVATE ARCH_X86_64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
    target_compile_definitions(rnoh_app PRIVATE ARCH_ARM64)
endif()

3.4 PackageProvider.cpp实现

cpp 复制代码
#include "RNOH/PackageProvider.h"
#include <vector>

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    // 返回空数组,后续可添加自定义Package
    return {};
}

3.5 ArkTS层配置

3.5.1 EntryAbility.ets
typescript 复制代码
import { RNAbility } from '@rnoh/react-native-openharmony';

export default class EntryAbility extends RNAbility {
  protected getPagePath(): string {
    return "pages/IndexPage"
  }

  override onCreate(want: Want): void {
    super.onCreate(want);
  }

  override onDestroy(): void {
    super.onDestroy();
  }
}
3.5.2 创建RNPackagesFactory.ets

harmony/entry/src/main/ets/目录下创建:

typescript 复制代码
import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [];
}
3.5.3 IndexPage.ets(主页面)
typescript 复制代码
import {
  AnyJSBundleProvider,
  ComponentBuilderContext,
  FileJSBundleProvider,
  MetroJSBundleProvider,
  ResourceJSBundleProvider,
  RNApp,
  RNOHErrorDialog,
  RNOHLogger,
  TraceJSBundleProviderDecorator,
  RNOHCoreContext
} from '@rnoh/react-native-openharmony';
import { createRNPackages } from '../RNPackagesFactory';

@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {}

const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent)

@Entry
@Component
struct IndexPage {
  @StorageLink('RNOHCoreContext') private rnohContext: RNOHCoreContext | undefined = undefined
  @State shouldShow: boolean = false
  private logger!: RNOHLogger

  aboutToAppear() {
    this.logger = this.rnohContext!.logger.clone("IndexPage")
    this.shouldShow = true
  }

  onBackPress(): boolean {
    this.rnohContext!.dispatchBackPress()
    return true
  }

  build() {
    Column() {
      if (this.rnohContext && this.shouldShow) {
        if (this.rnohContext?.isDebugModeEnabled) {
          RNOHErrorDialog({ ctx: this.rnohContext })
        }
        RNApp({
          rnInstanceConfig: {
            createRNPackages,
            enableNDKTextMeasuring: true,
            enableBackgroundExecutor: false,
            enableCAPIArchitecture: true,
            arkTsComponentNames: []
          },
          initialProps: {},
          appKey: "RnohMultideviceDemo",
          wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
          onSetUp: (rnInstance) => {
            rnInstance.enableFeatureFlag("ENABLE_RN_INSTANCE_CLEAN_UP")
          },
          jsBundleProvider: new TraceJSBundleProviderDecorator(
            new AnyJSBundleProvider([
              new MetroJSBundleProvider(),
              new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'),
              new ResourceJSBundleProvider(this.rnohContext.uiAbilityContext.resourceManager, 'bundle.harmony.js')
            ]),
            this.rnohContext.logger),
        })
      }
    }
    .width('100%')
    .height('100%')
  }
}

3.6 React Native响应式布局适配

在RN项目中创建适配不同屏幕尺寸的组件:

typescript 复制代码
// rn/src/components/ResponsiveLayout.tsx
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  Dimensions,
  Platform
} from 'react-native';

const { width: screenWidth, height: screenHeight } = Dimensions.get('window');

// 设备类型判断
const getDeviceType = () => {
  if (Platform.isPad) return 'tablet';
  if (screenWidth < 600) return 'phone';
  return 'tablet';
};

export const ResponsiveLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const deviceType = getDeviceType();
  const styles = createStyles(deviceType);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>
        {deviceType === 'phone' ? '手机端' : '平板端'}布局
      </Text>
      {children}
    </View>
  );
};

const createStyles = (deviceType: string) => StyleSheet.create({
  container: {
    flex: 1,
    padding: deviceType === 'phone' ? 16 : 32,
    backgroundColor: deviceType === 'phone' ? '#f5f5f5' : '#e8f4f8',
  },
  title: {
    fontSize: deviceType === 'phone' ? 20 : 28,
    fontWeight: 'bold',
    marginBottom: 16,
  },
});

// 监听屏幕尺寸变化
export class ResponsiveScreen extends React.Component {
  state = {
    dimensions: Dimensions.get('window'),
  };

  componentDidMount() {
    Dimensions.addEventListener('change', this.handleDimensionChange);
  }

  componentWillUnmount() {
    Dimensions.removeEventListener('change', this.handleDimensionChange);
  }

  handleDimensionChange = ({ window }) => {
    this.setState({ dimensions: window });
  };

  render() {
    return (
      <ResponsiveLayout>
        <Text>屏幕宽度: {this.state.dimensions.width}</Text>
        <Text>屏幕高度: {this.state.dimensions.height}</Text>
      </ResponsiveLayout>
    );
  }
}

四、多设备运行验证

4.1 真机调试配置

4.1.1 设备准备

  1. 手机开启开发者模式:设置 → 关于手机 → 连续点击版本号7次
  2. 启用USB调试和USB安装
  3. 连接电脑,确认设备被识别

4.1.2 驱动安装

bash 复制代码
# 查看连接设备
hdc list targets

# 查看设备信息
hdc device info

# 安装应用(需先生成hap包)
hdc install entry-signed.hap

4.1.3 签名配置

在DevEco Studio中配置自动签名:

json5 复制代码
// harmony/entry/build-profile.json5
{
  "app": {
    "signingProfiles": [
      {
        "name": "default",
        "type": "HarmonyOS",
        "material": {
          "certpath": "自动生成",
          "storePassword": "自动生成",
          "keyAlias": "自动生成",
          "keyPassword": "自动生成"
        }
      }
    ]
  }
}

4.2 模拟器调试

4.2.1 创建模拟器

  1. 打开Device Manager → Emulator Manager
  2. 创建Phone模拟器,选择API 20
  3. 内存分配至少4GB

4.2.2 启动模拟器

bash 复制代码
# 检查模拟器状态
hdc list targets

# 端口转发(用于Metro热更新)
hdc rport tcp:8081 tcp:8081

4.3 证据留存规范

创建文档目录结构存放运行证据:

复制代码
docs/
├── screenshots/
│   ├── phone_main_screen.png
│   ├── tablet_layout.png
│   └── emulator_running.png
└── logs/
    ├── phone_build_log.txt
    ├── tablet_runtime_log.txt
    └── emulator_debug_log.txt

导出日志脚本(PowerShell):

powershell 复制代码
# export_logs.ps1
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$logDir = "docs/logs"
New-Item -ItemType Directory -Force -Path $logDir

# 导出编译日志
hdc shell hilog > "$logDir/build_$timestamp.txt"

# 导出运行时日志
hdc shell hilog -x > "$logDir/runtime_$timestamp.txt"

五、开源仓库标准化配置

5.1 仓库创建规范

在AtomGit/Gitee/GitHub创建仓库时遵循以下规范:

配置项 推荐值 说明
仓库名称 rnoh-multidevice-demo 小写+连字符
描述 React Native鸿蒙跨平台Demo,支持多终端运行 清晰说明项目用途
许可证 Apache-2.0 OpenHarmony官方推荐
默认分支 main 现代Git规范

5.2 .gitignore配置

创建完整的忽略规则:

gitignore 复制代码
# 编译产物
build/
.ohos/
entry/build/
*.hap
*.app

# IDE配置
.idea/
.vscode/
*.iml
.cxx/

# 依赖包
node_modules/
oh_modules/

# 日志文件
*.log
hilog/

# 临时文件
.DS_Store
Thumbs.db
*~
*.swp
*.swo

# 测试覆盖率
coverage/
.nyc_output/

# 打包文件
*.tar.gz
*.zip

5.3 README.md模板

markdown 复制代码
# RNOH多设备适配示例

React Native for OpenHarmony多终端适配示例项目,支持手机、平板、模拟器运行。

## 运行环境

- Node.js: 16+
- DevEco Studio: 6.0+
- OpenHarmony SDK: API 20
- React Native: 0.72.5

## 快速开始

### 安装依赖

\`\`\`bash
# RN侧依赖
cd rn
npm install

# 鸿蒙侧依赖
cd ../harmony/entry
ohpm install
\`\`\`

### 生成Bundle

\`\`\`bash
cd rn
npm run harmony
\`\`\`

### 运行项目

1. 用DevEco Studio打开`harmony`目录
2. 选择目标设备(真机/模拟器)
3. 点击运行按钮

## 项目结构

\`\`\`
rnoh-multidevice-demo/
├── rn/           # React Native工程
├── harmony/      # 鸿蒙工程
└── docs/         # 文档与运行证据
\`\`\`

## 支持设备

- 华为/荣耀手机(HarmonyOS 4.0+)
- 平板设备
- DevEco Studio模拟器

## 常见问题

### 签名错误
在DevEco Studio中选择自动签名配置。

### bundle文件未生成
确保`metro.config.js`配置正确,重新执行`npm run harmony`。

## 许可证

Apache-2.0

5.4 提交规范

bash 复制代码
# 功能开发
git commit -m "feat: 添加平板布局适配"

# 问题修复
git commit -m "fix: 解决模拟器白屏问题"

# 文档更新
git commit -m "docs: 更新README运行说明"

# 配置修改
git commit -m "build: 更新SDK版本到API 20"

六、常见问题与解决方案

6.1 编译问题

问题1:找不到RNOH头文件

cmake 复制代码
# 检查CMakeLists.txt中的路径配置
message("OH_MODULE_DIR: ${OH_MODULE_DIR}")
message("RNOH_CPP_DIR: ${RNOH_CPP_DIR}")

# 确保路径正确指向oh_modules目录

问题2:架构不兼容

bash 复制代码
# 检查设备架构
hdc shell uname -m

# 根据设备架构调整abiFilters配置
# aarch64 → arm64-v8a
# x86_64 → x86_64

6.2 运行时问题

问题3:应用白屏

typescript 复制代码
// 检查appKey是否匹配
// rn/index.js
AppRegistry.registerComponent('RnohMultideviceDemo', () => App);

// harmony/IndexPage.ets
appKey: "RnohMultideviceDemo"  // 必须一致

问题4:热更新不生效

bash 复制代码
# 配置端口转发
hdc rport tcp:8081 tcp:8081

# 启动Metro服务
npm start

# 在Metro界面按r键重新加载

6.3 真机调试问题

问题5:设备连接失败

bash 复制代码
# 重启HDC服务
hdc kill
hdc start

# 检查USB调试是否开启
hdc list targets

问题6:安装失败

bash 复制代码
# 卸载旧版本
hdc uninstall com.example.rnoh.multidevice

# 清理缓存
hdc shell rm -rf /data/storage/el2/base/files/*

七、总结

通过本指南,我们完成了:

  1. ✅ React Native鸿蒙工程的初始化与配置
  2. ✅ 多终端(手机/平板/模拟器)的适配配置
  3. ✅ 响应式布局的实现
  4. ✅ 开源仓库的标准化配置
  5. ✅ 常见问题的解决方案

关键要点回顾

  • 使用Full SDK确保API完整性
  • 配置多架构支持实现跨设备运行
  • 规范的Git提交和文档提升项目可维护性
  • 完整的证据留存便于技术分享

下一步学习建议

  • 深入学习TurboModule自定义原生模块
  • 掌握Fabric组件开发
  • 探索RNOH性能优化技巧

参考资源:

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

相关推荐
冬奇Lab10 小时前
一天一个开源项目(第53篇):PDF 补丁丁 - 功能全面的 PDF 工具箱,编辑书签、解除限制、合并拆分、OCR 识别
开源·资讯
Arya_aa10 小时前
Mysql数据库-管理和存储数据库(开源管理系统)与JDBC操作数据库步骤,JUnit以及如何将压缩包中exe程序添加上桌面图标
数据库·mysql·junit·开源
国医中兴11 小时前
Flutter 三方库 stack_blur 鸿蒙适配指南 - 实现工业级高性能模糊滤镜、在 OpenHarmony 上打造极致视觉质感实战
flutter·华为·harmonyos
沐曦股份MetaX12 小时前
再升级!沐曦股份 GPU 接入华佗开源生态!
开源
aiAIman13 小时前
OpenClaw 生态主流 AI 模型真实性能 PinchBench深度解读(基于2026年3月12日测评数据)
人工智能·开源·aigc
IvorySQL14 小时前
官宣!全球 PostgreSQL 大神再度集结,HOW 2026 正式定档
数据库·postgresql·开源
Swift社区17 小时前
AI 原生鸿蒙应用开发实战
人工智能·华为·harmonyos
盐焗西兰花17 小时前
鸿蒙学习实战之路-Share Kit系列(12/17)-判断应用是否被系统分享拉起
前端·学习·harmonyos