Files
iiEsaywebUIapp/ios/Runner/AppDelegate.swift

175 lines
5.5 KiB
Swift
Raw Normal View History

2025-08-10 01:20:45 +05:30
import Flutter
import UIKit
// Background streaming handler class
class BackgroundStreamingHandler: NSObject {
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
private var activeStreams: Set<String> = []
private var channel: FlutterMethodChannel?
override init() {
super.init()
setupNotifications()
}
func setup(with channel: FlutterMethodChannel) {
self.channel = channel
}
private func setupNotifications() {
NotificationCenter.default.addObserver(
self,
selector: #selector(appDidEnterBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(appWillEnterForeground),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
}
@objc private func appDidEnterBackground() {
if !activeStreams.isEmpty {
startBackgroundTask()
}
}
@objc private func appWillEnterForeground() {
endBackgroundTask()
}
func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "startBackgroundExecution":
if let args = call.arguments as? [String: Any],
let streamIds = args["streamIds"] as? [String] {
startBackgroundExecution(streamIds: streamIds)
result(nil)
} else {
result(FlutterError(code: "INVALID_ARGS", message: "Invalid arguments", details: nil))
}
case "stopBackgroundExecution":
if let args = call.arguments as? [String: Any],
let streamIds = args["streamIds"] as? [String] {
stopBackgroundExecution(streamIds: streamIds)
result(nil)
} else {
result(FlutterError(code: "INVALID_ARGS", message: "Invalid arguments", details: nil))
}
case "keepAlive":
keepAlive()
result(nil)
case "saveStreamStates":
if let args = call.arguments as? [String: Any],
let states = args["states"] as? [[String: Any]] {
saveStreamStates(states)
result(nil)
} else {
result(FlutterError(code: "INVALID_ARGS", message: "Invalid arguments", details: nil))
}
case "recoverStreamStates":
result(recoverStreamStates())
default:
result(FlutterMethodNotImplemented)
}
}
private func startBackgroundExecution(streamIds: [String]) {
activeStreams = Set(streamIds)
if UIApplication.shared.applicationState == .background {
startBackgroundTask()
}
}
private func stopBackgroundExecution(streamIds: [String]) {
streamIds.forEach { activeStreams.remove($0) }
if activeStreams.isEmpty {
endBackgroundTask()
}
}
private func startBackgroundTask() {
guard backgroundTask == .invalid else { return }
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "ConduitStreaming") { [weak self] in
self?.endBackgroundTask()
}
}
private func endBackgroundTask() {
guard backgroundTask != .invalid else { return }
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = .invalid
}
private func keepAlive() {
if backgroundTask != .invalid {
endBackgroundTask()
startBackgroundTask()
}
}
private func saveStreamStates(_ states: [[String: Any]]) {
UserDefaults.standard.set(states, forKey: "ConduitActiveStreams")
}
private func recoverStreamStates() -> [[String: Any]] {
return UserDefaults.standard.array(forKey: "ConduitActiveStreams") as? [[String: Any]] ?? []
}
deinit {
NotificationCenter.default.removeObserver(self)
endBackgroundTask()
}
}
2025-08-10 01:20:45 +05:30
@main
@objc class AppDelegate: FlutterAppDelegate {
private var backgroundStreamingHandler: BackgroundStreamingHandler?
2025-08-10 01:20:45 +05:30
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
2025-09-13 10:16:58 +05:30
// Setup background streaming handler with scene-safe rootViewController access
var controller: FlutterViewController?
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let root = scene.windows.first?.rootViewController as? FlutterViewController {
controller = root
} else if let legacy = window?.rootViewController as? FlutterViewController {
controller = legacy
}
if let controller {
let channel = FlutterMethodChannel(
name: "conduit/background_streaming",
binaryMessenger: controller.binaryMessenger
)
backgroundStreamingHandler = BackgroundStreamingHandler()
backgroundStreamingHandler?.setup(with: channel)
// Register method call handler
channel.setMethodCallHandler { [weak self] (call, result) in
self?.backgroundStreamingHandler?.handle(call, result: result)
}
}
2025-08-10 01:20:45 +05:30
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}