BGAppRefreshTask is not working, I marked the option of background fetch capability
The method inside BGTaskScheduler.shared.register is never called
my code:
private let appRefreshTaskId = "internetDisconnectionsId"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
BGTaskScheduler.shared.register(forTaskWithIdentifier: appRefreshTaskId, using: nil) { task in
self.handleAppRefreshTask(task: task as! BGAppRefreshTask)
}
}
return true
}
func handleAppRefreshTask(task: BGAppRefreshTask) {
task.expirationHandler = {
print("Background Working")
task.setTaskCompleted(success: true)
}
}
#available(iOS 13.0, *)
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: appRefreshTaskId)
request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // Refresh after 2 minutes.
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh task \(error.localizedDescription)")
}
}
func sceneDidEnterBackground(_ scene: UIScene) {
(UIApplication.shared.delegate as! AppDelegate).scheduleAppRefresh()
print("called")
}
I would love to understand where I am wrong
Related
I'm trying to display an ad with GADAppOpenAd
The problem is, every initial login to the application, no advertisement is displayed, only when I go to the background and return to the application, then an advertisement appears,
I'm trying to have an advertisement appear on the initial login as well
var appOpenAd: GADAppOpenAd?
var loadTime = Date()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GADMobileAds.sharedInstance().start(completionHandler: nil)
requestAppOpenAd()
return true
}
extension AppDelegate:GADFullScreenContentDelegate {
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
requestAppOpenAd()
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
requestAppOpenAd()
}
func requestAppOpenAd() {
let request = GADRequest()
GADAppOpenAd.load(withAdUnitID: "ca-app-pub-3940256099942544/5662855259",
request: request,
orientation: UIInterfaceOrientation.portrait,
completionHandler: { (appOpenAdIn, _) in
self.appOpenAd = appOpenAdIn
self.appOpenAd?.fullScreenContentDelegate = self
self.loadTime = Date()
print("Ad is ready")
})
}
func tryToPresentAd() {
guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
return
}
if let gOpenAd = self.appOpenAd, wasLoadTimeLessThanNHoursAgo(thresholdN: 4){
gOpenAd.present(fromRootViewController: rootViewController)
} else {
self.requestAppOpenAd()
}
}
func wasLoadTimeLessThanNHoursAgo(thresholdN: Int) -> Bool {
let now = Date()
let timeIntervalBetweenNowAndLoadTime = now.timeIntervalSince(self.loadTime)
let secondsPerHour = 3600.0
let intervalInHours = timeIntervalBetweenNowAndLoadTime / secondsPerHour
return intervalInHours < Double(thresholdN)
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidBecomeActive(_ scene: UIScene) {
(UIApplication.shared.delegate as? AppDelegate)?.tryToPresentAd()
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.fetch.background", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.fetch.background")
// Fetch no earlier than 15 minutes from now.
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
// Schedule a new refresh task.
scheduleAppRefresh()
print("this background fetch called")
}
Above Code BGTaskScheduler completion Not working in swift 5, I added identifier with info.plist file permission. I need to use API with app background state. Please assist how can I achieve this one. Thanks
I am creating my own background task and I keep getting an error stating: 'Launch handler for task with identifier "processingTaskId" has already been registered'. I am still learning and would like to understand this error more.
code
import UIKit
import Flutter
import BackgroundTasks
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
let processingTaskId = "com.demo.processingtask"
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GeneratedPluginRegistrant.register(with: self)
if #available(iOS 13, *) {
BGTaskScheduler.shared.register(forTaskWithIdentifier: processingTaskId, using: nil) { task in
self.handleTask(task: task as! BGProcessingTask)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
#available(iOS 13.0, *)
func handleTask(task: BGProcessingTask) {
scheduleTask()
task.setTaskCompleted(success: true)
}
#available(iOS 13.0, *)
func scheduleTask() {
let request = BGProcessingTaskRequest(identifier: processingTaskId)
request.earliestBeginDate = nil
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule task: (error)")
}
}
}
I am trying to use the BackgroundTask framework to run a block of code periodically when the user closes the app. Preferably, I would want the code to run once every hour. In the project file below, I have the code change a value stored in UserDefaults, but no matter how long I wait it never runs the code in the task.
AppDelegate.swift
import UIKit
import BackgroundTasks
import OSLog
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.refresh", using: nil) { task in
Logger().info("[BGTASK] Preform bg fetch \("com.example.refresh")")
task.setTaskCompleted(success: true)
self.scheduleAppRefresh()
}
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.restock", using: nil) { task in
Logger().info("[BGTASK] Preform bg fetch \("com.example.restock")")
AppUserDefaults.newString = "New String" // <-- The string is changed here
task.setTaskCompleted(success: true)
self.scheduleBackgroundProcessing()
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh task \(error.localizedDescription)")
}
}
func scheduleBackgroundProcessing() {
let request = BGProcessingTaskRequest(identifier: "com.example.restock")
request.requiresNetworkConnectivity = true
request.requiresExternalPower = false
request.earliestBeginDate = Date(timeIntervalSinceNow: 1 * 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule image fetch: (error)")
}
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func applicationDidEnterBackground(_ application: UIApplication) {
Logger().info("App did enter background")
self.scheduleAppRefresh()
self.scheduleBackgroundProcessing()
}
}
When the app loads, I show newString in the ContentView:
ContentView.swift
import SwiftUI
import UserNotifications
struct ContentView: View {
var body: some View {
Text("New String: \(AppUserDefaults.newString)")
}
}
Project
I want to run the function in the background. But I get an error. The error I received is
"nw_connection_receive_internal_block_invoke.
Why am I getting this problem? I'm trying it on an iOS 13 device. But I can't run the application in the background. I added a background run feature in Info.plist. I want to run the interator.tickTimer function in the background. But I'm getting an error. Does not work in the background. In the background, I want to periodically retrieve data from firebase.
import BackgroundTasks
#available(iOS 13.0, *)
extension AppDelegate {
func cancelAllPandingBGTask() {
BGTaskScheduler.shared.cancelAllTaskRequests()
}
func scheduleImageFetcher() {
let request = BGProcessingTaskRequest(identifier: "....")
request.requiresNetworkConnectivity = true // Need to true if your task need to network process. Defaults to false.
request.requiresExternalPower = false
request.earliestBeginDate = Date(timeIntervalSinceNow: 40)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule image featch: \(error)")
}
}
func handleAppRefreshTask(task: BGAppRefreshTask) {
task.expirationHandler = {
}
DispatchQueue.main.async {
let interator = MainTableViewController()
interator.tickTimer()
}
task.setTaskCompleted(success: true)
}
func handleImageFetcherTask(task: BGProcessingTask) {
scheduleImageFetcher() // Recall
//Todo Work
task.expirationHandler = {
}
task.setTaskCompleted(success: true)
}
}
xtension AppDelegate {
func registerLocalNotification() {
let notificationCenter = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
notificationCenter.requestAuthorization(options: options) {
(didAllow, error) in
if !didAllow {
// print("User has declined notifications")
}
}
}
func scheduleLocalNotification() {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.getNotificationSettings { (settings) in
if settings.authorizationStatus == .authorized {
self.fireNotification()
}
}
}
func fireNotification() {
// Create Notification Content
let notificationContent = UNMutableNotificationContent()
// Configure Notification Content
notificationContent.title = "Bg"
notificationContent.body = "BG Notifications."
// Add Trigger
let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 1.0, repeats: false)
// Create Notification Request
let notificationRequest = UNNotificationRequest(identifier: "local_notification", content: notificationContent, trigger: notificationTrigger)
// Add Request to User Notification Center
UNUserNotificationCenter.current().add(notificationRequest) { (error) in
if let error = error {
print("Unable to Add Notification Request (\(error), \(error.localizedDescription))")
}
}
}
}
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
registerBackgroundTaks()
registerLocalNotification()
} else {
// Fallback on earlier versions
}
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
cancelAllPandingBGTask()
scheduleImageFetcher()
} else {
// Fallback on earlier versions
}
}
//MARK: Regiater BackGround Tasks
#available(iOS 13.0, *)
private func registerBackgroundTaks() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "....-...", using: nil) { task in
//This task is cast with processing request (BGProcessingTask)
self.scheduleLocalNotification()
self.handleImageFetcherTask(task: task as! BGProcessingTask)
}
}