如何使用Electron.js实现类似Hubstaff的URL与应用追踪功能?
Electron实现Hubstaff式应用与URL追踪方案
一、活跃应用追踪
借助active-win npm包获取系统当前激活的窗口信息,定时轮询记录应用切换情况:
const activeWin = require('active-win'); const { interval } = require('timers/promises'); // 追踪活跃应用 async function trackActiveApps() { let lastTrackedApp = null; // 每秒轮询一次 for await (const _ of interval(1000)) { try { const activeWindow = await activeWin(); if (!activeWindow) continue; const currentApp = activeWindow.owner.name; if (currentApp !== lastTrackedApp) { lastTrackedApp = currentApp; // 构造追踪日志 const appLog = { type: 'application', appName: currentApp, windowTitle: activeWindow.title, timestamp: Date.now(), userId: '当前用户唯一标识' // 需结合你的用户系统实现 }; // 处理日志(暂存/上传) processTrackLog(appLog); } } catch (err) { console.error('获取活跃应用失败:', err); } } } // 启动追踪 trackActiveApps();
二、URL追踪
分两种场景处理:
1. Electron内置BrowserWindow的URL追踪
监听窗口的导航事件,捕获路由变化:
const { BrowserWindow } = require('electron'); // 创建窗口时添加监听 const mainWindow = new BrowserWindow({ width: 1200, height: 800 }); // 监听页面跳转 mainWindow.webContents.on('did-navigate', (_, url) => { const urlLog = { type: 'url', url: url, source: 'internal', // 标记为内置窗口 timestamp: Date.now(), userId: '当前用户唯一标识' }; processTrackLog(urlLog); }); // 监听单页应用路由变化 mainWindow.webContents.on('did-navigate-in-page', (_, url) => { const urlLog = { type: 'url', url: url, source: 'internal', timestamp: Date.now(), userId: '当前用户唯一标识' }; processTrackLog(urlLog); });
2. 系统浏览器的URL追踪
需借助系统级能力实现,不同平台方案不同:
- macOS:通过AppleScript调用浏览器API获取当前标签页URL,结合
active-win判断浏览器是否激活:const { execSync } = require('child_process'); // 在trackActiveApps函数中扩展 if (['Google Chrome', 'Safari', 'Microsoft Edge'].includes(currentApp)) { try { // 以Chrome为例,执行AppleScript获取当前URL const rawUrl = execSync(`osascript -e 'tell application "${currentApp}" to get URL of active tab of front window'`); const currentUrl = rawUrl.toString().trim(); // 记录URL日志(逻辑同内置窗口) const urlLog = { type: 'url', url: currentUrl, source: `external_${currentApp.toLowerCase()}`, timestamp: Date.now(), userId: '当前用户唯一标识' }; processTrackLog(urlLog); } catch (err) { console.error(`获取${currentApp} URL失败:`, err); } } - Windows:可通过Win32 API或注册表钩子实现,也可以使用专门的npm包读取历史记录,但实时追踪需要系统权限。
- Linux:通过解析窗口标题(部分浏览器会在标题中显示URL)或借助桌面环境API实现。
三、数据存储与上传
为避免网络波动丢失数据,先本地缓存再定时上传:
const Store = require('electron-store'); const axios = require('axios'); // 或用Node.js内置http模块 const localStore = new Store(); const UPLOAD_INTERVAL = 5 * 60 * 1000; // 每5分钟上传一次 // 暂存日志到本地 function processTrackLog(log) { let cachedLogs = localStore.get('trackLogs', []); cachedLogs.push(log); // 限制本地缓存数量,防止占用过多空间 if (cachedLogs.length > 1000) { cachedLogs = cachedLogs.slice(-1000); } localStore.set('trackLogs', cachedLogs); } // 上传日志到服务器 async function uploadLogs() { const logs = localStore.get('trackLogs', []); if (logs.length === 0) return; try { await axios.post('https://你的服务器API地址/track', { userId: '当前用户唯一标识', logs: logs }, { headers: { 'Content-Type': 'application/json', // 可添加认证头,如Bearer token 'Authorization': `Bearer ${用户认证令牌}` } }); // 上传成功后清空本地缓存 localStore.set('trackLogs', []); } catch (err) { console.error('日志上传失败:', err); // 上传失败保留缓存,下次重试 } } // 启动定时上传 setInterval(uploadLogs, UPLOAD_INTERVAL); // 应用启动时尝试上传遗留日志 uploadLogs();
四、关键注意事项
- 权限申请:系统级追踪需要用户授权,比如macOS需开启「辅助功能」权限,Windows需调整隐私设置,Electron应用可通过弹窗引导用户手动授权。
- 隐私合规:必须在应用中明确告知用户追踪行为,获得用户同意,符合GDPR、CCPA等数据隐私法规。
- 性能优化:控制轮询频率(1秒一次足够),避免占用过多系统资源;本地缓存定期清理,防止存储溢出。
- 数据安全:上传日志使用HTTPS加密传输,本地敏感数据可加密存储(如
electron-store支持加密选项)。
内容的提问来源于stack exchange,提问作者Ashikur Rahman Munna
相关产品推荐
相关产品推荐

