powerMonitor 与 systemPreferences:电源状态与系统设置
本教程共 45 篇 · 第 26 篇 · 更新于 2026-08-03
26. powerMonitor 与 systemPreferences:电源与系统设置
本节目标
- 用
powerMonitor监听系统的睡眠、唤醒、锁屏事件。 - 查询系统空闲状态、是否使用电池供电。
- 用
systemPreferences读取系统外观(明暗)与强调色。 - 检查麦克风、摄像头、屏幕的媒体访问权限状态。
- 理解这些能力的进程归属与平台限制。
26-1 powerMonitor 的用途
powerMonitor 模块用来监控系统的电源状态变化。它在主进程运行,本身是一个 EventEmitter。典型用途是:系统进入睡眠前保存状态,唤醒后恢复连接,锁屏时暂停敏感操作。
它的事件大多是平台相关的。例如 suspend 和 resume 在系统挂起与恢复时触发;lock-screen 与 unlock-screen 在锁屏前后触发(macOS 与 Windows)。
下面演示一组常见监听,把它们集中放到 app.whenReady() 之后。
// 主进程 main.js
const { app, powerMonitor } = require('electron/main')
app.whenReady().then(() => {
powerMonitor.on('suspend', () => {
console.log('系统即将挂起,保存状态')
})
powerMonitor.on('resume', () => {
console.log('系统已恢复,重建连接')
})
powerMonitor.on('lock-screen', () => {
console.log('屏幕已锁定')
})
powerMonitor.on('unlock-screen', () => {
console.log('屏幕已解锁')
})
})
26-2 电池与电源事件
对于笔记本,on-ac 与 on-battery 事件在系统切换到交流电或电池供电时触发。macOS 与 Windows 支持这两个事件。
如果你想主动查询当前是否靠电池运行,可以用 isOnBatteryPower() 方法,或直接读 onBatteryPower 属性(布尔值)。
// 主进程 main.js
const { powerMonitor } = require('electron/main')
powerMonitor.on('on-battery', () => {
console.log('切换到电池,降低负载')
})
powerMonitor.on('on-ac', () => {
console.log('切换到电源,恢复正常')
})
// 主动查询
if (powerMonitor.isOnBatteryPower()) {
console.log('当前使用电池')
}
macOS 上还有一组与系统温度、CPU 限速相关的事件与方法:thermal-state-change 事件、getCurrentThermalState()、speed-limit-change 事件。当设备过热时,应用可以主动减少视频编码等重负载任务。
26-3 系统空闲与关机
powerMonitor 提供两个查询方法:getSystemIdleState(threshold) 返回当前空闲状态(active、idle、locked、unknown),getSystemIdleTime() 返回空闲秒数。
这两个方法常用来做「一段时间无操作就自动锁定」之类的功能,阈值以秒为单位。
// 主进程 main.js
const { powerMonitor } = require('electron/main')
const state = powerMonitor.getSystemIdleState(60)
console.log('空闲状态:', state)
const idleSeconds = powerMonitor.getSystemIdleTime()
console.log('已空闲秒数:', idleSeconds)
Linux 与 macOS 还支持 shutdown 事件。在系统准备重启或关机时触发;如果你在处理器里调用 event.preventDefault(),Electron 会尝试延迟关机,给应用留出干净退出的时间。此时应用应尽快调用 app.quit()。
26-4 systemPreferences 读取外观
systemPreferences 用来读取系统的偏好设置,同样运行在主进程(也支持 utility 进程)。它最有用的场景之一,是感知系统的明暗外观,从而让应用界面跟随系统主题。
macOS 上 getEffectiveAppearance() 返回当前生效的外观,值为 dark、light 或 unknown。effectiveAppearance 只读属性也能直接读取。
// 主进程 main.js
const { systemPreferences } = require('electron/main')
console.log('当前外观:', systemPreferences.getEffectiveAppearance())
需要注意:外观偏好在不同平台暴露程度不同。更通用的「跟随系统明暗」能力,Electron 还提供了专门的 nativeTheme 模块(如 nativeTheme.shouldUseDarkColors 与 updated 事件),跨平台更省心。若你的目标只是跟随明暗主题,优先用 nativeTheme。
26-5 颜色与强调色
systemPreferences.getAccentColor() 返回系统强调色(RGBA 十六进制字符串),例如 "aabbccdd"。Windows 与 macOS 可用 getColor(name) 取各类系统颜色(窗口背景、文字、菜单等)。
// 主进程 main.js
const { systemPreferences } = require('electron/main')
const accent = systemPreferences.getAccentColor()
console.log('强调色:', accent)
// 取窗口背景色(平台相关)
const bg = systemPreferences.getColor('window')
Windows 与 Linux 上,当强调色或颜色变化时,会分别发出 accent-color-changed 与 color-changed 事件,可据此刷新界面配色。
getAnimationSettings() 返回一个对象,包含 shouldRenderRichAnimation、scrollAnimationsEnabledBySystem、prefersReducedMotion。它能帮你判断用户是否偏好「减少动态效果」,从而决定是否播放重动画。
26-6 媒体访问权限
桌面捕获、麦克风、摄像头等功能需要用户授权。systemPreferences.getMediaAccessStatus(mediaType) 用来查询授权状态,参数可以是 microphone、camera、screen,返回 not-determined、granted、denied、restricted 或 unknown。
macOS 10.15 之后,捕获屏幕需要用户同意;10.14 之后麦克风与摄像头同理。下面的代码在启动屏幕捕获前先检查权限。
// 主进程 main.js
const { systemPreferences } = require('electron/main')
const status = systemPreferences.getMediaAccessStatus('screen')
if (status === 'granted') {
console.log('已授权屏幕捕获')
} else {
console.log('屏幕捕获权限状态:', status)
}
macOS 上 askForMediaAccess('microphone' | 'camera') 会弹出系统授权对话框,返回 Promise<boolean>。使用它时必须在 Info.plist 里配置 NSMicrophoneUsageDescription 等说明字符串,否则对话框无法正确弹出。
26-7 一个实用的组合场景
把电源事件与系统设置结合起来,可以做出贴心的体验。比如用户锁屏时暂停计时或挂起网络请求,解锁后再恢复;当系统切到电池供电时自动降低刷新频率,插上电源再恢复。
这类逻辑都放在主进程:用 powerMonitor 的事件感知状态切换,用 systemPreferences 读取当时的系统偏好,两者配合形成完整的「环境感知」能力。
// 主进程 main.js
const { powerMonitor, systemPreferences } = require('electron/main')
powerMonitor.on('lock-screen', () => {
// 暂停敏感或耗电操作
})
powerMonitor.on('unlock-screen', () => {
// 恢复操作
})
powerMonitor.on('on-battery', () => {
console.log('省电模式:', systemPreferences.getAnimationSettings())
})
如果你真正想要的是「界面跟随系统明暗」,记住优先用 nativeTheme 模块:它的 shouldUseDarkColors 与 updated 事件跨平台统一,比只用 systemPreferences.getEffectiveAppearance() 更稳妥。
再补充 mac 上的温度管理。当设备过热时,thermal-state-change 会给出 nominal、fair、serious、critical 等状态,应用可据此降低视频编码码率或暂停后台任务。getCurrentThermalState() 则能主动查询当前温度档位,便于在关键操作前评估是否合适继续。
还有一个常被忽略的能力:getSystemIdleTime() 与 getSystemIdleState(threshold)。前者返回系统空闲秒数,后者按你给的阈值返回 active、idle、locked 等状态。它们适合实现「长时间无操作就自动进入屏保或锁定」的逻辑,也常用于配合电源事件判断用户是否真的离开。Linux 与 macOS 还支持 shutdown 事件,在系统准备关机时调用 preventDefault() 可争取时间让应用干净退出,但务必尽快 app.quit(),否则会拖慢系统关机。
最后补充:systemPreferences 里很多方法带平台标签,例如 macOS 专属的 getUserDefault、askForMediaAccess 等。写跨平台代码时,调用前应先用 process.platform 判断,或为不支持的平台提供兜底,避免在不支持的系统上抛异常中断主进程逻辑。
常见误区
不要把 powerMonitor 事件当作跨平台一致的能力。许多事件只在 macOS 或 Windows 生效(文档里标注了平台),Linux 下可能收不到,需要做降级处理。
不要为了「跟随明暗主题」而只依赖 systemPreferences.getEffectiveAppearance()。它主要在 macOS 有意义,跨平台请优先用 nativeTheme,否则 Windows 与 Linux 的表现可能不符合预期。
注意 getMediaAccessStatus('screen') 在 macOS 10.15 之前始终返回 granted。在老系统上不能据此判断真实授权,需结合运行时捕获结果做容错。