Monday, September 18, 2023
HomeiOS Developmentios - Why is my background activity used to ship notification primarily...

ios – Why is my background activity used to ship notification primarily based on end result of a community name not firing in any respect?


I’m making an attempt to create a background activity to ship varied notifications at varied factors within the day, and every of them require a community to test if the notification needs to be despatched. I’ve examined the API, and I do know it really works. However when I attempt to add my app to my cellphone, nothing occurs (I do know as a result of my API logs by no means present any requests, and I by no means get notifications after I ought to). I adopted this video and browse this documentation, however for some purpose, the duty by no means appears to schedule/fireplace.

Right here is the associated code:

Community name:

func checkValue(worth: String, hours: Int) async -> Bool {
        // Construct url
        var urlString = MY_URL + "/Notification"
        urlString += "?worth="+worth+"&hours="+String(hours)
        
        guard let url = URL(string: urlString) else {
            print("Error: One thing mistaken with url.")
            return false
        }

        // construct full request
        let urlRequest: URLRequest = {
            var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
            request.allHTTPHeaderFields = [
                "Token": API_KEY
            ]
            return request
        }()
        
        // make request
        let config = URLSessionConfiguration.background(withIdentifier: SHOULD_SEND)
        config.sessionSendsLaunchEvents = true
        
        let session = URLSession(configuration: config)
//            let (information, response) = attempt await session.information(for: urlRequest)
        let (information, response) = await withTaskCancellationHandler {
            attempt! await session.information(for: urlRequest)
        } onCancel: {
            let activity = session.downloadTask(with: urlRequest)
            activity.resume()
        }
    
        // guarantee success
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
            // deal with if not 200
            print("Notification response not 200")
            return false
        }

        //assign worth
        return attempt! JSONDecoder().decode(Bool.self, from: information)
    
    }

Background Job associated code:

struct NotificationConfig: Equatable {
    var id: String
    var sort: NotificationType // only a string
    var instances: [Int]
    var hours: Int
    var title: String
    var physique: String
}

var notifications: [NotificationConfig] = [ // desired notifications ]

var physique: some Scene {
    WindowGroup {
        LandingView()
    }.backgroundTask(.appRefresh(SCHEDULE_DAILY_NOTIFICATIONS)) {
        let nextHour = scheduleAppRefresh()
        if nextHour != -1 {
            let instances = buildMap()
            
            for notif in instances[nextHour] ?? [] {
                let test = makeCheck(notification: notif)
                if await test() {
                    self.sendNotification(notif: notif)
                }
                
            }
        }
    } .backgroundTask(.appRefresh("shouldSend")) {
        let nextHour = scheduleAppRefresh()
        if nextHour != -1 {
            let instances = buildMap()
            
            for notif in instances[nextHour] ?? [] {
                let test = makeCheck(notification: notif)
                if await test() {
                    self.sendNotification(notif: notif)
                }
                
            }
        }
    }
}

func scheduleAppRefresh() -> Int {
    let nextHour = getNextNotifIndex()
    if nextHour == -1 {
        print("OOPS")
    }
    
    let calendar = Calendar.present
    let timeZone = TimeZone.present
    
    var dateComponents = calendar.dateComponents(in: timeZone, from: Date())
    dateComponents.hour = nextHour
    dateComponents.minute = 0
    dateComponents.second = 0
    
    guard var desiredTime = calendar.date(from: dateComponents) else {
        return -1
    }

    // if not in future, add a day
    if desiredTime.examine(Date()) == .orderedAscending {
        desiredTime = calendar.date(byAdding: .day, worth: 1, to: desiredTime)!
    }
    
    let request = BGAppRefreshTaskRequest(identifier: SCHEDULE_DAILY_NOTIFICATIONS)
    request.earliestBeginDate = calendar.date(byAdding: .minute, worth: -1, to: desiredTime)!
            
    do {
        attempt BGTaskScheduler.shared.submit(request)
    } catch {
        print("Couldn't schedule app refresh: (error)")
    }
    
    return nextHour
}

func buildMap() -> [Int: [NotificationConfig]] {
    var instances = [Int: [NotificationConfig]]()
    
    for notif in self.notifications {
        for time in notif.instances {
            if instances[time] != nil {
                instances[time]!.append(notif)
            } else {
                instances[time] = [notif]
            }
        }
    }
    
    return instances
}
    
func getNextNotifIndex() -> Int {
    let timers = buildMap()
    let now = Date()
    let calendar = Calendar.present
    let timeZone = TimeZone.present
    
    for hour in timers.keys.sorted() {
        var dateComponents = calendar.dateComponents(in: timeZone, from: now)
        dateComponents.hour = hour
        guard let thisTime = calendar.date(from: dateComponents) else {
            proceed
        }
        
        if thisTime.examine(now) == .orderedSame || thisTime.examine(now) == .orderedDescending {
            return hour
        }
    }
    
    return -1
}
    
func makeCheck(notification: NotificationConfig) -> () async -> Bool {
    return {
        return checkValue(worth: notification.sort, hours: notification.hours, meal: meal)
    }
}
        
// Operate to ship a notification for a selected hour
func sendNotification(notif: NotificationConfig) {
    UNUserNotificationCenter.present().requestAuthorization(choices: [.alert, .sound, .badge]) { granted, error in
        if granted {
            print("Notification authorization granted")
            let content material = UNMutableNotificationContent()
            content material.title = notif.title
            content material.physique = notif.physique
            content material.sound = UNNotificationSound.default
            
            let set off = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
            
            let identifier = "notification_(notif.instances[0])_(notif.id)"
            let request = UNNotificationRequest(identifier: identifier, content material: content material, set off: set off)
            
            UNUserNotificationCenter.present().add(request) { error in
                if let error = error {
                    print("Error scheduling notification for hour: (error)")
                } else {
                    print("Notification scheduled efficiently")
                }
            }
        }
    }
}

Sorry for the code dump, however I don’t know why it is not working. I adopted the steps within the documentation, and arrange my app settings (together with the Permitted background activity scheduler identifiers in Information.plist), nevertheless it by no means even reaches the within of the .backgroundTask Scene Modifier (utilizing debugger with breakpoints, by no means cease wherever within the background activity perform. A variety of the opposite helper capabilities have been examined and will work, however I included them simply in case. What might be inflicting this to occur, and what are steps I may take to debug background duties? That is my first time utilizing them, and all assist can be appreciated.

Are there any additional steps to arrange background duties than the developer docs that should be taken? Maybe on the machine, not in XCode on the undertaking?



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments