编写原生代码
  1. 创建用于实现模块的 CalculatorModule.ts

    entry/src/main/ets 路径下新建文件夹 turbomodule,并在文件夹中新增 CalculatorModule.ts
    如果是 ArkTSTurboModule,需要在此处实现:

    // entry/src/main/ets/turbomodule/CalculatorModule.ts
    import { AnyThreadTurboModule, UITurboModule } from '@rnoh/react-native-openharmony/ts';
    import { TM } from '@rnoh/react-native-openharmony/generated/ts';
    
    export class CalculatorModule extends UITurboModule implements TM.RTNCalculator.Spec {
      add(a: number, b: number): Promise<number>{
        return Promise.resolve(a+b);
      }
    }
    

    如果是 cxxTurboModule,不需要在此处实现,只需保证函数的参数类型和返回类型正确即可:

    // entry/src/main/ets/turbomodule/CalculatorModule.ts
    import { AnyThreadTurboModule, UITurboModule } from '@rnoh/react-native-openharmony/ts';
    import { TM } from '@rnoh/react-native-openharmony/generated/ts';
    
    export class CalculatorModule extends UITurboModule implements TM.RTNCalculator.Spec {
      add(a: number, b: number): Promise<number>{
        return Promise.resolve(123456);
      }
    }
    
  2. 创建 Package 的实现文件 GeneratedPackage.ets

    entry/src/main/ets 路径下新建 GeneratedPackage.ets,并添加对应的实现代码:

    // entry/src/main/ets/GeneratedPackage.ets
    import {
      RNOHPackage,
      AnyThreadTurboModule,
      AnyThreadTurboModuleContext,
      UITurboModule,
      UITurboModuleContext
    } from '@rnoh/react-native-openharmony';
    
    import { TM } from "@rnoh/react-native-openharmony/generated"
    import { CalculatorModule } from './turbomodule/CalculatorModule';
    
    export default class GeneratedPackage extends RNOHPackage {
      override getUITurboModuleFactoryByNameMap(): Map<string, (ctx: UITurboModuleContext) => UITurboModule | null> {
        return new Map<string, ((ctx: UITurboModuleContext) => UITurboModule)>()
          .set(TM.RTNCalculator.NAME, (ctx) => new CalculatorModule(ctx))
      }
    
      override async createEagerUITurboModuleByNameMap(ctx: UITurboModuleContext): Promise<Map<string, UITurboModule>> {
        const calculatorModule = new CalculatorModule(ctx);
        return new Map()
          .set(TM.RTNCalculator.NAME, calculatorModule)
      }
    }
    

    需要注意的是:

    • 文件中应该使用 export default 导出一个继承了 RNOHPackage 的类
    • 重写父类方法 getUITurboModuleFactoryByNameMap()createEagerUITurboModuleByNameMap()
    • entry/src/main/ets/RNPackagesFactory.ets 中添加创建该 Package 的方法:
      import { RNOHPackage, RNPackageContext } from '@rnoh/react-native-openharmony';
      import  GeneratedPackage  from './GeneratedPackage';
      
      export function createRNPackages(ctx: RNPackageContext): RNOHPackage[] {
        return [
          new GeneratedPackage(ctx)
        ];
      }
      
  3. 如果是 CxxTurboModule,需要一些额外步骤:

    什么是:CxxTurboModule,请参考React Native 中文网

    以 CalculatorModule 为例,展开胶水代码文件 RTNCalculator.cpp 中的宏 ARK_ASYNC_METHOD_METADATA:

    #include "RTNCalculator.h"
    
    namespace rnoh {
    using namespace facebook;
    
    RTNCalculator::RTNCalculator(const ArkTSTurboModule::Context ctx, const std::string name) : ArkTSTurboModule(ctx, name) {
        methodMap_ = {
    -       ARK_ASYNC_METHOD_METADATA(add, 2),
    +       { "add",
    +         { 2,
    +           [] (facebook::jsi::Runtime& rt, facebook::react::TurboModule& turboModule, const facebook::jsi::Value* args, size_t count) {
    +             return static_cast<ArkTSTurboModule&>(turboModule).callAsync(rt, "add", args, count);
    +           } 
    +         } 
    +       }
        };
    }
    
    } // namespace rnoh
    
    

    删除 lambda 表达式中对 ArkTSTurboModule 的异步桥接调用,改为直接实现。

    #include "RTNCalculator.h"
    
    namespace rnoh {
    using namespace facebook;
    
    RTNCalculator::RTNCalculator(const ArkTSTurboModule::Context ctx, const std::string name) : ArkTSTurboModule(ctx, name) {
        methodMap_ = {
           { "add",
             { 2,
               [] (facebook::jsi::Runtime& rt, facebook::react::TurboModule& turboModule, const facebook::jsi::Value* args, size_t count) {
    -             return static_cast<ArkTSTurboModule&>(turboModule).callAsync(rt, "add", args, count);
    +             return jsi::Value(args[0].asNumber() + args[1].asNumber());
               } 
             } 
           }
        };
    }
    
    } // namespace rnoh
    
    
  4. 添加胶水代码。根据您所使用的 Codegen 版本不同,有2种操作方式:

v1版本
  1. CMakeLists.txt 中添加新增的胶水代码文件

    entry/src/main/cpp/CMakeLists.txt 中定义 cpp 的 generated 路径,并添加到编译构建中:

    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)
    
    # RNOH_BEGIN: add_package_subdirectories
    add_subdirectory("${OH_MODULE_DIR}/@rnoh/sample-package/src/main/cpp" ./sample-package)
    # RNOH_END: add_package_subdirectories
    
    + file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
    add_library(rnoh_app SHARED
    +     ${GENERATED_CPP_FILES}
        "./PackageProvider.cpp"
        "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
    )
    
    target_link_libraries(rnoh_app PUBLIC rnoh)
    
    # RNOH_BEGIN: link_packages
    target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
    # RNOH_END: link_packages
    
  2. entry/src/main/cpp/PackageProvider.cpp 中创建 cpp 侧的 package 对象:

    #include "RNOH/PackageProvider.h"
    #include "SamplePackage.h"
    + #include "generated/RNOHGeneratedPackage.h"
    
    using namespace rnoh;
    
    std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
        return {
    +         std::make_shared<RNOHGeneratedPackage>(ctx), 
            std::make_shared<SamplePackage>(ctx)
        };
    }
    
v2版本
  1. CMakeLists.txt 中添加新增的胶水代码文件

    在这一步,需要在 CMake 文件中把 Codegen 生成的文件分别使用 add_librarytarget_include_directories 添加到编译构建的任务中:

    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)
    
    # RNOH_BEGIN: add_package_subdirectories
    add_subdirectory("${OH_MODULE_DIR}/@rnoh/sample-package/src/main/cpp" ./sample-package)
    # RNOH_END: add_package_subdirectories
    
    + set(rtn_calculator_generated_dir "${RNOH_GENERATED_DIR}/rtn_calculator")
    + file(GLOB_RECURSE rtn_calculator_generated_dir_SRC "${rtn_calculator_generated_dir}/**/*.cpp")
    + file(GLOB rtn_calculator_package_SRC CONFIGURE_DEPENDS *.cpp)
    add_library(rnoh_app SHARED
    +     ${rtn_calculator_generated_dir_SRC}
    +     ${rtn_calculator_package_SRC}
        "./PackageProvider.cpp"
        "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
    )
    
    + target_include_directories(rnoh_app PUBLIC ${rtn_calculator_generated_dir})
    
    target_link_libraries(rnoh_app PUBLIC rnoh)
    
    # RNOH_BEGIN: link_packages
    target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
    # RNOH_END: link_packages
    
  2. entry/src/main/cpp/PackageProvider.cpp 中创建 cpp 侧的 package 对象:

    #include "RNOH/PackageProvider.h"
    #include "SamplePackage.h"
    + #include "generated/rtn_calculator/RNOH/generated/BaseRtnCalculatorPackage.h"
    
    using namespace rnoh;
    
    std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
        return {
            std::make_shared<SamplePackage>(ctx),
    +         std::make_shared<BaseRtnCalculatorPackage>(ctx)
        };
    }
    

打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

在这里插入图片描述

最后运行效果图如下显示:

请添加图片描述

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐