Reputation: 147
I want to ask if it's even possible to send URL POST request from app when app receive silent push notification. If it is possible how can I get it?
My application successfully receiving silent push notifications and when I have my phone plugged in Xcode I'm able to execute url task (even in background) and get the desired results. After unplugging the phone from my Mac, the phone stops executing url tasks at all.
Regarding the apple documentation, when silent push notification appears, I have 30 seconds to execute the code
Your app has 30 seconds to perform any tasks and call the provided completion handler
My silent push notification:
{
notification: {},
apns: {
headers: {
"apns-priority" : '5',
"apns-push-type" : 'background'
},
payload: {
aps: {
"content-available" : 1,
}
}
},
topic: topic
};
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
}
self.emailFetch() // Here I call my function for sending POST request via URLSession
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
SOLVED
Currently I have updated dataTask to downloadTask and now I am able to successfully read the answer from the server from temporary file. It works properly when the app is running in background.
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
}
if login != nil && password != nil {
let session = URLSession.shared
let url = URL(string: "https://....")!
let body_values = Data(("data...").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
print("Starting load data")
let loadDataTask = session.downloadTask(with: request) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
if httpResponse.statusCode == 200 {
if let data = data {
if let dataString = try? String(contentsOf: data) {
This is being executed only in XCode
My logic is here...
completionHandler(.newData)
} else {
completionHandler(.failed)
}
}
else {
completionHandler(.failed)
}
}
else {
completionHandler(.failed)
}
}
else {
completionHandler(.failed)
}
}
loadDataTask.resume()
}
else {
completionHandler(.failed)
}
}
Upvotes: 1
Views: 1142
Reputation: 112
Hi Peter not sure if you ever figured this out but basically you have to use a .downloadTask instead of a .dataTask with your URLSession. That is likely why your current solution isn't working. The inclination may be to think "It's not a download task" but its just a matter of schematics. Think of download as the response from the server (e.g. 200 "Success"). You can still POST using this method.
Upvotes: 1