2025-08-10 01:20:45 +05:30
|
|
|
import Flutter
|
|
|
|
|
import UIKit
|
|
|
|
|
|
2025-08-16 20:27:44 +05:30
|
|
|
// 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 {
|
2025-08-16 20:27:44 +05:30
|
|
|
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-08-16 20:27:44 +05:30
|
|
|
|
2025-09-18 15:01:21 +05:30
|
|
|
// Setup background streaming handler using the plugin registry messenger
|
|
|
|
|
if let registrar = self.registrar(forPlugin: "BackgroundStreamingHandler") {
|
2025-08-16 20:27:44 +05:30
|
|
|
let channel = FlutterMethodChannel(
|
|
|
|
|
name: "conduit/background_streaming",
|
2025-09-18 15:01:21 +05:30
|
|
|
binaryMessenger: registrar.messenger()
|
2025-08-16 20:27:44 +05:30
|
|
|
)
|
2025-09-18 15:01:21 +05:30
|
|
|
|
2025-08-16 20:27:44 +05:30
|
|
|
backgroundStreamingHandler = BackgroundStreamingHandler()
|
|
|
|
|
backgroundStreamingHandler?.setup(with: channel)
|
2025-09-18 15:01:21 +05:30
|
|
|
|
2025-08-16 20:27:44 +05:30
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
}
|