完成大厅业务期实时状态推送给 H5 的事件驱动链路。每次变化时同时(1)
重写对应 app_*.js 文件供下次 reload,(2)bridge.call 反向推送给当前
页 H5 — 双轨与原 msext 行为等价。
新增 Source/Resource/BatteryMonitor.swift:
- @MainActor public final class BatteryMonitor,shared 单例 + 幂等 start()
- 监听 UIDevice.batteryLevelDidChangeNotification + 启动期读首次值
- currentLevel 同步快照(max(level, 0) 兜底模拟器 -1)+ onChange 回调
- notification block 内 MainActor.assumeIsolated 安全跨到 main actor
新增 Source/Resource/AppLifecycleObserver.swift:
- @MainActor public final class AppLifecycleObserver,shared 单例 + 幂等 start()
- 监听 didEnterBackgroundNotification + willEnterForegroundNotification
- onBackground / onForeground 双钩子;assumeIsolated 同上
WebContainerViewController.writeAppDataFiles 接入(替换 inline addObserver):
- 3 个 monitor 启动统一聚合(NetworkMonitor + BatteryMonitor + AppLifecycle)
- BatteryMonitor.onChange:writeBattery + bridge.call("getBattery", "%.2f")
- NetworkMonitor.onChange:writeNetwork + bridge.call("getnetwork", "1"/"2"/"3")
- AppLifecycle.onBackground/Foreground:bridge.call("appservice", "1"/"2")
- 首次值改读 BatteryMonitor.currentLevel 而非 UIDevice 原始值
至此 Phase 2.B 全部完成(5 项反向 callback:getphoneinfo / getBattery /
getnetwork / appservice / shakeEnd 全部接好)。
剩 Phase 2.C ExternalSubscriptions 生命周期管理(防双发,栈深 ≥ 2 时
下层不发桥事件)。
BuildProject 通过
Plan §5 Phase 2.B 全部勾选
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
50 lines
1.5 KiB
Swift
50 lines
1.5 KiB
Swift
//
|
||
// BatteryMonitor.swift
|
||
// ylgamehall
|
||
//
|
||
// UIDevice.batteryLevelDidChangeNotification 的最简 wrap:
|
||
// 提供 currentLevel 同步快照 + onChange 主线程回调。
|
||
//
|
||
// 契约:docs/H5-Native-Contract.md §3.2 [2]getBattery 反向 callback
|
||
// Phase 2.9
|
||
//
|
||
|
||
import UIKit
|
||
|
||
@MainActor
|
||
public final class BatteryMonitor {
|
||
|
||
public static let shared = BatteryMonitor()
|
||
|
||
/// 当前电量 0.0…1.0;模拟器无电池硬件返回 -1,BatteryMonitor.start() 后兜底为 0
|
||
public private(set) var currentLevel: Float = 0
|
||
|
||
/// 电量变化回调(主线程触发)
|
||
public var onChange: (@MainActor (Float) -> Void)?
|
||
|
||
private var started = false
|
||
|
||
public init() {}
|
||
|
||
public func start() {
|
||
guard !started else { return }
|
||
started = true
|
||
UIDevice.current.isBatteryMonitoringEnabled = true
|
||
currentLevel = max(UIDevice.current.batteryLevel, 0)
|
||
NotificationCenter.default.addObserver(
|
||
forName: UIDevice.batteryLevelDidChangeNotification,
|
||
object: nil,
|
||
queue: .main
|
||
) { [weak self] _ in
|
||
// forName: + queue: .main 的 block 闭包在 main 队列触发;
|
||
// 用 MainActor.assumeIsolated 把它桥到 main actor 隔离
|
||
MainActor.assumeIsolated {
|
||
guard let self else { return }
|
||
let level = max(UIDevice.current.batteryLevel, 0)
|
||
self.currentLevel = level
|
||
self.onChange?(level)
|
||
}
|
||
}
|
||
}
|
||
}
|