diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 88ec5d6..b33feff 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -51,6 +51,15 @@ final class RunnerFlutterViewController: FlutterViewController { return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + override func applicationDidBecomeActive(_ application: UIApplication) { + super.applicationDidBecomeActive(application) + requestWirelessDataPrompt() + } + + func requestWirelessDataPrompt() { + wirelessDataPrompt.requestSystemPrompt() + } + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) registerWirelessDataChannel(engineBridge) diff --git a/ios/Runner/SceneDelegate.swift b/ios/Runner/SceneDelegate.swift index b9ce8ea..c1a5618 100644 --- a/ios/Runner/SceneDelegate.swift +++ b/ios/Runner/SceneDelegate.swift @@ -1,6 +1,11 @@ +// Author: fruit.com.cn + import Flutter import UIKit class SceneDelegate: FlutterSceneDelegate { - + override func sceneDidBecomeActive(_ scene: UIScene) { + super.sceneDidBecomeActive(scene) + (UIApplication.shared.delegate as? AppDelegate)?.requestWirelessDataPrompt() + } } diff --git a/ios/Runner/WirelessDataPrompt.swift b/ios/Runner/WirelessDataPrompt.swift index 63e3610..04b50bf 100644 --- a/ios/Runner/WirelessDataPrompt.swift +++ b/ios/Runner/WirelessDataPrompt.swift @@ -4,15 +4,19 @@ import CoreTelephony import Flutter import Foundation -/// 监听系统无线数据选择,供 Flutter 在首个接口请求前等待。 +/// 监听系统无线数据选择,并用 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 @@ -22,7 +26,17 @@ final class WirelessDataPrompt { } } - /// 状态未选择时先挂起;用户点选后完成全部等待。 + /// 应用进入前台后请求一次,促使系统弹出无线数据选择。 + 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 { @@ -37,7 +51,7 @@ final class WirelessDataPrompt { } private func completeIfDecided(_ state: CTCellularDataRestrictedState) { - if state == .restrictedStateUnknown { + if state != .notRestricted { return } lock.lock()