如何通过 API 使用后台任务?

Posted

技术标签:

【中文标题】如何通过 API 使用后台任务?【英文标题】:How to use background task with API? 【发布时间】:2020-01-21 06:24:46 【问题描述】:

我正在尝试使用后台任务访问 API,但收到以下错误消息:

无法结束 BackgroundTask:不存在标识符为 3 (0x3) 的后台任务,或者它可能已经结束。插入 UIApplicationEndBackgroundTaskError() 进行调试。

下面是我正在使用的代码。

我不知道我哪里错了。请帮帮我。

     

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 

        registerBackgroundTaks()
        registerLocalNotification()
        return true
    

    func applicationDidEnterBackground(_ application: UIApplication) 
        cancelAllPandingBGTask()
        scheduleAppRefresh()
        scheduleImageFetcher()

    

    //MARK: Regiater BackGround Tasks
    private func registerBackgroundTaks() 

        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.SO.imagefetcher", using: nil)  task in
            //This task is cast with processing request (BGProcessingTask)
            self.scheduleLocalNotification()
            self.handleImageFetcherTask(task: task as! BGProcessingTask)
        

        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.SO.apprefresh", using: nil)  task in
            //This task is cast with processing request (BGAppRefreshTask)
            self.scheduleLocalNotification2()
            self.handleAppRefreshTask(task: task as! BGAppRefreshTask)
        
    


    extension AppDelegate 

    func cancelAllPandingBGTask() 
        BGTaskScheduler.shared.cancelAllTaskRequests()
    

    func scheduleImageFetcher() 
        let request = BGProcessingTaskRequest(identifier: "com.SO.imagefetcher")
        request.requiresNetworkConnectivity = true // Need to true if your task need to network process. Defaults to false.
        request.requiresExternalPower = true

        request.earliestBeginDate = Date(timeIntervalSinceNow: 1 * 60 ) // Featch Image Count after 1 minute.
        //Note :: EarliestBeginDate should not be set to too far into the future.
        do 
            try BGTaskScheduler.shared.submit(request)
         catch 
            print("Could not schedule image featch: \(error)")
        
    

    func scheduleAppRefresh() 
        let request = BGAppRefreshTaskRequest(identifier: "com.SO.apprefresh")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // App Refresh after 2 minute.
        //Note :: EarliestBeginDate should not be set to too far into the future.
        do 
            try BGTaskScheduler.shared.submit(request)
         catch 
            print("Could not schedule app refresh: \(error)")
        
    

    func handleAppRefreshTask(task: BGAppRefreshTask) 
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1

        let op = BlockOperation 
            self.runApi2(task: task)
        

        task.expirationHandler = 
            //This Block call by System
            //Canle your all tak's & queues
            op.cancel()
        
        scheduleLocalNotification()
        queue.addOperation(op)
    

    func handleImageFetcherTask(task: BGProcessingTask) 
        scheduleImageFetcher() // Recall


        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1

        let op = BlockOperation 
            self.runApi(task: task)
        

        //Todo Work
        task.expirationHandler = 
            //This Block call by System
            //Canle your all tak's & queues
            op.cancel()
        

        queue.addOperation(op)

    

    func runApi(task: BGProcessingTask) 
        let url = URL(string: "http://www.***.com")!

        let task = URLSession.shared.dataTask(with: url) (data, response, error) in
            guard let data = data else  return 
            print(String(data: data, encoding: .utf8)!)
            task.setTaskCompleted(success: true)
        

        task.resume()
    

    func runApi2(task: BGAppRefreshTask) 
        let url = URL(string: "http://www.***.com")!

        let task = URLSession.shared.dataTask(with: url) (data, response, error) in
            guard let data = data else  return 
            print(String(data: data, encoding: .utf8)!)
            task.setTaskCompleted(success: true)
        

        task.resume()
    


    extension 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 scheduleLocalNotification2() 
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.getNotificationSettings  (settings) in
            if settings.authorizationStatus == .authorized 
                self.fireNotification2()
            
        
    

    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))")
            
        
    

    func fireNotification2() 
        // Create Notification Content
        let notificationContent = UNMutableNotificationContent()

        // Configure Notification Content
        notificationContent.title = "processs"
        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))")
            
        
    

【问题讨论】:

【参考方案1】:

您应该将任务调度程序标识符添加到 info.plist 文件。赞this

【讨论】:

以上是关于如何通过 API 使用后台任务?的主要内容,如果未能解决你的问题,请参考以下文章

如何确定我的后台任务将在生产中调用多少个 3rd 方 Web api 调用?

Windows phone 8.1 后台任务突然退出

在后台任务中使用多个工作人员 - Fast-API

用于在后台运行日常任务的 Android WorkManager api

.Net / Asp.Net Web api 后台任务

[译]图解Android应用的后台任务和提醒