Silent push not triggering the code execution

I'm sending silent push notification every 30 minutes, I want execute code when silent notification arrives to device. But after lot of tries, I can't get the result. When I testing it on my device (with version from Xcode) everything works, after uploading it to TestFlight and downloading the version from TestFlight I'm not able to wake the app from background or wake it from terminated state. Simply this code executes after launching an app or app goes to foreground.

According to Apple documentation I should be able to wake the app and execute the 30 seconds of a code. I verified that silent notification is successfully delivered. I have missing something?

AppDelegate.swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if let messageID = userInfo[gcmMessageIDKey] {
        print("Message ID: \(messageID)")
    }

    guard (userInfo["aps"] as? [String?: Any]) != nil else {
        Analytics.logEvent("fetch_failed", parameters: nil)
        completionHandler(.failed)
        return
    }

    let login = UserDefaults.standard.value(forKey: "username") as? String
    let password = UserDefaults.standard.value(forKey: "password") as? String

    if login != nil && password != nil {
        let session = URLSession.shared
        let url = URL(string: "https://example.com")!
        let body_values = Data(("credentials...").utf8)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", forHTTPHeaderField: "User-Agent")
        request.httpBody = body_values

        let loadDataTask = session.dataTask(with: request) { data, response, error in
            if let httpResponse = response as? HTTPURLResponse {
                print(httpResponse.statusCode)
                if httpResponse.statusCode == 200 {
                    if let data = data, let dataString = String(data: data, encoding: .utf8) {
                        let htmlparser: HTMLParser = HTMLParser()
                        let numberOfEmails = htmlparser.getXPathvalue(xPath: "/html/body/div[1]/div[3]/div[3]/a[1]", fromHtml: dataString)
                        self.setNotification(title: "New emails!", body: "Count of new emails: \(numberOfEmails)")
                        completionHandler(.newData)
                    }
                    else {
                        completionHandler(.failed)
                    }
                }
                else {
                    completionHandler(.failed)
                }
            }
            else {
                completionHandler(.failed)
            }
        }
        loadDataTask.resume()
    }
    else {
        completionHandler(.failed)
    }
}

PushNotification.js

var message = {
  notification: {
  },
  apns: {
     headers: {
        'apns-priority' : '5',
        'apns-push-type' : 'background'
     },
     payload: {
         aps: {
            'content-available' : 1
         }
     }
   },
   topic: topic
};

1 answer

  • answered 2020-03-28 10:13 Caio Gomes

    There are two main things you must pay attention to that are discussed in this apple forum discussion!. The first one is that the app can't be terminated, otherwise it won't launch the app, it must be foreground or background. And the other one is that you need to enable the background mode in Info.plist to make it work. Other than that there are situations when the system won't just refresh your app, the greatest guarantee you have is only if the user clicks a notification your app receives, otherwise for some privacy concerns it may not work.