iOS Push Notifications: Part 2 — Sending notifications

Dmitrijs Beloborodovs
Citadele Bank Developers
4 min readMar 12, 2024
Photo by Jamie Street on Unsplash

There are several ways to test push notifications sending them using different techniques. Let’s start with simple one.

Drag and Drop

Sending push to local Simulator is possible with simple drag and drop. Just drag file with notification payload to simulator. First, we should add extra information to JSON which contains notification payload: provide app bundle identifier on same level as aps.

{
"Simulator Target Bundle": "me.dmi3j.push-notification-demo",
"aps": {
"alert": {
"title": "Lorem ipsum title",
"body": "Lorem ipsum body",
}
}
}

This file is in JSON format, but must have *.apns file extension.

xcrun

Sending same file is also possible with xcrun command from Terminal.

xcrun simctl push <SIMULATOR_DEVICE_ID> <YOUR_APP_BUNDLE_ID> <APNS_FILE_NAME>

To send to currently active Simulator with your app running, use

xcrun simctl push booted push.apns

If more than one are currently active — push comes to last booted or none (still can’t figure out why). If you decide to set up some kind of automated testing, probably worth specify Simulator device ID explicitly (use xcrun simctl list to get list with all of them.

So far we only “simulated” push. Without send any real one via Apple’s servers. Simulation is good for testing purposes, but does not reflect real life setup (i.e. push will reach app even before user allowed pushes, 🤷‍♂️)

curl

The “proper” and the only way to send real push notification is via Apple’s push notification server (all the rest — apps, console or third party services like Firebase — are just next level of abstraction and use APNs). To do that we need two things: push notification key configured in Developer portal (or key extracted from certificate configured in Developer portal) and device ID (aka “push notification token”).

This approach will also work with sending notification to Simulator (not only real device), at lest with M1 Mac. The interesting thing is push notification token hash for Simulator is 160 symbols long when one from real device is 64, 🤷‍♂️.

There are two environments in APNs: developers and production. In our example we connect to api.development.push.apple.com (use api.push.apple.com for production). Assuming key in a *.p8 file format is in same folder with script.

#!/bin/bash
# to execute it first chmod +x <script_name>.sh
deviceToken="xxx"
authKey="./AuthKey.p8"
authKeyId="xxx"
teamId="xxx"
bundleId="me.dmi3j.push-notification-demo"
endpoint=https://api.development.push.apple.com
read -r -d '' payload <<-'EOF'
{
"Simulator Target Bundle": "me.dmi3j.push-notification-demo",
"aps": {
"alert": {
"title": "Lorem ipsum title",
"body": "Lorem ipsum body",
}
}
}
EOF
# --------------------------------------------------------------------------base64() {
openssl base64 -e -A | tr -- '+/' '-_' | tr -d =
}
sign() {
printf "$1"| openssl dgst -binary -sha256 -sign "$authKey" | base64
}
time=$(date +%s)
header=$(printf '{ "alg": "ES256", "kid": "%s" }' "$authKeyId" | base64)
claims=$(printf '{ "iss": "%s", "iat": %d }' "$teamId" "$time" | base64)
jwt="$header.$claims.$(sign $header.$claims)"
curl --verbose \
--header "content-type: application/json" \
--header "authorization: bearer $jwt" \
--header "apns-topic: $bundleId" \
--data "$payload" \
$endpoint/3/device/$deviceToken
  • deviceToken is push notification token;
  • authKey is a path to *.p8 file with key;
  • authKeyId is a key identifier you see when generate one in Developer portal;
  • teamId is your development team identifier (see on portal);
  • bundleId your app bundle identifier.

The rest seems too obvious to comment. Ask me in comments for help if needed.

Apps

There are a lot of third party apps providing same functionality as shell script above but with more friendly UI. Apps were real help when they only way to send push was using certificate. It was a nightmare to do all the encryptions.

https://github.com/andela/pushtool

Push Notification Console

In 2023 Apple introduced a new tool available for developers — Push Notification Console. It’s a long awaited feature. With console it is possible not only send push to development and production environments, but also get back status of push.

It gives you configurable view for push payload and also JSON view.

For the every sent push there is informative log.

Conclusion

There are all know to me at the moment way to sent push notification. I think you can choose the best for your needs.

All the source code and scripts are available in this repo.

References

--

--