电量监控方案设计
本文档结合 CCElectrictyMonitor
和 CCElectricitySampleManager
两个模块的代码,介绍 iOS 应用中电量监控的整体方案、工作流程及统计功能,并附带流程图以便理解。
1. 模块概述
1.1 CCElectrictyMonitor (电量监控器)
-
职责:实时监听设备电量变化,提供代理和闭包两种回调方式,支持 OC 调用。
-
功能:
- 开启电池监控(
UIDevice.current.isBatteryMonitoringEnabled = true
) - 定时器定时读取当前电量(默认10秒间隔)
- 通过代理或 block 回调通知电量变化
- 支持设置最小电量阈值(可扩展)
- 开启电池监控(
1.2 CCElectricitySampleManager (电量采样管理器)
-
职责:根据不同运行场景(前台、后台)周期性采集电量数据,统计累计时间,保存采样数据到文件。
-
功能:
- 支持前台和后台两种场景采样,移除待机场景
- 配置不同场景采样时间间隔(前台30分钟,后台10分钟)
- 统计每个采样周期内电量变化百分比
- 累计统计各场景总时间
- 支持数据持久化存储与加载(JSON格式)
- 支持导出采样数据文件路径供外部分析
2. 设计方案说明
- 实时电量监听 :
CCElectrictyMonitor
通过定时器定时读取系统电量,通知外部关注者。适合做即时电量变化响应。 - 场景周期采样 :
CCElectricitySampleManager
根据 APP 当前运行场景,周期性采样电量,统计累计耗时和电量变化。适合做长期电量消耗分析。 - 数据持久化:采样数据保存到本地 JSON 文件,支持断点续采和后续上传分析。
- 接口设计:均支持 Objective-C 访问,方便混合项目集成。
3. 工作流程

4. 关键代码说明
4.1 电量实时监听(CCElectrictyMonitor)
- 使用
UIDevice.current.batteryLevel
获取当前电量百分比(0~1) - 通过
Timer.scheduledTimer
每10秒触发一次电量读取 - 电量变化通过代理或闭包传递给调用者
- 支持设置最小电量阈值
minBatteryLevel
swift
@MainActor private func startTimerIfNeeded() {
guard timer == nil else { return }
timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { [weak self] _ in
Task { @MainActor in
self?.observeElectricityChanged()
}
}
observeElectricityChanged()
}
4.2 电量采样管理(CCElectricitySampleManager)
- 根据场景配置采样间隔,前台30分钟,后台10分钟
- 采样时记录电量百分比变化
- 累计每个场景的总时间
- 采样数据缓存,定期写入本地 JSON 文件
- 支持导出采样数据文件路径
less
@MainActor @objc public func addSample(scene: EnergySamplingScene,
batteryLevel: Float,
currentMA: Float,
controllerName: String) {
let now = Date().timeIntervalSince1970
guard shouldSample(scene: scene, now: now) else { return }
let startTime = lastSampleTimes[scene] ?? now
let startBattery = lastBatteryLevels[scene] ?? batteryLevel
let duration = now - startTime
totalDuration[scene, default: 0] += duration
let sample = EnergySample(
scene: scene,
startTimestamp: startTime,
endTimestamp: now,
batteryLevelStart: startBattery,
batteryLevelEnd: batteryLevel,
deviceModel: UIDevice.current.modelName,
controllerName: lastControllerNames[scene] ?? controllerName
)
samplesCache.append(sample)
lastSampleTimes[scene] = now
lastBatteryLevels[scene] = batteryLevel
lastControllerNames[scene] = controllerName
if now - lastSaveTime > saveInterval {
saveToFile()
lastSaveTime = now
}
}
5. 使用示例
php
// 监听实时电量变化
CCElectrictyMonitor.shared.addElectricityLevelListener { level in
print("当前电量:(level)%")
}
// 在合适时机调用采样(例如根据场景切换)
CCElectricitySampleManager.shared.addSample(scene: .foreground,
batteryLevel: UIDevice.current.batteryLevel,
currentMA: 0.0,
controllerName: "HomeViewController")
// 查询累计时间
let fgDuration = CCElectricitySampleManager.shared.totalDuration(for: .foreground)
print("前台累计时间:(fgDuration)秒")
6. 总结
本方案结合实时电量监听与周期采样统计两部分:
- 实时监听确保能够快速响应电量变化事件
- 周期采样统计支持长期耗电分析,区分前后台场景
- 数据持久化方便后续数据上传和分析
- 设计兼顾 Swift 与 Objective-C 混合项目的调用需求
通过该方案,可以科学监控和分析 APP 的电量消耗表现,辅助优化节能策略。