鸿蒙 PC 与 Electron 结合开发:从环境搭建到核心功能落地(附完整代码)
前言
在跨端开发领域,Electron 凭借 “一次编写、多端运行” 的特性占据重要地位,其基于 Chromium 和 Node.js 的架构可快速将 Web 应用打包为 Windows、macOS、Linux 桌面应用。而鸿蒙系统(HarmonyOS)作为面向全场景的分布式操作系统,正逐步完善鸿蒙 PC、智慧屏等桌面端设备生态。将 Electron 与鸿蒙 PC 结合,既能复用 Web 技术栈的海量资源,又能借助鸿蒙的分布式能力实现 “跨设备无缝流转”,为开发者提供更灵活的全场景应用开发方案,尤其能满足鸿蒙 PC 用户对优质桌面应用的迫切需求。
本文面向有 Web 或桌面开发基础的开发者,从技术背景、环境搭建、核心功能开发到场景落地,全程附代码示例与官方文档链接,助力快速上手鸿蒙 PC Electron 开发。
一、鸿蒙 PC 与 Electron 结合的技术背景
1.1 为什么需要鸿蒙 PC + Electron?
- 技术复用:Electron 基于 Web 技术栈(HTML/CSS/JavaScript),开发者无需学习全新语言即可开发鸿蒙 PC 应用,降低迁移成本。
- 跨端能力互补:Electron 擅长桌面端应用开发,鸿蒙擅长分布式跨设备协同,二者结合可实现 “鸿蒙 PC 端功能 + 多设备流转” 的全场景体验(如鸿蒙 PC 端编辑文档,智慧屏端展示、手机端审批)。
- 生态适配需求:鸿蒙 PC(如华为 MateBook X Pro 2024 款鸿蒙版)正处于生态快速建设阶段,急需更多优质桌面应用,Electron 可将现有成熟桌面应用快速适配鸿蒙 PC,加速鸿蒙 PC 生态完善。
1.2 核心技术原理
鸿蒙系统通过方舟引擎(Ark Engine)支持 Electron 应用在鸿蒙 PC 上稳定运行,核心逻辑如下:
- Electron 应用的 Chromium 内核与鸿蒙 PC 的图形渲染框架深度适配,确保界面高清显示、操作流畅响应;
- Electron 的 Node.js 层与鸿蒙 PC 的系统 API 桥接,实现文件操作、设备调用等原生能力适配;
- 借助鸿蒙的分布式软总线,鸿蒙 PC 上的 Electron 应用可调用其他鸿蒙设备的资源(如摄像头、扬声器),也可被其他设备调用自身资源。
1.3 官方资源参考
- 鸿蒙 PC 开发官网:HarmonyOS for PC 开发指南
- Electron 官方文档:Electron 官方指南
- 鸿蒙与 Electron 适配说明:HarmonyOS 第三方框架适配文档
二、鸿蒙 PC Electron 开发环境搭建(附代码与操作步骤)
环境搭建分为 3 个核心步骤:基础环境(Node.js + Electron)、鸿蒙 PC 开发环境(DevEco Studio)、工程初始化与依赖配置。全程基于 Windows 11 系统演示,macOS/Linux 步骤类似,最终均适配鸿蒙 PC 设备。
2.1 基础环境准备(Node.js + Electron)
2.1.1 安装 Node.js
Electron 依赖 Node.js 环境,需安装 Node.js 16.x LTS 版本(经测试与鸿蒙 PC 适配最佳,高版本可能存在兼容性问题)。
- 下载地址:Node.js 16.20.2 官网下载
- 安装后验证:打开命令行(CMD 或 PowerShell),执行以下命令,输出版本号即安装成功:
node -v # 需输出 v16.20.2
npm -v # 需输出 8.19.4(Node.js 16.x 默认版本)
2.1.2 安装 Electron
通过 npm 全局安装 Electron,指定版本为 22.3.2(与鸿蒙 PC 方舟引擎适配的稳定版本):
# 全局安装Electron
npm install -g electron@22.3.2
# 验证安装
electron -v # 需输出 v22.3.2
2.2 鸿蒙 PC 开发环境配置(DevEco Studio)
鸿蒙 PC 应用的编译、打包与设备调试需通过 DevEco Studio 完成,需安装 DevEco Studio 4.0 及以上版本。
- 下载地址:DevEco Studio 官网下载
- 安装步骤:
- 双击安装包,选择 “自定义安装”,勾选 “HarmonyOS SDK for PC”(鸿蒙 PC 开发必需);
- 安装完成后,打开 DevEco Studio,自动下载鸿蒙 PC 端 SDK(版本选择 3.2.100 及以上);
- 配置 SDK 路径:进入「File > Settings > Appearance & Behavior > System Settings > HarmonyOS SDK」,确认 “PC” 选项卡下的 SDK 已全部下载。
- 验证环境:
- 打开 DevEco Studio,创建一个 “Empty Ability” 项目,模板选择 “PC”;
- 连接鸿蒙 PC 设备或启动鸿蒙 PC 模拟器(需在「Tools > Device Manager」中申请);
- 点击 “Run” 按钮,若项目能正常运行(显示默认页面),则鸿蒙 PC 开发环境配置成功。
2.3 鸿蒙 PC Electron 工程初始化(附代码)
2.3.1 创建 Electron 基础工程
新建文件夹(如HarmonyElectronDemo),打开命令行进入该文件夹,执行以下命令初始化 Electron 工程(适配鸿蒙 PC 运行):
bash
运行
# 初始化package.json(一路回车默认配置即可)
npm init -y
# 安装本地Electron依赖(确保与全局版本一致,适配鸿蒙PC)
npm install electron@22.3.2 --save-dev
在工程根目录创建 3 个核心文件:
main.js:Electron 主进程文件(控制应用生命周期、创建窗口,适配鸿蒙 PC 窗口规范);index.html:应用界面文件(Web 端页面,适配鸿蒙 PC 屏幕分辨率);preload.js:主进程与渲染进程的通信桥接文件(适配鸿蒙 PC 跨进程通信机制)。
2.3.2 核心文件代码实现
(1)main.js(Electron 主进程,适配鸿蒙 PC 窗口特性)
// 引入Electron核心模块
const { app, BrowserWindow } = require('electron');
const path = require('path');
// 避免垃圾回收导致窗口被销毁
let mainWindow;
// 创建窗口函数(适配鸿蒙PC窗口尺寸与显示特性)
function createWindow() {
mainWindow = new BrowserWindow({
width: 800, // 适配鸿蒙PC常见屏幕分辨率
height: 600, // 适配鸿蒙PC窗口交互逻辑
webPreferences: {
// 配置预加载脚本(用于主进程与渲染进程通信)
preload: path.join(__dirname, 'preload.js'),
// 启用Node.js环境(鸿蒙PC端需开启)
nodeIntegration: true,
contextIsolation: false // 关闭上下文隔离(适配鸿蒙PC API调用)
}
});
// 加载本地HTML文件
mainWindow.loadFile('index.html');
// 打开开发者工具(调试用,发布时需注释)
mainWindow.webContents.openDevTools();
// 窗口关闭事件
mainWindow.on('closed', () => {
mainWindow = null;
});
}
// 应用就绪后创建窗口(适配鸿蒙PC应用启动机制)
app.whenReady().then(() => {
createWindow();
// 适配macOS(窗口关闭后重新打开)
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// 所有窗口关闭后退出应用(Windows/Linux/鸿蒙PC)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
(2)preload.js(通信桥接,适配鸿蒙 PC 跨进程通信)
// 暴露Electron的ipcRenderer到渲染进程(用于跨进程通信,适配鸿蒙PC通信规范)
window.ipcRenderer = require('electron').ipcRenderer;
(3)index.html(应用界面,适配鸿蒙 PC 显示效果)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鸿蒙PC Electron Demo</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding-top: 50px;
/* 适配鸿蒙PC默认字体与显示密度 */
}
#deviceInfo {
margin-top: 30px;
color: #333;
font-size: 16px;
}
</style>
</head>
<body>
<h1>Hello 鸿蒙PC Electron!</h1>
<button id="getDeviceBtn">获取鸿蒙PC设备信息</button>
<div id="deviceInfo"></div>
<script>
// 监听按钮点击事件
document.getElementById('getDeviceBtn').addEventListener('click', () => {
// 后续章节将通过鸿蒙PC API获取设备信息,此处先占位
document.getElementById('deviceInfo').innerText = '待获取鸿蒙PC设备信息...';
});
</script>
</body>
</html>
2.3.3 配置工程运行脚本
修改package.json,添加scripts字段,用于启动适配鸿蒙 PC 的 Electron 应用:
{
"name": "harmony-pc-electron-demo",
"version": "1.0.0",
"main": "main.js", // 指定主进程文件
"scripts": {
"start": "electron ." // 启动命令(适配鸿蒙PC运行)
},
"devDependencies": {
"electron": "^22.3.2"
}
}
2.3.4 测试 Electron 工程(适配鸿蒙 PC 预览)
在命令行执行以下命令,若能弹出窗口并显示 “Hello 鸿蒙 PC Electron!”,则基础工程搭建成功,可后续对接鸿蒙 PC 设备:
npm run start
2.4 鸿蒙 PC 端工程配置(对接 Electron)
打开 DevEco Studio,创建一个 “Empty Ability” 项目,项目名称为HarmonyElectronHost,模板选择 “PC”(明确适配鸿蒙 PC),包名自定义(如com.example.harmonypcelectronhost)。
- 在鸿蒙 PC 工程的
main_pages.json中添加 Electron 应用的启动页面配置:
{
"src": [
"main_pages/Index",
{
"src": "electron/ElectronPage",
"window": {
"designWidth": 800, // 适配鸿蒙PC窗口设计宽度
"autoDesignWidth": true
}
}
]
}
- 在
src/main/electron目录下创建ElectronPage.ets文件,用于在鸿蒙 PC 上加载 Electron 应用:
import web_webview from '@ohos.web.webview';
import router from '@ohos.router';
@Entry
@Component
struct ElectronPage {
build() {
Column({ space: 10 }) {
// 鸿蒙PC WebView组件:加载Electron应用的本地HTML
Web({
src: $rawfile('index.html'), // 需将Electron工程的index.html放入鸿蒙PC工程的rawfile目录
controller: new web_webview.WebViewController()
})
.width('100%')
.height('90%') // 适配鸿蒙PC页面布局比例
// 返回按钮(适配鸿蒙PC交互逻辑)
Button('返回首页')
.width(150)
.height(40)
.onClick(() => {
router.back();
})
}
.width('100%')
.height('100%')
}
}
-
资源复制:将 Electron 工程中的
index.html、preload.js复制到鸿蒙 PC 工程的src/main/rawfile目录(若没有rawfile目录,需手动创建)。 -
测试鸿蒙 PC 对接:
- 启动鸿蒙 PC 模拟器或连接真实鸿蒙 PC 设备;
- 点击 DevEco Studio 的 “Run” 按钮,进入
ElectronPage页面,若能显示 Electron 应用的界面,则鸿蒙 PC 端配置成功。
2.5 环境搭建常见问题解决(针对鸿蒙 PC 场景)
| 问题现象 | 解决方案 | 参考链接 |
|---|---|---|
| Electron 启动报错 “Cannot find module 'electron'” | 1. 检查 Node.js 版本是否为 16.x(鸿蒙 PC 适配版本);2. 执行npm install重新安装依赖;3. 全局安装 Electron:npm install -g electron@22.3.2 |
Electron 安装问题排查 |
| 鸿蒙 PC WebView 加载 HTML 报错 “File not found” | 1. 确认 HTML 文件路径是否正确;2. 检查rawfile目录是否在鸿蒙 PC 工程的src/main下;3. 清理工程缓存:「Build > Clean Project」 |
鸿蒙 WebView 资源加载指南 |
| DevEco Studio 无法识别鸿蒙 PC 设备 | 1. 安装鸿蒙 PC 设备驱动:鸿蒙设备驱动下载;2. 开启鸿蒙 PC “开发者模式” 并允许 USB 调试 | 鸿蒙 PC 设备连接指南 |
三、鸿蒙 PC Electron 核心功能开发(多代码示例)
本节聚焦 3 个核心功能:鸿蒙 PC 设备信息获取、Electron 与鸿蒙 PC 的跨进程通信、分布式设备资源调用(鸿蒙 PC 为核心终端),每个功能均附完整代码与调试步骤。
3.1 功能 1:鸿蒙 PC 设备信息获取(Electron 调用鸿蒙 PC API)
通过鸿蒙的deviceInfo模块获取鸿蒙 PC 的设备型号、系统版本等信息,并在 Electron 界面展示。
3.1.1 鸿蒙 PC 端代码(能力封装)
在鸿蒙 PC 工程的src/main/ets/utils目录下创建DeviceInfoUtil.ets,封装鸿蒙 PC 设备信息获取方法:
import deviceInfo from '@ohos.device.deviceInfo';
/**
* 鸿蒙PC设备信息工具类
*/
export class DeviceInfoUtil {
/**
* 获取鸿蒙PC基本信息
* @returns 鸿蒙PC设备信息对象
*/
static getDeviceBasicInfo(): Record<string, string> {
return {
deviceName: deviceInfo.deviceName, // 鸿蒙PC设备名称
deviceModel: deviceInfo.deviceModel, // 鸿蒙PC设备型号
osVersion: deviceInfo.osVersion, // 鸿蒙PC系统版本
manufacturer: deviceInfo.manufacturer // 设备厂商(华为)
};
}
/**
* 获取鸿蒙PC唯一标识(需申请权限)
* @returns 鸿蒙PC唯一标识
*/
static getDeviceId(): string {
return deviceInfo.deviceId;
}
}
3.1.2 跨进程通信配置(Electron ↔ 鸿蒙 PC)
- 鸿蒙 PC 端:在
ElectronPage.ets中添加通信逻辑,通过WebView的onMessage监听 Electron 的请求,并返回鸿蒙 PC 设备信息:
import web_webview from '@ohos.web.webview';
import router from '@ohos.router';
import { DeviceInfoUtil } from '../utils/DeviceInfoUtil';
@Entry
@Component
struct ElectronPage {
// WebView控制器
private webViewController: web_webview.WebViewController = new web_webview.WebViewController();
build() {
Column({ space: 10 })
.width('100%')
.height('100%') {
// WebView组件
Web({
src: $rawfile('index.html'),
controller: this.webViewController
})
.width('100%')
.height('90%')
// 监听Electron发送的消息(适配鸿蒙PC通信)
.onMessage((event) => {
const message = event.message;
// 处理“获取鸿蒙PC设备信息”请求
if (message === 'getDeviceInfo') {
const deviceInfo = DeviceInfoUtil.getDeviceBasicInfo();
// 将鸿蒙PC设备信息发送给Electron
this.webViewController.postMessage({
type: 'deviceInfoResult',
data: deviceInfo
});
}
})
Button('返回首页')
.width(150)
.height(40)
.onClick(() => {
router.back();
})
}
}
}
- Electron 端:修改
index.html的脚本,发送请求并接收鸿蒙 PC 设备信息:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鸿蒙PC Electron Demo</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding-top: 50px;
}
#deviceInfo {
margin-top: 30px;
color: #333;
font-size: 16px;
line-height: 1.5;
}
button {
padding: 10px 20px;
font-size: 14px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Hello 鸿蒙PC Electron!</h1>
<button id="getDeviceBtn">获取鸿蒙PC设备信息</button>
<div id="deviceInfo"></div>
<script>
// 获取DOM元素
const getDeviceBtn = document.getElementById('getDeviceBtn');
const deviceInfoDiv = document.getElementById('deviceInfo');
// 监听按钮点击:发送“获取鸿蒙PC设备信息”请求到鸿蒙端
getDeviceBtn.addEventListener('click', () => {
deviceInfoDiv.innerText = '正在获取鸿蒙PC设备信息...';
// 通过WebView的postMessage发送请求(鸿蒙PC端监听该事件)
if (window.webkit && window.webkit.messageHandlers) {
// 鸿蒙PC WebView适配:通过webkit.messageHandlers发送消息
window.webkit.messageHandlers.postMessage.postMessage('getDeviceInfo');
}
});
// 监听鸿蒙PC端返回的消息
window.addEventListener('message', (event) => {
const { type, data } = event.data;
if (type === 'deviceInfoResult') {
// 渲染鸿蒙PC设备信息到页面
deviceInfoDiv.innerText = `
设备名称:${data.deviceName}
设备型号:${data.deviceModel}
系统版本:${data.osVersion}
设备厂商:${data.manufacturer}
`;
}
});
</script>
</body>
</html>
3.1.3 调试步骤
- 将修改后的
index.html复制到鸿蒙 PC 工程的rawfile目录; - 启动鸿蒙 PC 设备(模拟器或真实设备),运行鸿蒙工程;
- 点击 “获取鸿蒙 PC 设备信息” 按钮,若页面显示鸿蒙 PC 的设备型号、系统版本等信息,则功能实现成功。
3.2 功能 2:Electron 与鸿蒙 PC 的文件交互(读写本地文件)
Electron 可通过 Node.js 的fs模块操作文件,鸿蒙 PC 端可通过fileIo模块读写文件,二者结合实现鸿蒙 PC 端的跨端文件共享。
3.2.1 Electron 端代码(文件写入鸿蒙 PC)
修改main.js,添加文件写入功能,并通过 IPC 通信接收渲染进程的文件内容(适配鸿蒙 PC 文件路径规范):
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs'); // 引入Node.js文件模块
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.loadFile('index.html');
mainWindow.webContents.openDevTools();
mainWindow.on('closed', () => {
mainWindow = null;
});
}
// 监听渲染进程的“写入文件到鸿蒙PC”请求
ipcMain.on('writeFile', (event, { filePath, content }) => {
try {
// 写入文件(鸿蒙PC端标准路径示例:/home/user/Documents/)
const fullPath = path.join('/home/user/Documents/', filePath);
fs.writeFileSync(fullPath, content, 'utf8');
// 发送成功消息给渲染进程
event.reply('writeFileResult', { success: true, message: `文件已保存至鸿蒙PC:${fullPath}` });
} catch (error) {
// 发送失败消息
event.reply('writeFileResult', { success: false, message: error.message });
}
});
app.whenReady().then(createWindow);
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
3.2.2 Electron 渲染端代码(文件输入界面,适配鸿蒙 PC)
修改index.html,添加文件内容输入框和保存按钮(适配鸿蒙 PC 操作场景):
<!-- 新增文件操作区域(适配鸿蒙PC文件管理场景) -->
<div style="margin-top: 40px; padding: 0 20px;">
<h3>文件写入测试(保存到鸿蒙PC)</h3>
<input type="text" id="fileNameInput" placeholder="输入文件名(如test.txt)" style="width: 300px; padding: 8px; margin-right: 10px;">
<textarea id="fileContentInput" placeholder="输入文件内容..." style="width: 100%; height: 150px; margin-top: 10px; padding: 8px;"></textarea>
<button id="saveFileBtn" style="margin-top: 10px;">保存文件到鸿蒙PC</button>
<div id="fileResult" style="margin-top: 10px; color: #666;"></div>
</div>
<script>
// 新增:文件保存逻辑(适配鸿蒙PC)
const fileNameInput = document.getElementById('fileNameInput');
const fileContentInput = document.getElementById('fileContentInput');
const saveFileBtn = document.getElementById('saveFileBtn');
const fileResultDiv = document.getElementById('fileResult');
// 监听保存按钮点击
saveFileBtn.addEventListener('click', () => {
const fileName = fileNameInput.value.trim();
const content = fileContentInput.value.trim();
if (!fileName) {
fileResultDiv.innerText = '请输入文件名!';
return;
}
// 通过ipcRenderer发送文件写入请求到主进程(目标:鸿蒙PC)
window.ipcRenderer.send('writeFile', {
filePath: fileName,
content: content
});
});
// 监听主进程返回的文件写入结果
window.ipcRenderer.on('writeFileResult', (event, result) => {
if (result.success) {
fileResultDiv.innerText = `成功:${result.message}`;
fileResultDiv.style.color = 'green';
} else {
fileResultDiv.innerText = `失败:${result.message}`;
fileResultDiv.style.color = 'red';
}
});
</script>
3.2.3 鸿蒙 PC 端代码(文件读取)
在DeviceInfoUtil.ets中添加鸿蒙 PC 文件读取方法:
import fileIo from '@ohos.file.fs';
import { BusinessError } from '@ohos.base';
export class DeviceInfoUtil {
// ... 原有设备信息方法 ...
/**
* 读取鸿蒙PC本地文件
* @param filePath 文件路径(如:/home/user/Documents/test.txt)
* @returns 文件内容
*/
static async readFile(filePath: string): Promise<string> {
try {
// 打开鸿蒙PC本地文件
const file = await fileIo.open(filePath, fileIo.OpenMode.READ_ONLY);
// 读取文件内容
const buffer = new ArrayBuffer(4096);
const readResult = await fileIo.read(file.fd, buffer);
// 关闭文件
await fileIo.close(file.fd);
// 转换buffer为字符串
return String.fromCharCode.apply(null, new Uint8Array(buffer.slice(0, readResult.bytesRead)));
} catch (error) {
const err = error as BusinessError;
throw new Error(`鸿蒙PC文件读取失败:${err.message}`);
}
}
}
在ElectronPage.ets中添加文件读取的通信逻辑(适配鸿蒙 PC):
// 新增:监听Electron的文件读取请求(鸿蒙PC端)
.webView.onMessage((event) => {
const message = event.message;
if (message === 'getDeviceInfo') {
// ... 原有设备信息逻辑 ...
} else if (message.type === 'readFile') {
// 处理文件读取请求(鸿蒙PC本地文件)
DeviceInfoUtil.readFile(message.filePath)
.then(content => {
this.webViewController.postMessage({
type: 'readFileResult',
success: true,
content: content
});
})
.catch(error => {
this.webViewController.postMessage({
type: 'readFileResult',
success: false,
message: error.message
});
});
}
})
3.2.4 测试文件交互功能
- 在 Electron 界面输入文件名(如
test.txt)和内容(如Hello HarmonyOS PC Electron!); - 点击 “保存文件到鸿蒙 PC”,若提示 “文件已保存至鸿蒙 PC:/home/user/Documents/test.txt”,则写入成功;
- 在鸿蒙 PC 端调用
readFile方法(可添加按钮触发),若能读取到文件内容,则鸿蒙 PC 与 Electron 的文件交互功能实现成功。
3.3 功能 3:分布式设备资源调用(以鸿蒙 PC 为核心)
借助鸿蒙的分布式软总线,鸿蒙 PC 上的 Electron 应用可调用其他鸿蒙设备的资源(如智慧屏的摄像头、手机的麦克风)。本节以 “鸿蒙 PC 调用智慧屏摄像头拍照” 为例,演示分布式功能。
3.3.1 鸿蒙 PC 端代码(分布式能力配置)
- 配置分布式权限:在
module.json5中添加分布式相关权限(鸿蒙 PC 端必需):
{
"module": {
"abilities": [
{
// ... 原有配置 ...
"permissions": [
"ohos.permission.DISTRIBUTED_DATASYNC", // 分布式数据同步权限(鸿蒙PC必需)
"ohos.permission.CAMERA", // 摄像头权限
"ohos.permission.MICROPHONE" // 麦克风权限(可选)
]
}
]
}
}
- 封装分布式摄像头工具类(适配鸿蒙 PC 作为核心调用端):在
src/main/ets/utils目录下创建DistributedCameraUtil.ets:
import distributedDevice from '@ohos.distributedDevice';
import camera from '@ohos.multimedia.camera';
import image from '@ohos.multimedia.image';
import { BusinessError } from '@ohos.base';
/**
* 分布式摄像头工具类(鸿蒙PC为核心调用端)
*/
export class DistributedCameraUtil {
private static cameraManager: camera.CameraManager | null = null;
private static currentDeviceId: string = ''; // 分布式设备ID
/**
* 发现周边鸿蒙设备(鸿蒙PC主动发现)
* @returns 设备列表(设备ID + 设备名称)
*/
static async discoverDevices(): Promise<Array<{ deviceId: string; deviceName: string }>> {
try {
// 鸿蒙PC获取分布式设备列表
const deviceList = await distributedDevice.getTrustedDeviceListSync();
return deviceList.map(device => ({
deviceId: device.deviceId,
deviceName: device.deviceName
}));
} catch (error) {
const err = error as BusinessError;
throw new Error(`鸿蒙PC设备发现失败:${err.message}`);
}
}
/**
* 鸿蒙PC连接分布式设备的摄像头
* @param deviceId 目标设备ID(如智慧屏)
*/
static async connectCamera(deviceId: string): Promise<void> {
try {
// 保存目标设备ID
this.currentDeviceId = deviceId;
// 鸿蒙PC获取摄像头管理器(指定分布式设备ID)
this.cameraManager = await camera.getCameraManager(deviceId);
if (!this.cameraManager) {
throw new Error('鸿蒙PC获取摄像头管理器失败');
}
} catch (error) {
const err = error as BusinessError;
throw new Error(`鸿蒙PC摄像头连接失败:${err.message}`);
}
}
/**
* 拍照(鸿蒙PC触发,目标设备执行,返回结果)
* @returns 图片Base64字符串
*/
static async takePhoto(): Promise<string> {
if (!this.cameraManager || !this.currentDeviceId) {
throw new Error('鸿蒙PC未连接分布式摄像头');
}
try {
// 1. 鸿蒙PC获取目标设备摄像头列表
const cameraList = await this.cameraManager.getCameraList();
if (cameraList.length === 0) {
throw new Error('目标设备无可用摄像头');
}
const cameraDevice = cameraList[0]; // 选择第一个摄像头
// 2. 创建拍照会话
const photoSession = await this.cameraManager.createPhotoSession({
cameraDevice: cameraDevice,
// 配置图片输出格式(JPEG)
outputConfigs: [{
format: image.ImageFormat.JPEG,
size: { width: 1280, height: 720 }
}]
});
// 3. 鸿蒙PC触发拍照
const photoResult = await photoSession.takePhoto();
// 4. 关闭会话
await photoSession.close();
// 5. 将图片转换为Base64(返回给鸿蒙PC的Electron应用)
const imageBuffer = await photoResult.image.getBuffer();
const base64Str = Buffer.from(imageBuffer).toString('base64');
return base64Str;
} catch (error) {
const err = error as BusinessError;
throw new Error(`拍照失败:${err.message}`);
}
}
}
3.3.2 Electron 端代码(分布式功能界面,鸿蒙 PC 为操作端)
在index.html中添加分布式设备选择和拍照功能(适配鸿蒙 PC 操作场景)
<!-- 新增分布式摄像头区域(鸿蒙PC为核心调用端) -->
<div style="margin-top: 40px; padding: 0 20px; border-top: 1px solid #eee; padding-top: 20px;">
<h3>分布式摄像头调用(鸿蒙PC为核心)</h3>
<button id="discoverDevicesBtn">鸿蒙PC发现周边鸿蒙设备</button>
<select id="deviceSelect" style="margin-left: 10px; padding: 8px; display: none;"></select>
<button id="connectCameraBtn" style="margin-left: 10px; display: none;">连接目标设备摄像头</button>
<button id="takePhotoBtn" style="margin-left: 10px; display: none;">拍照(鸿蒙PC触发)</button>
<div id="cameraResult" style="margin-top: 20px;"></div>
<img id="photoImg" style="margin-top: 10px; max-width: 100%; display: none;" alt="拍照结果">
</div>
<script>
// 新增:分布式摄像头逻辑(鸿蒙PC为核心)
const discoverDevicesBtn = document.getElementById('discoverDevicesBtn');
const deviceSelect = document.getElementById('deviceSelect');
const connectCameraBtn = document.getElementById('connectCameraBtn');
const takePhotoBtn = document.getElementById('takePhotoBtn');
const cameraResultDiv = document.getElementById('cameraResult');
const photoImg = document.getElementById('photoImg');
// 1. 鸿蒙PC发现周边设备
discoverDevicesBtn.addEventListener('click', () => {
cameraResultDiv.innerText = '鸿蒙PC正在发现周边鸿蒙设备...';
// 发送设备发现请求到鸿蒙PC端
window.webkit.messageHandlers.postMessage.postMessage({
type: 'discoverDevices'
});
});
// 2. 鸿蒙PC连接摄像头
connectCameraBtn.addEventListener('click', () => {
const selectedDeviceId = deviceSelect.value;
if (!selectedDeviceId) {
cameraResultDiv.innerText = '请选择目标设备!';
return;
}
cameraResultDiv.innerText = '鸿蒙PC正在连接目标设备摄像头...';
// 发送连接请求到鸿蒙PC端
window.webkit.messageHandlers.postMessage.postMessage({
type: 'connectCamera',
deviceId: selectedDeviceId
});
});
// 3. 鸿蒙PC触发拍照
takePhotoBtn.addEventListener('click', () => {
cameraResultDiv.innerText = '鸿蒙PC正在触发拍照...';
// 发送拍照请求到鸿蒙PC端
window.webkit.messageHandlers.postMessage.postMessage({
type: 'takePhoto'
});
});
// 监听鸿蒙PC端返回的分布式消息
window.addEventListener('message', (event) => {
const { type, data, success, message, base64Str } = event.data;
switch (type) {
case 'discoverDevicesResult':
if (success) {
// 渲染设备列表(鸿蒙PC发现的设备)
deviceSelect.innerHTML = '';
data.forEach(device => {
const option = document.createElement('option');
option.value = device.deviceId;
option.text = device.deviceName;
deviceSelect.appendChild(option);
});
deviceSelect.style.display = 'inline-block';
connectCameraBtn.style.display = 'inline-block';
cameraResultDiv.innerText = `鸿蒙PC发现${data.length}台鸿蒙设备`;
} else {
cameraResultDiv.innerText = `设备发现失败:${message}`;
}
break;
case 'connectCameraResult':
if (success) {
takePhotoBtn.style.display = 'inline-block';
cameraResultDiv.innerText = '摄像头连接成功,鸿蒙PC可点击拍照';
} else {
cameraResultDiv.innerText = `连接失败:${message}`;
}
break;
case 'takePhotoResult':
if (success) {
// 显示拍照结果(Base64转图片,在鸿蒙PC上展示)
photoImg.src = `data:image/jpeg;base64,${base64Str}`;
photoImg.style.display = 'block';
cameraResultDiv.innerText = '拍照成功(鸿蒙PC触发)';
} else {
cameraResultDiv.innerText = `拍照失败:${message}`;
}
break;
}
});
</script>
3.3.3 鸿蒙 PC 端代码(分布式通信逻辑)
在ElectronPage.ets中添加分布式功能的通信处理(鸿蒙 PC 作为核心端):
import { DistributedCameraUtil } from '../utils/DistributedCameraUtil';
// 修改onMessage监听逻辑(鸿蒙PC端)
.webView.onMessage((event) => {
const message = event.message;
switch (message.type) {
case 'getDeviceInfo':
// ... 原有设备信息逻辑 ...
break;
case 'readFile':
// ... 原有文件读取逻辑 ...
break;
case 'discoverDevices':
// 处理鸿蒙PC的设备发现请求
DistributedCameraUtil.discoverDevices()
.then(devices => {
this.webViewController.postMessage({
type: 'discoverDevicesResult',
success: true,
data: devices
});
})
.catch(error => {
this.webViewController.postMessage({
type: 'discoverDevicesResult',
success: false,
message: error.message
});
});
break;
case 'connectCamera':
// 处理鸿蒙PC的摄像头连接请求
DistributedCameraUtil.connectCamera(message.deviceId)
.then(() => {
this.webViewController.postMessage({
type: 'connectCameraResult',
success: true
});
})
.catch(error => {
this.webViewController.postMessage({
type: 'connectCameraResult',
success: false,
message: error.message
});
});
break;
case 'takePhoto':
// 处理鸿蒙PC的拍照请求
DistributedCameraUtil.takePhoto()
.then(base64Str => {
this.webViewController.postMessage({
type: 'takePhotoResult',
success: true,
base64Str: base64Str
});
})
.catch(error => {
this.webViewController.postMessage({
type: 'takePhotoResult',
success: false,
message: error.message
});
});
break;
}
})
3.3.4 测试分布式功能
- 确保鸿蒙 PC 与智慧屏(或其他鸿蒙设备)处于同一局域网,并已登录同一华为账号(信任设备);
- 运行鸿蒙工程,点击 “鸿蒙 PC 发现周边鸿蒙设备”,若能显示智慧屏设备,则发现功能成功;
- 选择智慧屏,点击 “连接目标设备摄像头”,若提示 “摄像头连接成功,鸿蒙 PC 可点击拍照”,则连接功能成功;
- 点击 “拍照(鸿蒙 PC 触发)”,若能在鸿蒙 PC 的 Electron 界面显示智慧屏摄像头拍摄的图片,则分布式摄像头功能实现成功。
3.4 核心功能开发常见问题解决(鸿蒙 PC 场景)
| 问题现象 | 解决方案 | 参考链接 |
|---|---|---|
| 鸿蒙 PC 分布式设备发现为空 | 1. 确认鸿蒙 PC 与目标设备已登录同一华为账号;2. 开启鸿蒙 PC “分布式网络” 功能;3. 检查module.json5中已添加 DISTRIBUTED_DATASYNC 权限 |
鸿蒙分布式设备管理 |
| 摄像头调用报错 “Permission denied” | 1. 在鸿蒙 PC 的 “设置> 应用 > 权限管理” 中授予应用摄像头权限;2. 确保module.json5中已添加 CAMERA 权限 |
鸿蒙应用权限申请 |
| 图片 Base64 显示空白(鸿蒙 PC 端) | 1. 检查 Base64 字符串是否完整;2. 确认图片格式(JPEG/PNG)与data:image/xxx匹配;3. 缩小图片尺寸(避免鸿蒙 PC 端加载压力) |
鸿蒙图片处理指南 |
四、鸿蒙 PC Electron 应用场景与进阶实践
4.1 典型应用场景(聚焦鸿蒙 PC)
4.1.1 企业办公软件
- 场景描述:开发跨端办公套件(如文档编辑、会议软件),鸿蒙 PC 端用 Electron 实现复杂编辑功能,智慧屏端实现投屏演示,手机端实现移动审批。
- 技术优势:复用 Web 技术栈的办公组件(如 Quill、TinyMCE),借助鸿蒙分布式能力实现 “鸿蒙 PC 编辑 - 智慧屏演示 - 手机审批” 无缝流转。
- 案例参考:华为鸿蒙 PC 端的 “华为文档”,支持与手机、智慧屏同步编辑。
4.1.2 工具类应用
- 场景描述:开发代码编辑器、思维导图工具,鸿蒙 PC 端用 Electron 实现高效编辑,平板端用鸿蒙实现手写批注,手机端实现文件管理。
- 技术优势:Electron 支持 Node.js 后端能力(如代码编译、文件解析),鸿蒙 PC 支持键盘、鼠标精准操作,适配桌面端工具使用习惯。
- 开发建议:使用 Monaco Editor(VS Code 核心)作为代码编辑组件,集成鸿蒙 PC 的快捷键适配 API 提升操作效率。
4.1.3 多媒体应用
- 场景描述:开发视频剪辑、直播工具,鸿蒙 PC 端用 Electron 实现视频编辑,智慧屏端实现预览,手机端实现远程控制。
- 技术优势:Electron 可集成 FFmpeg(视频处理)、WebRTC(直播),鸿蒙 PC 可调用本地高性能硬件资源,同时协同其他设备的音视频能力。
- 资源推荐:Electron-FFmpeg 集成文档、鸿蒙 PC WebRTC 开发指南。
4.2 进阶实践:鸿蒙 PC 应用打包与发布
4.2.1 Electron 端打包(鸿蒙 PC 可执行文件)
使用electron-packager将 Electron 应用打包为鸿蒙 PC 端可执行文件:
- 安装打包工具:
npm install electron-packager --save-dev
- 添加打包脚本(
package.json):
"scripts": {
"start": "electron .",
"package:harmonypc": "electron-packager . HarmonyElectronApp --platform linux --arch x64 --out dist --overwrite"
}
- 执行打包命令:
npm run package:harmonypc
打包结果位于dist/HarmonyElectronApp-linux-x64目录,可直接在鸿蒙 PC 端运行。
4.2.2 鸿蒙 PC 端打包(HAP 文件)
通过 DevEco Studio 打包鸿蒙应用为 HAP 文件(可发布到鸿蒙应用市场,供鸿蒙 PC 用户下载):
- 配置签名:进入「Project Structure > Project > Signing Configs」,创建签名证书(需申请鸿蒙开发者账号);
- 打包 HAP:点击「Build > Build HAP (s)」,生成的 HAP 文件位于
build/outputs/hap目录; - 发布渠道:通过鸿蒙应用市场开发者平台提交 HAP 文件审核,审核通过后即可供鸿蒙 PC 用户下载安装。
4.3 性能优化建议(针对鸿蒙 PC)
- 减少 Electron 窗口渲染压力:
- 使用
webPreferences.plugins = false禁用不必要插件,降低鸿蒙 PC 资源占用; - 适配鸿蒙 PC 屏幕分辨率,避免过度缩放导致的渲染卡顿。
- 使用
- 优化鸿蒙 PC 分布式通信:
- 鸿蒙 PC 作为核心端,减少跨设备数据传输量(如压缩图片、分块传输);
- 使用鸿蒙的
DistributedData模块在鸿蒙 PC 本地缓存常用数据,避免重复请求。
- 内存管理:
- Electron 主进程避免创建过多窗口(鸿蒙 PC 端每个窗口占用独立内存);
- 鸿蒙 PC 端及时释放不再使用的资源(如关闭摄像头会话、释放文件句柄)。
五、总结与资源推荐
5.1 开发总结
鸿蒙 PC 与 Electron 结合,为桌面端全场景应用开发提供了 “Web 技术复用 + 分布式能力” 的新路径,尤其适配鸿蒙 PC 的生态建设需求。核心要点总结如下:
- 环境搭建:需同步配置 Node.js(16.x)、Electron(22.3.2)、DevEco Studio(4.0+),确保与鸿蒙 PC 版本兼容;
- 核心通信:通过 WebView 的
onMessage和postMessage实现 Electron 与鸿蒙 PC 的跨进程通信; - 分布式能力:以鸿蒙 PC 为核心,借助鸿蒙的
distributedDevice、camera等模块,实现多设备资源调用; - 场景落地:适合企业办公、工具类、多媒体等鸿蒙 PC 高频使用场景,可快速复用 Web 生态资源,加速鸿蒙 PC 应用开发。
5.2 官方资源推荐
- 鸿蒙 PC 开发官网:HarmonyOS for PC 开发者文档
- Electron 官方指南:Electron 快速入门
- 鸿蒙分布式能力:HarmonyOS 分布式技术文档
- 鸿蒙 API 参考:HarmonyOS API 9 文档
5.3 学习路径建议
- 入门阶段:掌握 Electron 基础(窗口创建、IPC 通信)、鸿蒙 PC DevEco Studio 使用;
- 进阶阶段:学习鸿蒙 PC 分布式 API、Electron 与鸿蒙 PC 的通信适配;
- 实战阶段:开发小型工具应用(如记事本、图片查看器),熟悉鸿蒙 PC 应用打包与发布流程;
- 深入阶段:优化鸿蒙 PC 应用性能、集成复杂功能(如视频处理、数据库),参与开源项目。
欢迎加入开源鸿蒙 PC 社区,与更多开发者交流技术、共享资源、共建生态:https://harmonypc.csdn.net/
通过本文的代码示例与指南,希望能帮助开发者快速上手鸿蒙 PC Electron 开发,共同推动鸿蒙 PC 桌面端生态的完善与发展。若在实践中遇到问题,可通过鸿蒙开发者论坛(HarmonyOS 开发者论坛)、Electron 社区(Electron Community)或开源鸿蒙 PC 社区寻求帮助。
更多推荐



所有评论(0)