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工程

# 使用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文件,添加鸿蒙平台支持:

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目录下安装鸿蒙依赖:

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配置示例

# 设置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 验证配置

# 验证HDC工具
hdc version
# 预期输出:hdc version 1.4.2

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

三、多终端适配配置

3.1 编译架构配置

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

{
  "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

{
  "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_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实现

#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
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/目录下创建:

import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [];
}
3.5.3 IndexPage.ets(主页面)
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项目中创建适配不同屏幕尺寸的组件:

// 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 驱动安装

# 查看连接设备
hdc list targets

# 查看设备信息
hdc device info

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

4.1.3 签名配置

在DevEco Studio中配置自动签名:

// 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 启动模拟器

# 检查模拟器状态
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):

# 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配置

创建完整的忽略规则:

# 编译产物
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模板

# 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 提交规范

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

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

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

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

六、常见问题与解决方案

6.1 编译问题

问题1:找不到RNOH头文件

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

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

问题2:架构不兼容

# 检查设备架构
hdc shell uname -m

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

6.2 运行时问题

问题3:应用白屏

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

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

问题4:热更新不生效

# 配置端口转发
hdc rport tcp:8081 tcp:8081

# 启动Metro服务
npm start

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

6.3 真机调试问题

问题5:设备连接失败

# 重启HDC服务
hdc kill
hdc start

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

问题6:安装失败

# 卸载旧版本
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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐