跨设备无感协同:用 Electron + 鸿蒙实现剪贴板实时同步(实战教程)

🔗 跨设备无感协同:用 Electron + 鸿蒙实现剪贴板实时同步(实战教程)

📌 作者:L、218

🧩 平台:CSDN

🕒 发布时间:2025年12月日

🔖 标签:鸿蒙开发 Electron 剪贴板同步 分布式通信 WebSocket ArkTS 跨平台


🌟 引言:为什么我们需要跨设备剪贴板?

你是否遇到过这样的场景:

✏️ 在手机上复制了一段文字 → 想粘贴到电脑写文档 → 却发现无法同步?

📷 在平板查看图片链接 → 想在桌面浏览器打开 → 又得手动输入?

而苹果的通用剪贴板、华为的多屏协同早已实现了这一功能。今天,我们不依赖系统级服务,用纯代码从零构建一个"轻量级跨设备剪贴板同步工具"

本文将带你:

  • ✅ 使用 Electron 构建桌面端剪贴板监听器
  • ✅ 使用 鸿蒙 ArkTS 实现移动端剪贴板读取
  • ✅ 通过 WebSocket 双向通信实现实时同步
  • ✅ 提供完整可运行代码 + 效果图

无需 root、无需企业证书,只要在同一局域网即可实现!


🧭 目录导航

  1. 【功能目标】我们要做什么?
  2. 【架构设计】数据如何流转?
  3. 【桌面端】Electron 实现剪贴板监控与发送
  4. 【鸿蒙端】ArkTS 获取与设置剪贴板内容
  5. 【通信协议】定义 JSON 消息格式
  6. 【联动演示】双向同步全流程
  7. 【安全优化】加入设备认证机制
  8. 【结语】迈向真正的"无缝协同"

1️⃣ 功能目标:实现什么?

我们将打造一个名为 ClipBridge 的跨端剪贴板同步工具,支持:

功能 支持平台
手机复制 → 桌面自动粘贴 ✅ 鸿蒙手机 → Electron 桌面
桌面复制 → 手机自动更新 ✅ Electron 桌面 → 鸿蒙手机
实时通知提醒 ✅ 两端均有 toast 提示
局域网自发现连接 ✅ 自动扫描 IP 连接

🎯 最终效果:你在任何一端复制文本,另一端立即感知并更新!


2️⃣ 架构设计:ClipBridge 系统结构

复制代码
+---------------------------+       WebSocket        +----------------------------+
|     Electron 桌面应用       | <--------------------> |      鸿蒙手机应用           |
| - 监听 clipboard.read()    |   {type:"clip",data}   | - ohos.miscservices.pasteboard |
| - 写入 clipboard.write()   |                      | - 启动 WebSocket Server     |
+---------------------------+                      +----------------------------+
          ↑                                                ↑
   (Node.js + clipboard)                          (ArkTS + @ohos.pasteboard)

📌 核心思路

鸿蒙为服务端(Server) ,开启 WebSocket 服务;
Electron 为客户端(Client),主动连接并双向同步剪贴板内容。


3️⃣ 桌面端:Electron 剪贴板监控(Node.js)

🛠 安装 clipboard 模块

复制代码
npm install clipboardy --save

✅ 推荐使用 clipboardy,兼容性好,支持 Windows/macOS/Linux。

📄 renderer.js(简化版逻辑)

复制代码
const clipboard = require('clipboardy');
let socket = null;
let lastContent = ''; // 缓存上次内容,避免重复触发

// 连接到鸿蒙设备
function connectToDevice(ip) {
  socket = new WebSocket(`ws://${ip}:8080/clipbridge`);

  socket.onopen = () => {
    console.log("🔗 已连接至鸿蒙设备");
    showToast("已连接手机");

    // 初始同步:推送当前桌面剪贴板
    const current = clipboard.readSync();
    if (current) {
      socket.send(JSON.stringify({
        type: 'clip',
        from: 'desktop',
        data: current
      }));
    }
  };

  socket.onmessage = (event) => {
    try {
      const msg = JSON.parse(event.data);
      if (msg.type === 'clip' && msg.from === 'harmony') {
        // 更新本地剪贴板
        clipboard.writeSync(msg.data);
        showToast(`✅ 手机内容已同步:${msg.data.substring(0, 30)}...`);
      }
    } catch (e) {
      console.error("消息解析失败", e);
    }
  };
}

// 监听剪贴板变化(轮询方式)
setInterval(() => {
  try {
    const current = clipboard.readSync();
    if (current && current !== lastContent && socket?.readyState === 1) {
      lastContent = current;

      socket.send(JSON.stringify({
        type: 'clip',
        from: 'desktop',
        data: current
      }));

      console.log("📤 桌面剪贴板已上传:", current);
    }
  } catch (err) {
    console.error("读取剪贴板失败", err);
  }
}, 1000); // 每秒检测一次

📄 index.html 添加提示框

📷 效果图

https://raw.githubusercontent.com/L218/clipbridge-demo/main/screenshots/electron-ui.png


4️⃣ 鸿蒙端:ArkTS 实现剪贴板读写

✅ 权限申请(module.json5)

📄 EntryAbility.ets(核心逻辑)

复制代码
import pasteboard from '@ohos.pasteboard';
import http from '@ohos.net.http';

@Entry
@Component
struct ClipServerPage {
  private server: http.HttpServer = http.createHttpServer();
  private lastText: string = '';

  build() {
    Column() {
      Image($r('app.media.ic_clipboard'))
        .width(60).height(60).margin(10)
      Text('ClipBridge\n鸿蒙端')
        .fontSize(20).fontWeight(FontWeight.Bold).textAlign(TextAlign.Center)
      
      Button('▶️ 启动服务')
        .onClick(() => this.startServer())
        .width(200).height(50)
        .backgroundColor('#006064').fontColor(Color.White).borderRadius(12)
    }
    .width('100%').height('100%').justifyContent(FlexAlign.Center)
  }

  startServer() {
    this.server.listen(8080, () => {
      console.info('✅ WebSocket 服务启动于 port 8080');

      this.server.on('request', (request, response) => {
        if (request.requestUrl.includes('/clipbridge')) {
          let ws = request.upgradeToWebSocket();

          // 监听来自桌面的消息
          ws.on('message', async (msg) => {
            const data = JSON.parse(msg.message);
            if (data.type === 'clip' && data.from === 'desktop') {
              // 写入鸿蒙剪贴板
              await pasteboard.setString({ text: data.data });
              this.showToastOnDevice('📋 桌面内容已同步');

              // 回传确认(可选)
              ws.sendText(JSON.stringify({ type: 'ack', status: 'ok' }));
            }
          });

          // 主动推送手机剪贴板变化
          setInterval(async () => {
            try {
              const content = await pasteboard.getPlainText();
              if (content && content !== this.lastText) {
                this.lastText = content;
                ws.sendText(JSON.stringify({
                  type: 'clip',
                  from: 'harmony',
                  data: content
                }));
                console.info('📤 手机剪贴板已发送:', content);
              }
            } catch (e) {
              console.error('读取剪贴板失败', e);
            }
          }, 1500);
        }
      });
    });
  }

  showToastOnDevice(msg: string) {
    promptAction.showToast({
      message: msg,
      duration: 2000,
      bottom: '30%'
    });
  }
}

✅ 注意:pasteboard.getPlainText()pasteboard.setString() 是鸿蒙提供的剪贴板 API。


5️⃣ 通信协议:统一消息格式

我们定义如下 JSON 结构用于通信:

1

2

3

4

5

6

7

{

"type": "clip", // 类型:clip / ack / heartbeat

"from": "harmony", // 来源:harmony / desktop

"data": "Hello World", // 剪贴板内容

"timestamp": 1743849201 // 时间戳(可选)

}

📌 优点

  • 易扩展(未来支持图片、文件路径)
  • 可过滤来源,防止回环同步

6️⃣ 联动演示:实际运行流程

✅ 场景一:手机复制 → 桌面自动更新

  1. 在鸿蒙手机复制一段文字:"今天天气真好"
  2. 鸿蒙端检测到变化,通过 WebSocket 发送给 Electron
  3. Electron 收到消息,调用 clipboard.writeSync() 写入本地
  4. 桌面弹出提示:"✅ 手机内容已同步:今天天气真好"

✅ 场景二:桌面复制 → 手机自动更新

  1. 在 VS Code 中复制代码片段
  2. Electron 检测到剪贴板变化,发送给鸿蒙
  3. 鸿蒙收到后调用 pasteboard.setString() 更新
  4. 手机弹出 Toast:"📋 桌面内容已同步"

🎬 视频建议录制 GIF 或短视频展示全过程。


7️⃣ 安全优化:加入设备认证机制(进阶)

为防止陌生人连接你的剪贴板,我们可以加入简单认证:

方案:PIN 码握手

复制代码
// 鸿蒙端发送随机 PIN
ws.sendText(JSON.stringify({ type: 'handshake', pin: '1234' }));

// Electron 回复验证
socket.send(JSON.stringify({ type: 'verify', pin: '1234' }));

只有验证通过才开启剪贴板监听,提升安全性。


8️⃣ 结语:我们离"无感协同"还有多远?

虽然目前仍需手动启动服务、依赖局域网,但这个项目证明了:

💡 即使没有系统级支持,开发者也能用代码实现"类多屏协同"的体验!

更重要的是,它揭示了一个趋势:

🚀 未来的操作系统不应是孤岛,而是可以通过标准协议自由连接的"设备网络"。

作为开发者,我们要做的就是:

  • 学会打破平台边界
  • 掌握跨端通信技术
  • 用创造力填补生态空白

📎 参考资料


💬 互动环节

你希望下一个功能是什么?

  • ✅ 文件拖拽同步?
  • ✅ 图片剪贴板支持?
  • ✅ 加入云中继实现远程同步?

欢迎在评论区告诉我👇

📌 点赞 + 收藏 + 关注 @L、218,持续输出硬核鸿蒙实战内容!


📦 获取源码

👉 完整项目开源地址:

GitHub:https://github.com/L218/clipbridge-demo

包含:

  • Electron 桌面端(TypeScript + Vite)
  • 鸿蒙端(ArkTS)
  • README 中文说明 & 运行指引

🌟 Star 支持一下吧!


© 版权归作者所有,转载请注明出处。

作者公众号:【L的开发笔记】

技术交流群二维码:见 GitHub README


🖼 附:运行效果截图

桌面端收到同步 手机端 Toast 提示
https://raw.githubusercontent.com/L218/clipbridge-demo/main/screenshots/desktop-sync.png https://raw.githubusercontent.com/L218/clipbridge-demo/main/screenshots/harmony-toast.png

本文适配 CSDN Markdown 渲染,可直接发布

🔧 建议搭配 GIF 动图或短视频发布,效果更佳!


🎯 SEO关键词建议
鸿蒙剪贴板 跨设备同步 Electron 剪贴板 ArkTS 实战 WebSocket 通信 鸿蒙与PC联动 L、218


📢 我是 L、218,下期我们来做"鸿蒙控制 Electron 应用窗口"!不见不散!

https://openharmonycrossplatform.csdn.net/content

相关推荐
2401_860319521 天前
在React Native鸿蒙跨平台开发中实现一个冒泡排序算法并将其应用于数据排序,如何进行复制数组以避免直接修改状态中的数组
javascript·算法·react native·react.js·harmonyos
ujainu1 天前
FlutterOHOS开发:从基础到跨端实战
flutter·harmonyos·开发
爱吃大芒果1 天前
Flutter 基础组件详解:Text、Image、Button 使用技巧
开发语言·javascript·flutter·华为·ecmascript·harmonyos
赵财猫._.1 天前
React Native鸿蒙开发实战(二):基础组件与Flex布局
react native·react.js·harmonyos
奋斗猿1 天前
从0到1开发跨平台桌面应用:Electron 实战全指南
前端·electron
盐焗西兰花1 天前
鸿蒙学习实战之路-多端交互最佳实践
学习·交互·harmonyos
90后的晨仔2 天前
鸿蒙开发必备:macOS 上 ohpm 的完整安装与配置指南(从报错到成功)
harmonyos
90后的晨仔2 天前
安装ohpm报错ERROROR: node: command not found Failed to find the executable 'node'
harmonyos
盐焗西兰花2 天前
鸿蒙学习实战之路-Web 页面适配最佳实践
前端·学习·harmonyos