In your app delegate
import UserNotifications
class AppDelegate: ... UNUserNotificationCenterDelegate {
If you:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
print("notification tapped to open app ....")
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("notification arrived while app in foreground!")
completionHandler(.alert)
}
When you
and indeed the
then
and
and you will see 'notification tapped to open app ...' on the console.
But in those functions,
how the heck do you get the actual push PAYLOAD?
(That is to say the .data
value ...... or indeed any part of the payload. For example, if you're using the excellent github.com/AndrewBarba/apns2 you'd want precisely where it has the example data: {
... )
How the heck do you get the notification (payload) in the UserNotifications
delegate functions?!
Again this is when the user ***has actually opened the app, simply by tapping (ie, "slide, open") on a notification.
I am NOT discussing the difficult issue of waking an app in background (say, to download a file etc).
How the heck do you get the payload?
For 2024 we've found the best library to use for APNS is
https://github.com/parse-community/node-apn
It works. There's no support, nobody answers on the github issues, but it works fine.
Be aware that the older https://github.com/node-apn/node-apn is completely broken, (doesn't work at all) and is abandoned, but nobody bothered clicking delete. Every bit of documentation, functionality, syntax etc is identical on the new "@parse" one, there is nothing to do to swap over. If you used the old one which is now broken it's just
] npm uninstall apn
] npm install @parse/node-apn
and you're done.
Some random sample code ..
var apn = require('@parse/node-apn')
...
async function sendNotifsSilent() { // silent bg type
for (const aBase64Token of global.known_apns_tokens) {
console.log(`try SILENT APN for ${aBase64Token}`)
var note = new apn.Notification()
const hours = 8
note.expiry = Math.floor(Date.now() / 1000) + (hours * 60 * 60)
//note.payload = { 'examplePayloadItem': 'some payload itemn value' }
note.pushType = 'background'
note.contentAvailable = 1
note.topic = "you.com.yourapp"
const aTokenData = Buffer.from(aBase64Token, 'base64').toString('hex')
apnProvider.send(note, aTokenData).then((result) => {
console.log("result apn")
console.log(result)
console.log(result.failed)
console.log(result.failed.response)
})
apnProvider_sandbox.send(note, aTokenData).then((result) => {
console.log("result apn sandbox")
console.log(result)
console.log(result.failed)
console.log(result.failed.response)
})
}
}
...
async function sendNotifs() { // normal push notification
for (const aBase64Token of global.known_apns_tokens) {
var note = new apn.Notification()
const hours = 8
note.expiry = Math.floor(Date.now() / 1000) + (hours * 60 * 60)
// note.badge = 3
note.sound = "ping.aiff"
note.alert = {
title: "Some News", body: "Something happened."
}
// or just note.alert = "string"
note.payload = { 'examplePayloadItem': 'some payload item value' }
note.topic = "you.com.yourapp"
const aTokenData = Buffer.from(aBase64Token, 'base64').toString('hex')
apnProvider.send(note, aTokenData).then((result) => {
console.log("result apn")
console.log(result)
console.log(result.failed)
console.log(result.failed.response)
})
apnProvider_sandbox.send(note, aTokenData).then((result) => {
console.log("result apn sandbox")
console.log(result)
console.log(result.failed)
console.log(result.failed.response)
})
}
}
setup
const p8key = `-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkw666666666666666666666666
H2auA793mqBtW6EnOHyYdzssduKgCgYIKoZIzj0D666666666666666666666666
ZTY3g/tduKhcWUvVTvAQyItLaKqHmE5bMmDjhQ7t666666666666666666666666
ExQwdo3d
-----END PRIVATE KEY-----`
var apn_options = {
token: {
key: p8key,
keyId: "PL7aKVBLAH",
teamId: "EGW16TBLAH"
},
production: true
}
var apn_options_sandbox = {
token: {
key: p8key,
keyId: "PL7aKVBLAH",
teamId: "EGW16TBLAH"
},
production: false
}
var apnProvider = new apn.Provider(apn_options)
var apnProvider_sandbox = new apn.Provider(apn_options_sandbox)
Older option ...
Answer kindly provided by the crew at npm-apns2
(Library currently has a bug .. setting .topic is broken!)
For data like
let bn = new BasicNotification(deviceToken, 'Teste', {
data: {
name: 'jack',
street: 'jones'
} })
so ...
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler:
@escaping () -> Void) {
print("notification tapped, app opens")
let userInfo = response.notification.request.content.userInfo
let name: String? = userInfo["name"] as! String?
let street: String? = userInfo["street"] as! String?
let test3: String? = userInfo["typo"] as! String?
print("> \(name)") // optional 'jack'
print("> \(street)") // optional 'jones'
print("> \(test3)") // nil
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("notification arrived while app in foreground (user has
not 'tapped on notification' - you get this immediately)")
let userInfo = notification.request.content.userInfo // sic
let name: String? = userInfo["name"] as! String?
let street: String? = userInfo["street"] as! String?
let test3: String? = userInfo["typo"] as! String?
print("> \(name)") // optional 'jack'
print("> \(street)") // optional 'main'
print("> \(test3)") // nil
completionHandler(.alert)
}
and that's it.