news 2026/1/19 18:44:22

鸿蒙OS与Electron的跨平台协作:打造桌面与设备互联应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙OS与Electron的跨平台协作:打造桌面与设备互联应用

引言

随着华为鸿蒙OS(HarmonyOS)的快速发展,越来越多的开发者开始关注如何将现有技术栈与鸿蒙生态进行整合。而Electron作为构建跨平台桌面应用的成熟框架,能否与鸿蒙系统产生"化学反应"?本文将探索鸿蒙设备与Electron应用的协同工作模式,通过实际代码案例展示如何实现桌面应用与鸿蒙设备的无缝通信。

重要提示:鸿蒙OS本身并不直接支持运行Electron应用(Electron基于Chromium+Node.js,而鸿蒙有自己的应用框架),但我们可以利用网络通信实现两者间的协同工作。本文重点介绍这种跨平台协作模式

一、技术背景

1.1 鸿蒙OS网络能力

鸿蒙OS 3.0+ 提供了强大的网络通信能力:

  • 支持HTTP/HTTPS协议
  • 可创建本地HTTP服务器
  • 具备WebSocket通信能力
  • 支持局域网设备发现

1.2 Electron的网络优势

Electron作为桌面应用框架,天然具备:

  • 完整的Node.js后端能力
  • 便捷的HTTP客户端功能
  • 丰富的UI组件库
  • 跨Windows/macOS/Linux平台

1.3 协作模式

https://img-blog.csdnimg.cn/direct/8a7b8c9d0e1f4e4f8f4e4f4f4f4f4f4f4.png

核心思路
鸿蒙设备作为服务提供方运行HTTP服务,Electron应用作为客户端发起请求,通过局域网实现数据交互。

二、实战案例:设备状态监控系统

让我们实现一个简单的应用场景:
通过Electron桌面应用实时监控鸿蒙设备的电池状态和系统信息

2.1 鸿蒙端实现(服务提供方)

步骤1:创建鸿蒙项目
  1. 打开DevEco Studio
  2. 创建新项目:Create > Empty Ability
  3. 选择API Version 9+(推荐API 10)
步骤2:添加网络权限

module.json5中添加网络权限:

{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
}
}

{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
}
}

{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
}
}

{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
}
}

{

"module": {

"reqPermissions": [

{

"name": "ohos.permission.INTERNET"

},

{

"name": "ohos.permission.GET_NETWORK_INFO"

}

]

}

}

步骤3:实现HTTP服务

创建HttpServer.ets文件:

import http from '@ohos.net.http'; import battery from '@ohos.batteryManager'; export class DeviceServer { private server: http.HttpServer; constructor() { this.server = http.createHttpServer(); } start(port: number = 8080) { // 配置请求处理 this.server.on('request', (request: http.HttpRequest, response: http.HttpResponse) => { console.log(`Request received: ${request.url}`); // 处理不同API端点 if (request.url === '/api/status') { this.handleStatusRequest(response); } else if (request.url === '/api/battery') { this.handleBatteryRequest(response); } else { this.sendResponse(response, 404, 'Not Found'); } }); // 启动服务器 this.server.listen(port, () => { console.log(`HTTP server running on port ${port}`); }); } private handleStatusRequest(response: http.HttpResponse) { const status = { deviceName: 'HarmonyOS Device', osVersion: 'HarmonyOS 4.0', uptime: Math.floor(process.uptime() * 1000), timestamp: new Date().toISOString() }; this.sendJsonResponse(response, status); } private handleBatteryRequest(response: http.HttpResponse) { try { const level = battery.getBatteryLevel(); const status = battery.getChargingStatus(); const batteryInfo = { level: level * 100, isCharging: status === battery.ChargingStatus.CHARGING, health: battery.getHealthStatus(), temperature: battery.getBatteryTemperature() / 10 }; this.sendJsonResponse(response, batteryInfo); } catch (err) { console.error('Battery error:', err); this.sendResponse(response, 500, 'Failed to get battery info'); } } private sendJsonResponse(response: http.HttpResponse, data: any) { response.writeHeader(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); response.end(JSON.stringify(data)); } private sendResponse(response: http.HttpResponse, code: number, message: string) { response.writeHeader(code, { 'Content-Type': 'text/plain' }); response.end(message); } }
步骤4:在MainAbility中启动服务
// MainAbility.ets import { DeviceServer } from './HttpServer'; @Entry @Component struct MainAbility { private server: DeviceServer = new DeviceServer(); build() { // UI代码... } aboutToAppear() { // 启动HTTP服务 this.server.start(8080); console.log('Device server started'); // 保持后台运行(可选) this.keepAlive(); } private keepAlive() { // 实现后台保活逻辑(根据业务需求) console.log('Keeping server alive...'); } }

https://img-blog.csdnimg.cn/direct/3a4b5c6d7e8f9e4f8f4e4f4f4f4f4f4f4.png

2.2 Electron端实现(客户端)

步骤1:创建Electron项目
mkdir harmony-electron cd harmony-electron npm init -y npm install electron axios @types/node
步骤2:创建主进程文件

main.js

const { app, BrowserWindow, ipcMain } = require('electron')
const axios = require('axios')
const path = require('path')

// 鸿蒙设备IP(需替换为实际IP)
const HARMONY_DEVICE_IP = '192.168.1.100'

function createWindow() {
const win = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false,
contextIsolation: true
}
})

win.loadFile('index.html')

// 自动刷新设备数据
setInterval(() => {
fetchDeviceStatus(win)
fetchBatteryInfo(win)
}, 5000)
}

// 获取设备状态
async function fetchDeviceStatus(window) {
try {
const response = await axios.get(`http://${HARMONY_DEVICE_IP}:8080/api/status`)
window.webContents.send('device-status', response.data)
} catch (error) {
console.error('Status fetch error:', error.message)
window.webContents.send('device-status', {
error: '无法连接设备',
timestamp: new Date().toISOString()
})
}
}

// 获取电池信息
async function fetchBatteryInfo(window) {
try {
const response = await axios.get(`http://${HARMONY_DEVICE_IP}:8080/api/battery`)
window.webContents.send('battery-info', response.data)
} catch (error) {
console.error('Battery fetch error:', 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()
}
})

// 处理手动刷新请求
ipcMain.on('refresh-data', () => {
const windows = BrowserWindow.getAllWindows()
if (windows.length > 0) {
fetchDeviceStatus(windows[0])
fetchBatteryInfo(windows[0])
}
})

const { app, BrowserWindow, ipcMain } = require('electron')

const axios = require('axios')

const path = require('path')

// 鸿蒙设备IP(需替换为实际IP)

const HARMONY_DEVICE_IP = '192.168.1.100'

function createWindow() {

const win = new BrowserWindow({

width: 1000,

height: 700,

webPreferences: {

preload: path.join(__dirname, 'preload.js'),

nodeIntegration: false,

contextIsolation: true

}

})

win.loadFile('index.html')

// 自动刷新设备数据

setInterval(() => {

fetchDeviceStatus(win)

fetchBatteryInfo(win)

}, 5000)

}

// 获取设备状态

async function fetchDeviceStatus(window) {

try {

const response = await axios.get(`http://${HARMONY_DEVICE_IP}:8080/api/status`)

window.webContents.send('device-status', response.data)

} catch (error) {

console.error('Status fetch error:', error.message)

window.webContents.send('device-status', {

error: '无法连接设备',

timestamp: new Date().toISOString()

})

}

}

// 获取电池信息

async function fetchBatteryInfo(window) {

try {

const response = await axios.get(`http://${HARMONY_DEVICE_IP}:8080/api/battery`)

window.webContents.send('battery-info', response.data)

} catch (error) {

console.error('Battery fetch error:', 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()

}

})

// 处理手动刷新请求

ipcMain.on('refresh-data', () => {

const windows = BrowserWindow.getAllWindows()

if (windows.length > 0) {

fetchDeviceStatus(windows[0])

fetchBatteryInfo(windows[0])

}

})

步骤3:创建预加载脚本

preload.js

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {

onStatusUpdate: (callback) => ipcRenderer.on('device-status', callback),

onBatteryUpdate: (callback) => ipcRenderer.on('battery-info', callback),

refreshData: () => ipcRenderer.send('refresh-data')

})

步骤4:创建UI界面

index.html

<!DOCTYPE html>

window.electronAPI.onStatusUpdate((event, data) => {

if (data.error) {

deviceStatusEl.textContent = '离线';

deviceStatusEl.className = 'info-value error';

return;

}

deviceStatusEl.textContent = '在线';

deviceStatusEl.className = 'info-value';

lastUpdateEl.textContent = new Date().toLocaleTimeString();

deviceNameEl.textContent = data.deviceName;

osVersionEl.textContent = data.osVersion;

// 转换运行时间为可读格式

const uptimeMs = data.uptime;

const seconds = Math.floor((uptimeMs / 1000) % 60);

const minutes = Math.floor((uptimeMs / (1000 * 60)) % 60);

const hours = Math.floor((uptimeMs / (1000 * 60 * 60)) % 24);

uptimeEl.textContent = `${hours}h ${minutes}m ${seconds}s`;

});

// 处理电池信息更新

window.electronAPI.onBatteryUpdate((event, data) => {

if (data.error) return;

// 电量显示

batteryLevelEl.textContent = `${data.level.toFixed(1)}%`;

batteryFillEl.style.width = `${data.level}%`;

// 充电状态

if (data.isCharging) {

chargingStatusEl.textContent = '充电中';

chargingStatusEl.className = 'info-value charging';

} else {

chargingStatusEl.textContent = '未充电';

chargingStatusEl.className = 'info-value';

}

// 温度

temperatureEl.textContent = data.temperature.toFixed(1);

});

// 手动刷新按钮

refreshBtn.addEventListener('click', () => {

window.electronAPI.refreshData();

refreshBtn.textContent = '刷新中...';

setTimeout(() => {

refreshBtn.textContent = '手动刷新数据';

}, 1000);

});

});

</script>

</body>

</html>

步骤5:添加启动脚本

package.json中添加:

{
"scripts": {
"start": "electron ."
}
}

步骤6:运行Electron应用
npm start

https://img-blog.csdnimg.cn/direct/9a8b7c6d5e4f3e4f8f4e4f4f4f4f4f4f4.png

三、关键问题与解决方案

3.1 设备IP自动发现

手动输入IP不友好,可通过以下方式改进:

鸿蒙端广播服务

// 在HttpServer中添加 import wifi from '@ohos.wifi'; private broadcastService() { const ssid = wifi.getWifiSsid(); // 获取当前WiFi名称 const ip = wifi.getIpAddress(); // 获取设备IP // 通过UDP广播服务信息(简化示例) const broadcastMsg = `HARMONY_DEVICE:${ssid}:${ip}:8080`; // 实现UDP广播逻辑... }

Electron端自动发现

// 添加设备发现功能

function discoverHarmonyDevices() {

const dgram = require('dgram');

const client = dgram.createSocket('udp4');

client.bind(() => {

client.setBroadcast(true);

const message = Buffer.from('DISCOVER_HARMONY');

client.send(message, 0, message.length, 4000, '255.255.255.255');

});

client.on('message', (msg, rinfo) => {

if (msg.toString().startsWith('HARMONY_DEVICE')) {

const [, , ip, port] = msg.toString().split(':');

console.log(`Found device at ${ip}:${port}`);

// 更新UI显示发现的设备

}

});

}

3.2 安全性增强

  • 添加认证机制:在鸿蒙端实现简单的Token验证
  • 使用HTTPS:配置自签名证书实现安全通信
  • 限制IP访问:只允许特定IP范围访问
// 鸿蒙端添加Token验证 private handleStatusRequest(response: http.HttpResponse, request: http.HttpRequest) { const token = request.header['x-auth-token']; if (token !== 'YOUR_SECURE_TOKEN') { this.sendResponse(response, 401, 'Unauthorized'); return; } // ...继续处理 }

3.3 跨域问题处理

在鸿蒙HTTP响应中添加CORS头:

response.writeHeader(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST' });

四、应用场景拓展

  1. 设备调试工具:开发专业的鸿蒙设备调试桌面应用
  2. 多屏协同:实现桌面与鸿蒙设备的深度交互
  3. IoT管理平台:统一管理多个鸿蒙IoT设备
  4. 开发辅助工具:如资源管理、日志查看等

https://img-blog.csdnimg.cn/direct/1a2b3c4d5e6f7e4f8f4e4f4f4f4f4f4f4.png

五、总结

虽然鸿蒙OS与Electron属于不同的技术生态,但通过网络通信这一桥梁,我们可以实现:

  • 高效的跨平台协作
  • 桌面应用与移动设备的深度整合
  • 复用现有Electron技术栈

这种模式特别适合需要桌面管理界面+鸿蒙设备的场景,既发挥了Electron在桌面端的优势,又充分利用了鸿蒙设备的移动特性。

关键收获

  1. 鸿蒙可作为HTTP服务提供方
  2. Electron可作为功能强大的客户端
  3. 通过REST API实现数据互通
  4. 适用于设备监控、调试工具等场景

六、资源推荐

  1. 鸿蒙官方文档
  2. Electron官方文档
  3. 鸿蒙网络开发指南
  4. Electron与Node.js集成
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/16 12:52:53

分享几则中年夫妻关系的有益建议

著名演员何晴去世了&#xff0c;很震惊&#xff0c;她是我最喜欢的女演员&#xff0c;曾经出演过四大名著。分享几则中年夫妻关系的有益建议&#xff1a; 1、可以容忍对方的生活习惯。包括拉S放P、不叠被、不洗衣&#xff0c;但要管好自己&#xff0c;还是尽量别过份坦荡。 2、…

作者头像 李华
网站建设 2026/1/17 19:56:23

(108页PPT)园区大数据治理解决方案(附下载方式)

篇幅所限&#xff0c;本文只提供部分资料内容&#xff0c;完整资料请看下面链接 &#xff08;108页PPT&#xff09;园区大数据治理解决方案.pptx_智慧园区总体规划PPT资源-CSDN下载 资料解读&#xff1a;《园区大数据治理解决方案》 详细资料请看本解读文章的最后内容。 在数…

作者头像 李华
网站建设 2026/1/11 13:42:28

行为驱动开发(BDD)实践流程深度解析

1. BDD核心理念与测试价值重塑 行为驱动开发本质上是测试驱动开发(TDD)的演进延伸&#xff0c;其革命性在于将关注点从“代码功能验证”转向“业务行为实现”。对测试人员而言&#xff0c;这意味着&#xff1a; 需求澄清前移&#xff1a;测试人员在需求讨论阶段即参与行为场景…

作者头像 李华
网站建设 2026/1/2 10:58:27

如何快速构建企业级ICT资产管理系统:Chemex免费开源解决方案终极指南

如何快速构建企业级ICT资产管理系统&#xff1a;Chemex免费开源解决方案终极指南 【免费下载链接】chemex &#x1f525; 咖啡壶是一个免费、开源、高效且漂亮的资产管理平台。资产管理、归属/使用者追溯、盘点以及可靠的服务器状态管理面板。基于优雅的Laravel框架开发。 项…

作者头像 李华
网站建设 2026/1/11 17:28:48

1Panel面板OpenResty安装失败的完整解决方案

在使用1Panel面板进行OpenResty部署时&#xff0c;很多用户会遇到安装失败的问题&#xff0c;特别是在aarch64架构的Debian系统上。本文将从问题诊断、深度解析到实战修复&#xff0c;为您提供一套完整的解决方案。 【免费下载链接】1Panel 新一代的 Linux 服务器运维管理面板 …

作者头像 李华