鴻蒙開發(fā)harmonyos集成react native

上一篇文章說下載鴻蒙開發(fā)工具,今天開始實踐了

1. 新建rn項目(mac端)

npx react-native@0.72.5 init AwesomeProject --version 0.72.5

或者使用如下命令,跳過其他node_modules的安裝過程,因為暫時不需要依賴庫,但是網(wǎng)速好的情況下,還是建議用上面的命令,一次安裝成功

npx react-native@0.72.5 init AwesomeProject --version 0.72.5 --skip-install

init之后的文件夾如圖所示,這里只有ios和android文件夾,我的理解應(yīng)該有個harmony文件夾放著鴻蒙的項目才對,讓我們接著往下看


image.png

2.下載安裝鴻蒙依賴

在react native項目的package.json文件內(nèi)添加"dev": "react-native bundle-harmony --dev"這句話

{
 "name": "AwesomeProject",
 "version": "0.0.1",
 "private": true,
 "scripts": {
   "android": "react-native run-android",
   "ios": "react-native run-ios",
   "lint": "eslint .",
   "start": "react-native start",
   "test": "jest",
+    "dev": "react-native bundle-harmony --dev"
 },
 "dependencies": {
   "react": "18.2.0",
   "react-native": "0.72.5"
 },
 "devDependencies": {
   "@babel/core": "^7.20.0",
   "@babel/preset-env": "^7.20.0",
   "@babel/runtime": "^7.20.0",
   "@react-native/eslint-config": "^0.72.2",
   "@react-native/metro-config": "^0.72.11",
   "@tsconfig/react-native": "^3.0.0",
   "@types/react": "^18.0.24",
   "@types/react-test-renderer": "^18.0.0",
   "babel-jest": "^29.2.1",
   "eslint": "^8.19.0",
   "jest": "^29.2.1",
   "metro-react-native-babel-preset": "0.76.8",
   "prettier": "^2.4.1",
   "react-test-renderer": "18.2.0",
   "typescript": "4.8.4"
 },
 "engines": {
   "node": ">=16"
 }
}

打開terminal,cd到新建項目的文件下,執(zhí)行

// @x.x.x可以不要,默認(rèn)會安裝最新版的依賴,也可以指定版本號,但是要考慮跟rn版本的兼容性
npm i @react-native-oh/react-native-harmony@x.x.x
// 我這里用的是npm i @react-native-oh/react-native-harmony@0.72.53

3. 修改rn配置文件metro.config.js

const {mergeConfig, getDefaultConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');

/**
* @type {import("metro-config").ConfigT}
*/
const config = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true,
      },
    }),
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({
  reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}), config);

4. 生成bundle文件,供鴻蒙使用

cd到rn對應(yīng)的文件夾下,運行npm run dev 即運行npm run react-native bundle-harmony --dev
運行完成會生成bundle.harmony.js和assets文件夾,如下圖

131751370932_.pic.jpg

5. 新建鴻蒙項目

這里不再過多介紹,鴻蒙開發(fā)官網(wǎng)都有介紹,注意一點:在創(chuàng)建項目的時候,bundlename要與開發(fā)者證書里的bundlename一致,可以在DevEco Studio -> file -> project structure中查看bundle name,如下圖

image.png

然后在確定下證書中對應(yīng)的bundle name,終端輸入命令:keytool -list -v -keystore debug2.p12 -storetype PKCS12
image.png

我這里隨便找的一個證書實驗的,所以bundle name是空,bundle name是所有者: CN=test5566, OU=, O=, L=, ST=, C=中的O=對應(yīng)的東西。

6,修改bundle name(非必需)

找到AppScope/app.json5

{
  "app": {
    "bundleName": "com.123.app.id",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_layered_image",
    "label": "$string:app_name"
  }
}

在這里修改之后,build clean,然后rebuild即可

7,在 MyApplication/entry/src/main 目錄下新建 cpp 文件夾。在 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("${RNOH_CPP_DIR}" ./rn)

add_library(rnoh_app SHARED
    "./PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)

target_link_libraries(rnoh_app PUBLIC rnoh)

8,在 cpp 目錄下新增 PackageProvider.cpp

#include "RNOH/PackageProvider.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {};
}

9,打開 MyApplicaton\entry\build-profile.json5,將 cpp 中的代碼添加到鴻蒙的編譯構(gòu)建任務(wù)中

{
 "apiType": "stageMode",
 "buildOption": {
+   "externalNativeOptions": {
+      "path": "./src/main/cpp/CMakeLists.txt",
+      "arguments": "",
+      "cppFlags": "",
+    }
 },
 "buildOptionSet": [
   {
     "name": "release",
     "arkOptions": {
       "obfuscation": {
         "ruleOptions": {
           "enable": true,
           "files": [
             "./obfuscation-rules.txt"
           ]
         }
       }
     }
   },
 ],
 "targets": [
   {
     "name": "default"
   },
   {
     "name": "ohosTest",
   }
 ]
}

10, 打開 MyApplicaton\entry\src\main\ets\entryability\EntryAbility.ets,引入并使用 RNAbility,該文件需要滿足以下的要求:

import { RNAbility } from '@rnoh/react-native-openharmony';

export default class EntryAbility extends RNAbility {
  getPagePath() {
    return 'pages/Index';
  }
}

11, 在 MyApplicaton\entry\src\main\ets 目錄下新增 RNPackagesFactory.et

import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [];
}

12,打開 MyApplicaton\entry\src\main\ets\pages\Index.ets,添加RNOH的使用代碼,修改后如下:

RNApp的參數(shù)appKey需要與RN工程中AppRegistry.registerComponent注冊的appName保持一致,否則會導(dǎo)致白屏。

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%')
  }
}

13,加載bundle包,本地加載 bundle。將 bundle 文件和 assets 圖片放在 entry/src/main/resources/rawfile 路徑下,在 entry/src/main/ets/pages/Index.ets 中使用

最后一步,運行鴻蒙,一定要連接手機,不然會報錯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容