从零学习RN for OpenHarmony踩坑日记(三)
打开DevEco Studio,点击,选择创建工程,如图所示:点击Next按钮,创建一个名为 “MyApplication” 的项目。
创建鸿蒙工程
一、新建项目
打开DevEco Studio,点击 File > New > Create Project,选择创建 Empty Ability 工程,如图所示:
点击 Next 按钮,创建一个名为 “MyApplication” 的项目。如图所示:

二、新建模拟器(有真机的可以忽略这步用真机调试)
点击右上角No devices,在在下拉列表中选择device manger
点击下方模拟器保存路径进行配置,不建议放在C盘,因为会占用较大存储空间。配置完本地保存路径后,点击右侧New emulator进行新增模拟器。

选择和新建项目sdk版本对应的phone模拟器,这里我用的sdk版本是HarmonyOS 6.0.2(22),因此我选择第一个,点击action下的下载按钮会开始下载模拟器镜像。
请注意:如果在下载镜像期间报错说网络错误,DNS解析失败,这种情况一般是由于上次下载没有完全下载完毕就断开了导致的,需要清空模拟器路径中的所有文件,重启DevEco Studio重新加载即可。

下载完毕后点击next,配置其他选项,也可以不改使用默认值。配置完毕后可以看到新建的这个模拟器,点击三角形按钮可以启动。


三、真机调试
请注意,此次是官方文档说明,由于本人没有鸿蒙设备,没有经过验证。
连接真机,点击 File > Project Structure,在弹窗界面点击 Signing Configs,勾选 Support HarmonyOS 和 Automatically generate signature,然后点击 Sign In 登录华为账号,并签名。

四、添加 React Native 配置
在 entry 目录下执行以下命令:
ohpm i @rnoh/react-native-openharmony
执行完成后会在工程级目录以及模块级目录下生成 oh_modules 文件夹。
请注意:由于文件较大,下载时间可能比较长,请耐心等待。
五、补充CPP侧代码
- 在
MyApplication/entry/src/main目录下新建 cpp 文件夹。 - 在 cpp 目录下新增
CMakeLists.txt,并将 RNOH 的适配层代码添加到编译构建中生成librnoh_app.so:project(rnapp) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_SKIP_BUILD_RPATH TRUE) set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules") set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp") set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments") set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie") add_compile_definitions(WITH_HITRACE_SYSTRACE) set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use add_subdirectory("${RNOH_CPP_DIR}" ./rn) add_library(rnoh_app SHARED "./PackageProvider.cpp" "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" ) target_link_libraries(rnoh_app PUBLIC rnoh) - 在 cpp 目录下新增
PackageProvider.cpp,该文件需要满足以下要求:- 需要导入
RNOH/PackageProvider; - 实现
getPackages方法,用于创建三方库或自定义 TurboModule 或 Fabric 的 package 对象。
#include "RNOH/PackageProvider.h" using namespace rnoh; std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) { return {}; } - 需要导入
- 打开
MyApplicaton\entry\build-profile.json5,将 cpp 中的代码添加到应用工程的编译构建任务中;如果在x86_64架构的模拟器上运行应用,需在externalNativeOptions配置中额外添加abiFilters字段,并包含x86_64架构参数,如下所示,abiFilters字段当前被注释,默认仅构建适用于arm64-v8a架构的版本。目前我使用的模拟器是无需这行配置。{ "apiType": "stageMode", "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + // "abiFilters": ["arm64-v8a", "x86_64"] + } }, "targets": [ { "name": "default" }, { "name": "ohosTest", } ] }
六、补充ArkTS侧的代码
-
打开
MyApplicaton\entry\src\main\ets\entryability\EntryAbility.ets,引入并使用RNAbility,该文件需要满足以下的要求:- 需要重写
getPagePath,返回程序的入口 page。
import { RNAbility } from '@rnoh/react-native-openharmony'; export default class EntryAbility extends RNAbility { getPagePath() { return 'pages/Index'; } }- 如果需要扩展使用对应的生命周期函数
- 请在代码中调用
super(由于RNAbility在生命周期函数中进行了对应的操作,因此建议使用super以确保原有功能不丢失)。 - 需确保函数的参数列表与父类保持兼容。
- 建议添加
override关键字,以提升代码可读性并增强编译器检查。
- 请在代码中调用
import { RNAbility } from '@rnoh/react-native-openharmony'; export default class EntryAbility extends RNAbility { getPagePath() { return 'pages/Index'; } override onCreate(want: Want): void { super.onCreate(want); hilog.info(0x0000, 'testTag', '%{public}s', 'EntryAbility onCreate'); } } - 需要重写
-
在
MyApplicaton\entry\src\main\ets目录下新增RNPackagesFactory.ets,该文件需要满足以下要求:- 在
@rnoh/react-native-openharmony导入RNPackageContext和RNPackage; - 在文件中导出
createRNPackages方法,用于创建三方库或自定义 TurboModule、Fabric的package 对象。
此处不涉及三方库与自定义TurboModule或组件,需要返回空数组。
import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts'; export function createRNPackages(ctx: RNPackageContext): RNPackage[] { return []; } - 在
-
打开
MyApplicaton\entry\src\main\ets\pages\Index.ets,添加RNOH的使用代码,修改后如下:RNApp的参数appKey需要与RN工程中AppRegistry.registerComponent注册的appName保持一致,否则会导致白屏。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 Index { @StorageLink('RNOHCoreContext') private rnohCoreContext: RNOHCoreContext | undefined = undefined @State shouldShow: boolean = false private logger!: RNOHLogger aboutToAppear() { this.logger = this.rnohCoreContext!.logger.clone("Index") const stopTracing = this.logger.clone("aboutToAppear").startTracing(); this.shouldShow = true stopTracing(); } onBackPress(): boolean | undefined { // NOTE: this is required since `Ability`'s `onBackPressed` function always // terminates or puts the app in the background, but we want Ark to ignore it completely // when handled by RN this.rnohCoreContext!.dispatchBackPress() return true } build() { Column() { if (this.rnohCoreContext && this.shouldShow) { if (this.rnohCoreContext?.isDebugModeEnabled) { RNOHErrorDialog({ ctx: this.rnohCoreContext }) } RNApp({ rnInstanceConfig: { createRNPackages, enableNDKTextMeasuring: true, // 该项必须为true,用于开启NDK文本测算 enableBackgroundExecutor: false, enableCAPIArchitecture: true, // 该项必须为true,用于开启CAPI arkTsComponentNames: [] }, initialProps: { "foo": "bar" } as Record<string, string>, appKey: "AwesomeProject", wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder, onSetUp: (rnInstance) => { rnInstance.enableFeatureFlag("ENABLE_RN_INSTANCE_CLEAN_UP") }, jsBundleProvider: new TraceJSBundleProviderDecorator( new AnyJSBundleProvider([ new MetroJSBundleProvider(), // NOTE: to load the bundle from file, place it in // `/data/app/el2/100/base/com.rnoh.tester/files/bundle.harmony.js` // on your device. The path mismatch is due to app sandboxing on OpenHarmony new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'), new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'hermes_bundle.hbc'), new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js') ]), this.rnohCoreContext.logger), }) } } .height('100%') .width('100%') } }
七、加载bundle包
我们在从零学习RN for OpenHarmony踩坑日记(二)https://blog.csdn.net/gaojw07/article/details/157292044中已经生成了bundle,此处只需要将其粘贴进入entry/src/main/resources/rawfile 路径下即可,并在 entry/src/main/ets/pages/Index.ets 中使用。

八、启动并运行工程
启动模拟器,然后点击右上角启动按钮即可启动工程。

错误:
16:41:54.307: Build task in 1 min 30 s 229 ms
16:41:54.309: Launching com.example.myapplication
16:41:54.312: $ hdc shell aa force-stop com.example.myapplication
16:41:54.578: $ hdc shell mkdir data/local/tmp/243d1319bd334876babe313110e563b7
16:41:55.315: $ hdc file send C:\Users\13650\DevEcoStudioProjects\MyApplication\entry\build\default\outputs\default\entry-default-signed.hap "data/local/tmp/243d1319bd334876babe313110e563b7" in 737 ms
16:41:55.711: $ hdc shell bm install -p data/local/tmp/243d1319bd334876babe313110e563b7 in 395 ms
Install Failed: error: failed to install bundle.
code:9568332
error: install sign info inconsistent.
View detailed instructions.
You can also uninstall and reinstall the modules.
16:41:55.820: $ hdc shell rm -rf data/local/tmp/243d1319bd334876babe313110e563b7
16:41:55.823: Launch com.example.myapplication failed, starting handle failure progress
Error while Deploy Hap
错误原因:
该问题是由于设备上已安装的应用与新安装的应用中签名不一致。如果在Run->Edit Configurations中勾选了“Keep Application Data”(不卸载应用,覆盖安装),并且重新进行了签名,将导致该报错。
解决方案:
请卸载设备上已安装的应用,或取消勾选“Keep Application Data”后,重新安装新的应用。
解决后启动成功。

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



所有评论(0)