Hi Kevin
Thank you for the reply and the link for detailed background task information.
Here is what I am trying to do:
The network extension receives a file from peers via the established packet tunnel similar to airdrop.
The network extension then needs to notify the suspended main APP about receiving the file by submitting a background task request for an ID to get the main APP to run a background task.
The main APP registers to be waken up by the ID and moves the file from the shared container to its own document area so that the Files app can view it.
Here is the code snippet that does that.
`
import NetworkExtension
import BackgroundTasks
import os
// In NEPacketTunnelProvider
class PacketTunnelProvider: NEPacketTunnelProvider {
private static let log = OSLog(subsystem: "io.cylonix.sase", category: "NetworkExtension")
func handleFileReceipt(fileName: String) {
let defaults = UserDefaults(suiteName: "group.io.cylonix.sase")
defaults?.set(true, forKey: "FileReceived")
defaults?.set(fileName, forKey: "FileName")
defaults?.synchronize()
os_log(.info, log: Self.log, "File receipt recorded: %{public}@ at %{public}@", fileName, Date().description)
scheduleRefreshTask()
}
private func scheduleRefreshTask() {
let request = BGAppRefreshTaskRequest(identifier: "io.cylonix.sase.ios.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 1)
os_log(.info, log: Self.log, "Submitting refresh task")
do {
try BGTaskScheduler.shared.submit(request)
os_log(.info, log: Self.log, "Refresh task submitted")
} catch {
os_log(.error, log: Self.log, "Refresh task submission failed: %{public}@", error.localizedDescription)
}
}
}
// In BackgroundTaskManager
class BackgroundTaskManager {
static let shared = BackgroundTaskManager()
private static let log = OSLog(subsystem: "io.cylonix.sase", category: "MainApp")
func registerBackgroundTasks() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "io.cylonix.sase.ios.refresh", using: .main) { task in
self.handleRefreshTask(task as! BGAppRefreshTask)
}
}
func handleRefreshTask(_ task: BGAppRefreshTask) {
os_log(.info, log: Self.log, "Handling refresh task")
task.expirationHandler = {
os_log(.error, log: Self.log, "Refresh task expired")
task.setTaskCompleted(success: false)
}
checkMissedFiles()
task.setTaskCompleted(success: true)
}
func checkMissedFiles() {
let defaults = UserDefaults(suiteName: "group.io.cylonix.sase")
if defaults?.bool(forKey: "FileReceived") == true, let fileName = defaults?.string(forKey: "FileName") {
os_log(.info, log: Self.log, "Found missed file: %{public}@", fileName)
defaults?.set(false, forKey: "FileReceived")
defaults?.set(nil, forKey: "FileName")
defaults?.synchronize()
}
}
}`
When I am running the test, I didn't run it through Xcode in debug mode as in that case the main app always stays active. I did it through the release mode either from the test flight distribution or via "flutter run --release" that's in release mode too. I also tried background processing task too and the behavior is the same.
Thanks,
Randy