鸿蒙OS与Electron的跨平台协作:打造桌面与设备互联应用
2026/5/23 2:10:59 网站建设 项目流程

引言

随着华为鸿蒙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集成

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询