69 lines
1.8 KiB
Swift
69 lines
1.8 KiB
Swift
// Author: fruit.com.cn
|
|
|
|
import CoreTelephony
|
|
import Flutter
|
|
import Foundation
|
|
|
|
/// 监听系统无线数据选择,并用 URLSession 唤起系统选择框。
|
|
final class WirelessDataPrompt {
|
|
static let channelName = "com.stormg.lumadrama/wireless-data"
|
|
static let awaitDecisionMethod = "awaitDecision"
|
|
|
|
/// 系统选择框由 URLSession 触发,Dart 的 Socket 请求不会弹出。
|
|
private static let promptURL = URL(string: "https://captive.apple.com/hotspot-detect.html")
|
|
|
|
private let cellularData = CTCellularData()
|
|
private let lock = NSLock()
|
|
private var pending: [FlutterResult] = []
|
|
private var decided = false
|
|
private var didRequestPrompt = false
|
|
|
|
init() {
|
|
cellularData.cellularDataRestrictionDidUpdateNotifier = { [weak self] state in
|
|
DispatchQueue.main.async {
|
|
self?.completeIfDecided(state)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 应用进入前台后请求一次,促使系统弹出无线数据选择。
|
|
func requestSystemPrompt() {
|
|
guard !didRequestPrompt, let promptURL = Self.promptURL else {
|
|
return
|
|
}
|
|
didRequestPrompt = true
|
|
_ = cellularData.restrictedState
|
|
URLSession.shared.dataTask(with: promptURL) { _, _, _ in }.resume()
|
|
}
|
|
|
|
/// 未允许前先挂起;用户允许无线数据后再放行。
|
|
func awaitDecision(_ result: @escaping FlutterResult) {
|
|
lock.lock()
|
|
if decided {
|
|
lock.unlock()
|
|
DispatchQueue.main.async {
|
|
result(nil)
|
|
}
|
|
return
|
|
}
|
|
pending.append(result)
|
|
lock.unlock()
|
|
}
|
|
|
|
private func completeIfDecided(_ state: CTCellularDataRestrictedState) {
|
|
if state != .notRestricted {
|
|
return
|
|
}
|
|
lock.lock()
|
|
if decided {
|
|
lock.unlock()
|
|
return
|
|
}
|
|
decided = true
|
|
let waiters = pending
|
|
pending.removeAll()
|
|
lock.unlock()
|
|
waiters.forEach { $0(nil) }
|
|
}
|
|
}
|