LNNetworkMonitor.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //
  2. // LNNetworkMonitor.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/11/2.
  6. //
  7. import Foundation
  8. import Network
  9. import CoreTelephony
  10. protocol LNNetworkMonitorNotify {
  11. func onNetworkStateChanged(state: LNNetworkState)
  12. }
  13. extension LNNetworkMonitorNotify {
  14. func onNetworkStateChanged(state: LNNetworkState) {}
  15. }
  16. enum LNNetworkState {
  17. case noNetwork
  18. case available
  19. }
  20. enum LNNetworkType {
  21. case unknown // 未知
  22. case notConnected // 无网络
  23. case wifi // WiFi
  24. case cellular2G // 2G
  25. case cellular3G // 3G
  26. case cellular4G // 4G
  27. case cellular5G // 5G
  28. var desc: String {
  29. switch self {
  30. case .unknown: "unknown"
  31. case .notConnected: "unknown"
  32. case .wifi: "wifi"
  33. case .cellular2G: "2g"
  34. case .cellular3G: "3g"
  35. case .cellular4G: "4g"
  36. case .cellular5G: "5g"
  37. }
  38. }
  39. }
  40. class LNNetworkMonitor {
  41. // 创建网络路径监听器(可指定监听的网络类型,如 .cellular、.wifi 等,nil 表示监听所有类型)
  42. private static let monitor = NWPathMonitor()
  43. // 蜂窝网络信息管理器
  44. private static let telephonyInfo = CTTelephonyNetworkInfo()
  45. // 用于在主线程处理回调
  46. private static let queue = DispatchQueue(label: "LNNetworkMonitor")
  47. private(set) static var curState: LNNetworkState = .noNetwork {
  48. didSet {
  49. if oldValue != curState {
  50. notifyNeetworkStateChanged()
  51. }
  52. }
  53. }
  54. static func startMonitoring() {
  55. // 设置路径变化的回调
  56. monitor.pathUpdateHandler = { path in
  57. // 检查当前网络的授权状态
  58. switch path.status {
  59. case .satisfied:
  60. // 网络已连接(可能已授权)
  61. curState = .available
  62. case .unsatisfied:
  63. // 网络未连接(可能因授权问题导致)
  64. Log.d("网络未连接,可能未授权或无网络")
  65. curState = .noNetwork
  66. case .requiresConnection:
  67. // 正在连接中(可能需要等待授权)
  68. Log.d("正在连接网络...")
  69. curState = .noNetwork
  70. @unknown default:
  71. Log.d("未知网络状态")
  72. curState = .noNetwork
  73. }
  74. // // 更精确的授权状态判断(通过 path.isExpensive 等属性辅助判断)
  75. // if path.isExpensive {
  76. // print("当前网络为蜂窝网络或付费网络")
  77. // }
  78. //
  79. // // 检查是否受限于低数据模式
  80. // if path.isConstrained {
  81. // print("网络受限于低数据模式")
  82. // }
  83. }
  84. // 开始监听(指定处理队列)
  85. monitor.start(queue: queue)
  86. }
  87. // 停止监听(例如在页面销毁时调用)
  88. static func stopMonitoring() {
  89. monitor.cancel()
  90. }
  91. static var curNetworkType: LNNetworkType {
  92. let path = monitor.currentPath
  93. guard path.status == .satisfied else {
  94. return .notConnected
  95. }
  96. if path.usesInterfaceType(.wifi) {
  97. return .wifi
  98. }
  99. if path.usesInterfaceType(.cellular) {
  100. return cellularNetworkType
  101. }
  102. return .unknown
  103. }
  104. static var networkProvider: String {
  105. if let carriers = telephonyInfo.serviceSubscriberCellularProviders {
  106. // 遍历所有 SIM 卡的网络类型(取第一个有效类型)
  107. for (_, carrier) in carriers {
  108. if let name = carrier.carrierName, !name.isEmpty {
  109. return name
  110. }
  111. }
  112. }
  113. return ""
  114. }
  115. private static var cellularNetworkType: LNNetworkType {
  116. if let serviceRadioMap = telephonyInfo.serviceCurrentRadioAccessTechnology {
  117. // 遍历所有 SIM 卡的网络类型(取第一个有效类型)
  118. for (_, radioType) in serviceRadioMap {
  119. return mapRadioTypeToNetworkType(radioType)
  120. }
  121. }
  122. return .unknown
  123. }
  124. // 映射无线电类型到网络类型
  125. private static func mapRadioTypeToNetworkType(_ radioType: String) -> LNNetworkType {
  126. switch radioType {
  127. // 2G 类型
  128. case CTRadioAccessTechnologyGPRS,
  129. CTRadioAccessTechnologyEdge,
  130. CTRadioAccessTechnologyCDMA1x:
  131. return .cellular2G
  132. // 3G 类型
  133. case CTRadioAccessTechnologyWCDMA,
  134. CTRadioAccessTechnologyHSDPA,
  135. CTRadioAccessTechnologyHSUPA,
  136. CTRadioAccessTechnologyCDMAEVDORev0,
  137. CTRadioAccessTechnologyCDMAEVDORevA,
  138. CTRadioAccessTechnologyCDMAEVDORevB,
  139. CTRadioAccessTechnologyeHRPD:
  140. return .cellular3G
  141. // 4G LTE
  142. case CTRadioAccessTechnologyLTE:
  143. return .cellular4G
  144. // 5G(iOS 14.1+ 支持)
  145. case CTRadioAccessTechnologyNR:
  146. return .cellular5G
  147. default:
  148. return .unknown
  149. }
  150. }
  151. }
  152. extension LNNetworkMonitor {
  153. private static func notifyNeetworkStateChanged() {
  154. LNEventDeliver.notifyEvent { ($0 as? LNNetworkMonitorNotify)?.onNetworkStateChanged(state: curState) }
  155. }
  156. }