前言
由于项目需求,组件需要支持 iOS、Android 和 HarmonyOS 三端,碰巧 React Native (RN) 的鸿蒙适配开源了,所以决定尝试使用 RN 来开发三端 App。这份踩坑日记记录了在适配 HarmonyOS 过程中遇到的问题和解决方法,供大家参考。
环境搭建以及项目初始化
环境搭建和项目初始化过程相对简单,按照 ohos_react_native 的官方文档可以顺利完成。
第三方插件的适配
起初,使用了 @react-native-oh-tpl/react-native-gesture-handler、 @react-native-oh-tpl/react-native-safe-area-context 和 @react-native-oh-tpl/stack 等库。这些库的适配较好,可以参考 官方文档进行使用。
然而,在集成 @react-native-oh-tpl/react-native-doc-viewer 这个库时,出现了问题。
问题
首先,根据文档执行了以下操作:
// 三方适配的库都是要指定版本的,在制定版本上fork改造的
npm i react-native-doc-viewer@2.7.8
接着,安装鸿蒙适配版本的类库:
// 根据自己tgz包的文件来改
npm i @react-native-oh-tpl/react-native-doc-viewer@file:../react-native-harmony-packages/react-native-oh-tpl-react-native-doc-viewer-2.7.8-0.0.2.tgz
在代码中尝试调用库的方法:
const handlePreview = async () => {
if (Platform.OS === 'ios') {
//IOS
OpenFile.openDoc(
[
{
url: 'https://xxxxxxxx',
fileNameOptional: 'test',
},
],
(error, url) => {
if (error) {
console.error(error);
} else {
console.log(url);
}
},
);
} else {
//Android
OpenFile.openDoc(
[
{
url: 'https://xxxxxxxx', // Local "file://" + filepath
fileName: 'test',
cache: false,
fileType: 'pptx',
},
],
(error, url) => {
if (error) {
console.error(error);
} else {
console.log(url);
}
},
);
}
};
然而,满怀期待打开 App 后,却发现那经典的一幕:
Uncaught Error TurboModuleRegistry.getEnforcing(...):'RNCDocViewercould not be found. Verify that a module by this name isregistered in the native binary
解决方法
经过一番源码分析和对 ohos_react_native 的文档研究,发现该库仅适配了 TurboModule
,但缺乏 cxxTurboModule
的适配代码。因此,我们需要手动为 cxxTurboModule
进行适配。
在 @react-native-oh-tpl/react-native-doc-viewer/src
目录下创建 cpp
文件夹,并添加以下文件:
- DocViewerTurboModule.h
#pragma once
#include "RNOH/ArkTSTurboModule.h"
namespace rnoh {
class JSI_EXPORT DocViewerTurboModule : public ArkTSTurboModule {
public:
DocViewerTurboModule(const ArkTSTurboModule::Context ctx, const std::string name);
};
}
- DocViewerTurboModule.cpp
#include "DocViewerTurboModule.h"
#include "RNOH/ArkTSTurboModule.h"
using namespace rnoh;
using namespace facebook;
static jsi::Value __hostFunction_DocViewerTurboModule_openDoc(jsi::Runtime &rt, react::TurboModule &turboModule,
const jsi::Value *args, size_t count) {
return jsi::Value(static_cast<ArkTSTurboModule &>(turboModule).call(rt, "openDoc", args, count));
}
// 其他方法定义省略...
DocViewerTurboModule::DocViewerTurboModule(const ArkTSTurboModule::Context ctx, const std::string name)
: ArkTSTurboModule(ctx, name) {
methodMap_["openDoc"] = MethodMetadata{0, __hostFunction_DocViewerTurboModule_openDoc};
}
- DocViewerPackage.h
#include "RNOH/Package.h"
#include "DocViewerTurboModule.h"
namespace rnoh {
class DocViewerPackage : public Package {
public:
DocViewerPackage(Package::Context ctx) : Package(ctx) {}
std::unique_ptr<TurboModuleFactoryDelegate> createTurboModuleFactoryDelegate() override {
return std::make_unique<NativeRTCDocViewerFactoryDelegate>();
}
};
}
- CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
file(GLOB rnoh_doc_viewer_SRC CONFIGURE_DEPENDS *.cpp)
add_library(rnoh_doc_viewer SHARED ${rnoh_doc_viewer_SRC})
target_include_directories(rnoh_doc_viewer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(rnoh_doc_viewer PUBLIC rnoh)
更新鸿蒙工程配置
在鸿蒙工程的 CMakeLists.txt 中添加:
add_subdirectory("类库cpp文件夹路径" ./doc-viewer)
target_link_libraries(rnoh_app PUBLIC rnoh_doc_viewer)
并在 PackageProvider.cpp 中增加以下代码:
#include "DocViewerPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
// 增加的代码
std::make_shared<DocViewerPackage>(ctx)
};
}
至此,问题解决,成功适配了 @react-native-oh-tpl/react-native-doc-viewer 到 HarmonyOS。
效果
最后
放上我对这个库的pr