Electron34鸿蒙PC调用ets

将Electron编译工具链配置环境变量

export CC="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/clang --target=aarch64-linux-ohos"
export CXX="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/clang++ --target=aarch64-linux-ohos"
export LD="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/lld --target=aarch64-linux-ohos"
export STRIP="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-strip"
export RANLIB="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-ranlib"
export OBJDUMP="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-objdump"
export OBJCOPY="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-objcopy"
export NM="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-nm"
export AR="~/electron_release/chromium-electron-release/src/ohos_sdk/openharmony/native/llvm/bin/llvm-ar"
export CFLAGS="-fPIC -D__MUSL__=1"
export CXXFLAGS="-fPIC -D__MUSL__=1"

目录结构示意

本指导文档共使用到三个文件夹,分别为aki、addapter、addon,它们处于同级目录下,目录结构如下图所示:

一、aki的下载以及编译

  1. 使用Git拉取aki代码

git clone https://gitcode.com/openharmony-sig/aki.git
  1. 配置aki的cmakelist文件,添加如下内容(请注意替换路径)

## 在ets-demo/aki/CMakeLists.txt中添加以下配置
# set electron path
set(ELE_PATH ~/electron/34_release/chromium-electron-release)
set(CMAKE_C_COMPILER ${ELE_PATH}/src/ohos_sdk/openharmony/native/llvm/bin/clang)
set(CMAKE_CXX_COMPILER ${ELE_PATH}/src/ohos_sdk/openharmony/native/llvm/bin/clang++)
set(CMAKE_CXX_FLAGS "--target=aarch64-linux-ohos")
​
# 下列配置如果是electron25的话无需添加
add_compile_options(
  -Wno-vla-cxx-extension        # 不显示关于 C++ 中使用变长数组的警告
  -Wno-error=vla-cxx-extension  # 不把这个警告当作错误处理
)

如下图所示:

  1. 编译aki

cd aki
​
mkdir build && cd build
​
cmake .. -DCMAKE_BUILD_TYPE=Release
​
make

编译完成后可在 build/src 目录下生成编译产物:libaki_jsbind.so

二、编译adapter

  1. Demo文件已提供,请仿照示例文件中的demo.cc代码进行方法注册

注意:demo.cc的头文件引用顺序,正确顺序如下,在提供的demo中已修改。

#include "openharmony/native/sysroot/usr/include/napi/native_api.h"
#include "openharmony/native/sysroot/usr/include/js_native_api_types.h"
#include "third_party/electron_node/src/node.h"
  1. 仿照示例文件中的getPath.cc进行方法绑定

  2. 根据本地路径情况修改CMakeLists的编译环境路径

  3. 编译adapter

mkdir build && cd build
​
cmake ../
​
make

编译完成后可在 build 目录下生成编译产物:libadaptertest.so

三、编译addon

  1. 在CMakeLists.txt文件中修改头文件路径 将cmake文件中的文件路径修改为自己本地的路径,并注意需要链接上libshim.a文件(已附件) 如下图所示:

  2. Electron34需要使用cmake-js编译,工程在addon文件夹下,编译出来的库名字是electron-addon.node(可自行在配置文件中修改),位于build/Release目录下。cmake-js需要在addon目录下使用npm install命令编译。

cd addon
​
# npm install 命令的作用为安装npm依赖
# 在package.json文件中,已为scripts字段配置参数:"install": "cmake-js compile"
# 使在使用npm install 安装环境依赖的同时执行'cmake-js compile'编译
npm install --verbose

编译完成后可在 build/Release 目录下生成编译产物:electron-addon.node

注:在执行“npm install”命令可以分解为两个步骤,分别为: “npm install”:npm安装依赖的标准命令,执行此命令时将按照npm项目中的package.json文件中的配置来安装环境依赖 “cmake-js compile”:首先会检测并在本地安装cmake-js的依赖项,当执行到该命令时你可以看到编译机在家目录下生成了一个.cmake-js/文件夹,文件夹下会存放对应node版本的相关依赖。当依赖满足时则会按照CMakeLists.txt文件的编译指令开始编译。

报错处理

报错一、

证书问题,可以通过在~/.npmrc配置cafile来解决,如果配置cafile后仍然报错,可以在编译命令前添加NODE_TLS_REJECT_UNAUTHORIZED=0可临时跳过证书校验,如下图:

报错二、 如果报如下图所示或类似的错误,请检查您的编译工具链环境变量是否已配置,并执行source ~/.bashrc命令刷新环境变量。

如果可以正常编译,最终结果如下图:

四、构建har包

注:该步骤缺少的文件及文件夹请自行创建

  1. 创建工程 文档中提到的示例,已经在附件中附带了,但不能直接全部拷贝进去使用,可以复制对应文件内容,library需要自己新建,如下图所示: deveco中点击File ==> New ==> Moudle ==> Static Library,创建一个Library


  1. 将adapter中的注册进行声明和初始化

// 新建文件:ohos_hap\library\src\main\ets\interface\interface.ts
export class JSBind {
  bindFunction: (name: string, func: Function) => number;
}
​
export interface NativeContext {
  JSBind: JSBind;
}

  1. 定义初始化和bind函数

// 新建文件:ohos_hap\library\src\main\ets\utils\NativeTest.ets
import adaptertest from 'libadaptertest.so';
import { NativeContext } from '../interface/interface';
import environment from '@ohos.file.environment'
import { hilog } from '@kit.PerformanceAnalysisKit';
​
export class JsBindingTest {
  private static currentContext: NativeContext;
​
  static getUserDesktopDir(): string {
    let  userDir : string = '';
    try {
      userDir = environment.getUserDesktopDir();
      hilog.info(0x0000, 'testing', `getUserDesktopDir:${JSON.stringify(userDir)}`);
    } catch (error){
      hilog.info(0x0000, 'testing', `getUserDesktopDir failed caused by: :${JSON.stringify(error)}`);
    }
    return "zhangao: "+userDir;
  }
​
  static init() {
    JsBindingTest.currentContext = adaptertest.getNativeContext();
  }
​
  static bind() {
    if (JsBindingTest.currentContext === undefined) {
      JsBindingTest.currentContext = adaptertest.getNativeContext();
    }
    JsBindingTest.currentContext.JSBind.bindFunction("getDir", JsBindingTest.getUserDesktopDir);
  }
​
  static getNativeContext(): NativeContext {
    if (JsBindingTest.currentContext !== undefined) {
      return JsBindingTest.currentContext;
    }
    return adaptertest.getNativeContext();
  }
}

  1. 增加共享包导出声明入口 在src/main目录下创建 cpp -> types ->libadaptertest(根据实际修改)

// 增加文件:ohos_hap/library/src/main/cpp/types/libadaptertest/index.d.ts
import type { NativeContext } from '../../../ets/interface/interface'
​
export const getNativeContext: () => NativeContext;

// 增加文件:ohos_hap/library/src/main/cpp/types/libadaptertest/oh-package.json5
{
  "name": "libadaptertest.so",
  "types": "./index.d.ts",
  "version": "1.0.0",
  "description": "libadapter.so type file"
}
  1. 修改library根目录下的oh-packages.json5配置文件,增加引用依赖

// 修改文件:ohos_hap\library\oh-package.json5
{
  "name": "library",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "Index.ets",
  "author": "",
  "license": "Apache-2.0",
  "devDependencies": {
    'libadaptertest.so': 'file:./src/main/cpp/types/libadaptertest',
  },
  "dependencies": {
    "inversify": "^6.0.1",
    "reflect-metadata": "^0.1.13"
  }
}
​
  1. 修改library根目录下的Index.ets配置文件,增加导出方法

// 修改文件:ohos_hap\library\Index.ets
export { MainPage } from './src/main/ets/components/MainPage';
export { JsBindingTest } from './src/main/ets/utils/NativeTest';
  1. 构建har包 参考文档:引用共享包 在web_engine模块中引用此HAR包 webgine/oh-packages.json5 中增加引用配置

// 修改文件:ohos_hap\web_engine\oh-package.json5
{
  "name": "web_engine",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "Index.ets",
  "author": "",
  "license": "Apache-2.0",
  "devDependencies": {
    'libadapter.so': 'file:./src/main/cpp/types/libadapter',
  },
  "dependencies": {
    "inversify": "^6.0.1",
    "reflect-metadata": "^0.1.13",
    "library": "file:../library"
  }
}

在WebAbilityStage.ets文件中初始化、绑定

// 修改文件:ohos_hap\web_engine\src\main\ets\application\WebAbilityStage.ets(需要修改的文件已在下方代码中使用“++”符号标注)
import AbilityStage from '@ohos.app.ability.AbilityStage';
import { CommandType, ConfigData, ContextType } from '../common/Constants';
import JsBindingUtils from '../utils/JsBindingUtils';
import Want from '@ohos.app.ability.Want';
import lazy { GlobalThisHelper } from '../utils/GlobalThisHelper';
import lazy { NativeContext } from '../interface/CommonInterface';
import lazy { CommonDependencyProvider } from '../common/CommonDependencyProvider';
import { AbilityConstant } from '@kit.AbilityKit';
import { ConfigurationConstant, Configuration } from '@kit.AbilityKit';
import { NativeThemeAdapter } from '../adapter/NativeThemeAdapter'
import Inject from '../common/InjectModule';
++ import { JsBindingTest } from 'library';
++ import { JsBindingMethod } from '../jsbindings/JsBindingMethod';
​
const DELAYED_TIME = 0;
export class WebAbilityStage extends AbilityStage {
​
  private nativeContext: NativeContext | undefined = undefined;
  private nativeThemeAdapter: NativeThemeAdapter | undefined;
​
  onCreate(): void {
++     JsBindingTest.init();
    this.runTaskAsync();
  }
​
  onAcceptWant(want: Want): string {
    let instanceKey = want.parameters?.instanceKey;
    if (instanceKey) {
      return instanceKey.toString();
    }
    if (GlobalThisHelper.isLaunched()) {
      let result = this.nativeContext?.ExecuteCommand(
        CommandType.kGetLastActiveWidget, { is_sync: true });
      let widgetId = result?.last_widget_Id;
      if (widgetId) {
        return ConfigData.WINDOW_PREFIX + widgetId;
      }
    }
    this.context.getApplicationContext().tempDir;
    return ConfigData.DEFAULT_WINDOW_ID;
  }
​
  onPrepareTermination(): AbilityConstant.PrepareTermination {
    this.nativeContext?.ExecuteCommand(CommandType.kAppQuit, { is_sync: false });
    return AbilityConstant.PrepareTermination.TERMINATE_IMMEDIATELY;
  }
​
  onConfigurationUpdate(config: Configuration) {
    if (config.colorMode !== undefined) {
      this.nativeThemeAdapter?.setSystemNativeTheme(config.colorMode);
    }
  }
​
  private runTaskAsync() {
++    setTimeout(() => {
++      JsBindingMethod.bind();
++      JsBindingTest.bind();
++    })
    setTimeout(() => {
      JsBindingUtils.initNativeContext(ContextType.kMainProcess);
      this.nativeContext = JsBindingUtils.getNativeContext(ContextType.kMainProcess);
      if (!GlobalThisHelper.isLaunched()) {
        let appContext = this.context.getApplicationContext();
        GlobalThisHelper.appInit(new CommonDependencyProvider(appContext));
      }
      import('../jsbindings/JsBindingMethod').then((ns:ESObject) => {
        ns.JsBindingMethod.bind();
        this.nativeThemeAdapter = Inject.get(NativeThemeAdapter);
      }).catch(()=>{
        console.log('import failed');
      });
    }, DELAYED_TIME)
  }
}

附加内容:部分目录结构介绍

五、调用

  1. HAP包目录结构

  2. JS代码调用

// 修改文件:ohos_hap\web_engine\src\main\resources\resfile\resources\app\main.js
const { app, BrowserWindow, Tray, nativeImage, Menu } = require('electron');
const path = require('path');
const addon = require('electron-addon.node')
console.log('electron-addon keys:',Object.keys(addon));
let mainWindow, tray;
​
function createWindow() {
    tray = new Tray(nativeImage.createFromPath(path.join(__dirname, 'electron_white.png')));
    mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
    });
    mainWindow.setWindowButtonVisibility(true);
    mainWindow.loadURL('https://cn.bing.com');
    console.log('test electron-addon  hello()', addon.hello());
    console.log('test electron-addon  getDir() ', addon.getDir());
​
}
app.whenReady().then(createWindow);
​

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐