1.0.0-rc.0 • Published 5 months ago

rn_hmfeatures v1.0.0-rc.0

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

rn_hmfeatures

介绍

这是一个旨在解决React Native页面与OpenHarmonyOS特性特征不一致问题,专为React Native页面提供OpenHarmony特征。该库包含的接口和开箱即用的组件,使开发者能够在React Native页面轻松应用各种OpenHarmony特征。

工程目录

├─harmony
│  ├─rn_hmfeatures.har
│  └─rn_hmfeatures
│     └─src
│        └─main
│           └─cpp          // OpenHarmony侧CAPI实现Fabric组件
│              ├─CMakeLists.txt
│              ├─GeometryViewComponentDescriptor.h
│              ├─GeometryViewComponentInstance.cpp
│              ├─GeometryViewComponentInstance.h
│              ├─GeometryViewEventEmitter.cpp
│              ├─GeometryViewEventEmitter.h
│              ├─GeometryViewJSIBinder.h
│              ├─GeometryViewNode.cpp
│              ├─GeometryViewNode.h
│              ├─GeometryViewPackage.cpp
│              ├─GeometryViewPackage.h
│              ├─Props.cpp
│              └─Props.h
└─src
   ├─index.tsx
   └─fabric
      └─GeometryView.tsx   // RN 侧Fabric组件

安装与使用

请拉取rn_hmfeatures代码仓并执行npm pack获取tgz包。

进入到工程目录并输入以下命令:

说明: #处替换为tgz包的路径

npm

npm install rn_hmfeatures@file:#

yarn

yarn add rn_hmfeatures@file:#

下面的代码展示了这个库的基本使用场景:ArkUI的navigation控制路由跳转,NavDestination加载对应的RN bundle。

PlayList页面

使用了GeometryView组件,并设置了geometryViewID为'test',点击事件调用原生navPathStack.pushPath,跳转MusicPlay页面。

function PlayList() {
  return (
    <SafeAreaView style={styles.container}>
      <GeometryView
        style={[styles.geometryView, { top: 100, left: 100 }]} 
        geometryViewID={'test'}
        onGeometryViewClick={() => {
          SampleTurboModule.pushStringToHarmony('pages/MusicPlay', 1);
        }}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%',
    height: '100%',
  },
  geometryView: {
    position: 'absolute', 
    width: 60,
    height: 60,
    backgroundColor: 'red',
  },
});

export default PlayList;

MusicPlay页面

function MusicPlay() {
  return (
    <SafeAreaView style={styles.container}>
      <GeometryView style={{ width: 200, height: 200, backgroundColor: 'red' }} geometryViewID={'test'} onGeometryViewClick={() => {
        SampleTurboModule.pushStringToHarmony('pop', 2)
      }} >
      </GeometryView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%',
    height: '100%'
  },
  text: {
    fontSize: 18,
    color: '#333',
  },
});

export default MusicPlay;

原生侧

PlayListPage监听RN页面跳转事件,如果事件触发,调用this.navPathStack.pushPath({ name: 'MusicPlayPage' }),跳转至原生MusicPlayPage页面。

@Component
export default struct PlayListPage {
  private instance: RNInstance = LoadManager.instance;
  private bundlePath = 'bundle/playlist.harmony.bundle'
  private moduleName = 'PlayList'
  @StorageLink('isMetroAvailable') isMetroAvailable: boolean = false
  @Consume('navPathStack') navPathStack: NavPathStack

  aboutToAppear() {
    emitter.on({ eventId: 1 }, () => {
      animateTo({duration: 700, curve: Curve.Friction}, () => {
        this.navPathStack.pushPath({ name: 'MusicPlayPage' })
      });
    });
  }

  aboutToDisappear() {
    emitter.off(1);
  }

  build() {
    NavDestination() {
      if (this.isMetroAvailable) {
        MetroBaseRN({
          moduleName: this.moduleName,
        }).align(Alignment.Top).margin({ top: 0 })
      } else if (this.instance) {
        BaseRN({
          rnInstance: this.instance,
          moduleName: this.moduleName,
          bundlePath: this.bundlePath,
        }).align(Alignment.Top).margin({ top: 0 })
      } else {
        Text('加载失败')
      }
    }
    .hideTitleBar(true)
  }
}

MusicPlayPage加载RN侧MusicPlay页面

@Component
export default struct MusicPlayPage {
  private instance: RNInstance = LoadManager.instance
  private bundlePath = 'bundle/musicplay.harmony.bundle'
  private moduleName = 'MusicPlay'
  @StorageLink('isMetroAvailable') isMetroAvailable: boolean = false
  @Consume('navPathStack') navPathStack: NavPathStack

  aboutToAppear() {
    emitter.on({ eventId: 2 }, () => {
      animateTo({duration: 700, curve: Curve.Friction}, () => {
        this.navPathStack.pop()
      });
    });
  }

  aboutToDisappear() {
    emitter.off(2);
  }

  build() {
    NavDestination() {
      if (this.isMetroAvailable) {
        MetroBaseRN({
          moduleName: this.moduleName,
        })
          .align(Alignment.Top).margin({ top: 20 })
      } else if (this.instance) {
        BaseRN({
          rnInstance: this.instance,
          moduleName: this.moduleName,
          bundlePath: this.bundlePath,
        }).align(Alignment.Top).margin({ top: 20 })
      } else {
        Text('加载失败')
      }
    }
    .geometryTransition('test')   // 设置同RN侧一致的id
    .hideTitleBar(true)
  }
}

Link

目前OpenHarmony暂不支持AutoLink,所以Link步骤需要手动配置。

首先需要使用DevEco Studio打开项目里的OpenHarmony工程,在工程根目录的 oh-package.json5 添加 overrides 字段:

{
  ...
  "overrides": {
    "@rnoh/react-native-openharmony" : "./react_native_openharmony"
  }
}

引入原生端代码

目前有两种方法:

  1. 通过har包引入(在IDE完善相关功能后该方法会被遗弃,目前首选此方法)。

    说明: har包位于三方库安装路径的harmony文件夹下。

    a.打开entry/oh-package.json5,添加以下依赖:

    "dependencies": {
        "@rnoh/react-native-openharmony": "file:../react_native_openharmony",
        "rn_hmfeatures": "file:../../node_modules/rn_hmfeatures/harmony/rn_hmfeatures.har",
      }

    b.配置CMakeLists和引入GeometryViewPackage:

    打开entry/src/main/cpp/CMakeLists.txt,添加:

    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("${OH_MODULE_DIR}/rn_hmfeatures/src/main/cpp" ./rn_hmfeatures)
    
    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)
    + target_link_libraries(rnoh_app PUBLIC rn_hmfeatures)

    c.打开entry/src/main/cpp/PackageProvider.cpp,添加:

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

    d.运行:

    点击右上角的sync按钮

    或者在终端执行:

    cd entry
    ohpm install

    然后编译、运行即可。

  2. 直接链接源码。

    如需使用直接链接源码,请参考直接链接源码说明

API

说明: "Platform"列表示支持的平台,All表示支持所有平台。

NameDescriptionTypePlatform
geometryViewID共享元素ID.stringOpenHarmony
onGeometryViewClick点击GeometryView回调.callbackOpenHarmony