Electron调用ETS指导文档

返回主文档

目录


前置要求

  • 操作系统:Ubuntu 22.04
  • CPU架构:x86_64

参考 Electron鸿蒙化指导文档 git拉取Electron源代码。


一、aki源码下载和编译

1. 利用git下拉aki框架代码

git clone https://gitee.com/openharmony-sig/aki.git

2. 配置cmake

进入aki目录,在cmake中增加以下编译配置(服务器中鸿蒙clang、clang++对应的路径,以下路径仅作参考):

set(CMAKE_C_COMPILE /home/dev_chromium/xxx/electron114/chromium114-electron/src/ohos_sdk/openharmony/native/llvm/bin/clang)
set(CMAKE_CXX_COMPILE /home/dev_chromium/xxx/electron114/chromium114-electron/src/ohos_sdk/openharmony/native/llvm/bin/clang)
set(CMAKE_CXX_FLAGS "--target=aarch64-linux-ohos")

cmake配置示例

3. 配置环境变量(clang、clang++换为实际路径)

export CC="/home/dev_chromium/xxx/electron114/chromium114-electron/src/ohos_sdk/openharmony/native/llvm/bin/clang --target=aarch64-liniux-ohos"
export CXX="/home/dev_chromium/xxx/electron114/chromium114-electron/src/ohos_sdk/openharmony/native/llvm/bin/clang++ --target=aarch64-liniux-ohos"

4. 编译

运行结束在build/src路径会生成最终的编译产物libaki_jsbind.so

cd aki
mkdir build
cd build
cmake ../ -DCMAKE_BUILD_TYPE=Release
make

二、应用adapter编写

1. 样例目录结构

目录结构图示如下:

目录结构

其中,aki文件夹为第一步git下来的aki。

2. 仿照adapter下的demo进行方法的注册

adapter注册示例

3. 仿照getPatch.cc进行方法的绑定

此处提供同步和异步两种方式,供应用自己选择:

方法绑定示例

CMakeLists编写

# Project Name
SET(TARGETFILENAME "adaptertest")
PROJECT(${TARGETFILENAME})

# CMake minimum version requirement setting
cmake_minimum_required(VERSION 3.8)

# set electron path 请根据实际情况填写!!!
set(ELE_PATH  /home/dev_chromium/xxx/electron114/chromium114-electron)

# ohos
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")

# 设置包含目录
# ohos
include_directories(${ELE_PATH}/src/)
include_directories(${ELE_PATH}/src/third_party/electron_node/deps/v8/include/)
include_directories(${ELE_PATH}/src/ohos_sdk/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../aki/include)

message(${CMAKE_CURRENT_SOURCE_DIR})

set(src demo.cc getpath.cc)
set(headers getpath.h)

# 生成可执行文件
#add_executable(${TARGETFILENAME} demo.cpp)

# 生成静态库
#ADD_LIBRARY(${TARGETFILENAME} STATIC demo.cpp)

# 生成动态库或共享库
ADD_LIBRARY (${TARGETFILENAME} SHARED
${src}
)

target_compile_features(${TARGETFILENAME} PUBLIC cxx_std_17)
target_compile_definitions(${TARGETFILENAME} PUBLIC JSBIND_USING_NAPI=1)
target_compile_definitions(${TARGETFILENAME} PUBLIC AKI_BUILDING_SHARED=1)

# 设置链接库文件-ohos
target_link_libraries(${TARGETFILENAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../aki/build/src/libaki_jsbind.so)
target_link_libraries(${TARGETFILENAME} PUBLIC ${ELE_PATH}/src/out/musl_64/libelectron.so)

# 修改后缀名为 .node
# SET_TARGET_PROPERTIES(${TARGETFILENAME} PROPERTIES SUFFIX ".node")

获取编译产物

执行命令,可获取编译产物libadaptertest.so

mkdir build
cd build
cmake ../
make

三、应用addon编写

样例目录结构

addon目录结构

调用adapter

调用adapter示例

CMakeLists编写

# Project Name
SET(TARGETFILENAME "addon")
PROJECT(${TARGETFILENAME})

# CMake minimum version requirement setting
cmake_minimum_required(VERSION 3.8)

# set electron path 请根据实际情况填写!!!
set(ELE_PATH  /home/dev_chromium/xxx/electron114/chromium114-electron)

# ohos
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")

# 设置包含目录
# ohos
include_directories(${ELE_PATH}/src/)
include_directories(${ELE_PATH}/src/third_party/electron_node/deps/v8/include/)
include_directories(${ELE_PATH}/src/ohos_sdk/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/)

message(${CMAKE_CURRENT_SOURCE_DIR})

set(src demo.cc)

# 生成可执行文件
#add_executable(${TARGETFILENAME} demo.cpp)

# 生成静态库
#ADD_LIBRARY(${TARGETFILENAME} STATIC demo.cpp)

# 生成动态库或共享库
ADD_LIBRARY (${TARGETFILENAME} SHARED
${src}
)

# 设置链接库文件-ohos
target_link_libraries(${TARGETFILENAME} PUBLIC ${ELE_PATH}/src/out/musl_64/libelectron.so)
target_link_libraries(${TARGETFILENAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../adapter/build/libadaptertest.so)
target_compile_definitions(${TARGETFILENAME} PUBLIC NODE_MODULE_VERSION=116)

# 修改后缀名为 .node
SET_TARGET_PROPERTIES(${TARGETFILENAME} PROPERTIES SUFFIX ".node")

获取编译产物

执行下述命令后,可获取编译产物addon.node

mkdir build
cd build
cmake ../
make

四、ets调用及har包构建

创建工程

deveco中点击 File ==> New ==> Moudle ==> Static Library,创建一个Library

创建Library

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

adapter中的注册进行声明

export class JSBind{
  bindFunction: (name: string, func:Function) => number;
}

export interface NativeContext{
  JSBind: JSBind;
}

声明示例

定义初始化和bind函数

import adaptertest from 'libadaptertest.so'
import { NativeContext } from '../interface/interface'
import environment from '@ohos.file.environment'
import hilog from '@ohos.hilog'

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 userDir;
  }

  //异步方法
  // static  getUserDesktopDir(callback: (str: string) => void) : void{
  //   setTimeout(() => {
  //     let userDir : string = '';
  //     userDir = environment.getUserDesktopDir();
  //     hilog.info(0x0000, 'testing', `getUserDesktopDir Async:${JSON.stringify(userDir)}`);
  //     callback(userDir);
  //   }, 3000)
  // }

  static init(){
    JSBindingTest.currentContext = adaptertest.getNativeContext();
    return;
  }

  static bind(){
    if(JSBindingTest.currentContext === undefined){
      hilog.info(0x0000, 'testing', `bind`);
      JSBindingTest.currentContext = adaptertest.getNativeContext();
    }
    JSBindingTest.currentContext.JSBind.bindFunction('getDir', JSBindingTest.getUserDesktopDir);
    return;
  }
}

初始化和bind函数

增加共享包导出声明入口

在src/main目录下创建 cpp -> types ->libadaptertest(根据实际修改)

创建types目录

import type { NativeContext } from '../../../ets/interface/interface'

export const getNativeContext: () => NativeContext;

导出声明示例

增加oh-packages.json5配置文件

{
  "types": "./index.d.ts",
  "name": "libadaptertest.so",
  "description": "libadapter.so type file",
  "version": ""
}

oh-packages配置

修改library根目录下的oh-packages.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"
  }
}

引用依赖配置

修改library根目录下的Index.ets配置文件,增加导出方法

export { MainPage } from './src/main/ets/components/MainPage';
export { JSBindingTest } from './src/main/ets/utils/NativeTest'

导出方法配置

构建har包

参考文档:引用共享包-开发及引用共享包-应用/元服务开发-DevEco Studio - 华为HarmonyOS开发者

在web_engine模块中引用此HAR包 webgine/oh-packages.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"
  }
}

HAR包引用配置

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

// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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 { JSBindingTest } from 'library';
import { JsBindingMethod } from '../jsbindings/JsBindingMethod';

const DELAYED_TIME = 0;

export class WebAbilityStage extends AbilityStage {
  private nativeContext: NativeContext | undefined = 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;
  }

  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();
      }).catch(()=>{
        console.log('import failed');
      });
    }, DELAYED_TIME)
  }
}

初始化绑定示例

附加:部分目录结构介绍

目录结构介绍


五、最终调用

HAP包目录结构

HAP包目录结构

JS代码调用

JS代码调用示例

运行结果

运行结果


六、代码样例