This article is an overview of how to set up Remote Push Notifications for your games on the iOS target platform, and is for those users with experience using GameMaker, as well as experience with web servers and API procedures (if you only need Local Push Notifications, see this).
NOTE: The Firebase extension can be used to easily implement push notifications on iOS. Refer to its documentation.
The method shown in this article is still applicable.
Overview
Of all the platforms that currently permit Push Notifications, iOS is probably the most complicated, so before getting started on the actual process of setting up the server and actually pushing out messages, let's have a look at exactly how things are supposed to work.

So, what's happening here? Let's go through the diagram with a bit more detail:
- Your game enables push notifications through iOS, and the user has to confirm that he wishes to receive these notifications. The os then contacts the Apple Push Notification Service (APNS for short) to request a device token.
- Your game will then receive this device token (You can think of the device token as the address that push notifications will be sent to).
- This token should then be sent from your game to your server to be stored.
- When something of interest to your game happens (for example, a specific date is reached), your server sends a push notification to the APNS.
- The APNS then sends on the push notification to the user’s device.
When the user’s device receives the push notification, it shows an alert, plays a sound and/or updates the games icon. The user can then launch the game from the alert if they choose, and the game is given the contents of the push notification and can handle it as it sees fit in the The Asynchronous Push Event (see below for more information).
Getting Started
This tutorial assumes that you have already had some experience with publishing to the iOS platform and have already acquired your Production (or Development) certificates. If this is not the case then please see the article on Getting Your Game Onto The App Store.
Once you have your certificates you need to create a new app in iTunes and get it's App ID (Certificates, Identifiers and Profiles > iOS Apps > Certificates > App IDs).
NOTE: You cannot use a wildcard ID, as each push app needs its own unique ID because push notifications are sent to a specific application only.
Fill out the relevant details for your game, making sure to select the "Push Notification" checkbox under the App Services section. Once you have your details filled out click the "Submit" button as normal and you should see a list of all the details for your game, with Push Notifications marked as "enabled".

You can now select your game from the list in iTunes and from there you will see the features that you have enabled, with Push Notifications showing a couple of yellow "Configurable" icons. You must now use the "Settings" button to take you to the page where you can setup these notifications. You will need to make a an Production SSL Certificate (or a Development one if that is the current profile certificate), so click on the button and follow the steps outlined in the “Add iOS Certificate” wizard this brings up.
Once finish, click "Download" to get the certificate (it is named “aps_development.cer”) and store it with the Certificate Signing Request and your *.p12 signing key (you can get the *.p12 signing key by clicking the arrow on your certificate in the keychain access app, and then exporting the key as a .p12 file).
You should now go ahead and create the provisioning profile for your game.
Making a PEM File
These files now need to be made into a single PEM (Privacy Enhanced Email) file, because the push part of our server in this example will be written in PHP and requires this file.
You’re going to use the command-line OpenSSL tools for this, so open a Terminal and execute the following steps:
1) Go to the folder where you downloaded the files, in my case the Desktop:
$ cd ~/Desktop/
2) Convert the .cer file into a .pem file:
$ openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
3) Convert the private key’s .p12 file into a .pem file:
$ openssl pkcs12 -nocerts -out PushChatKey.pem -in PushChatKey.p12 Enter Import Password: MAC verified OK Enter PEM pass phrase: Verifying - Enter PEM pass phrase:
You first need to enter the password for the .p12 file so that openssl can read it, and then you need to enter a new password that will be used to encrypt the PEM file.
NOTE: if you don’t enter a PEM password, openssl will not give an error message but the generated .pem file will not have the private key in it.
4.1) Finally, combine the certificate and key into a single .pem file:
$ cat PushChatCert.pem PushChatKey.pem > ck.pem
4.2) t this point it’s a good idea to test whether the certificate works. Execute the following command:
$ telnet gateway.sandbox.push.apple.com 2195 Trying 17.172.232.226... Connected to gateway.sandbox.push-apple.com.akadns.net. Escape character is '^]'.
This tries to make a regular, unencrypted, connection to the APNS server. If you see the above response, then your Mac can reach APNS. Press Ctrl+C to close the connection. If you get an error message, then make sure your firewall allows outgoing connections on port 2195.
Let’s try connecting again, this time using our SSL certificate and private key to set up a secure connection:
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem Enter pass phrase for PushChatKey.pem:
You should see a whole bunch of output, which is openssl letting you know what is going on under the hood.
If the connection is successful, you should be able to type a few characters. When you press enter, the server should disconnect. If there was a problem establishing the connection, openssl will give you an error message but you may have to scroll up through the output to find it.
NOTE: There are two different APNS servers: the “sandbox” server that you can use for testing, and the live server that you use in production mode. Above, we used the sandbox server but if you are using a production certificate then you should use the production server (gateway.push.apple.com:2195)
Server Implementation
In this example we are using PHP to push out our notification, but bare in mind that no matter what you do you will need to have your server store the unique "device token" that is generated by your game when it activates push notifications (see the section on the Asynchronous Push Notification Event, below).
This token, along with the PEM file and your password will be used to generate the notification, and you can see a simple example of how your final php would look here:
The actual JSON payload itself can contain multiple details, but it is split into three basic sections:
- Alert - At it's most basic, this is simply a message string that is displayed when the user touches the notification
- Badge - A number that is to be displayed on the badge icon (setting this to 0 will remove all numbers from the icon)
- Sound - This currently isn't supported and so should be set to "default" to trigger the default notification sound
You can find complete details of all permitted strings and sub strings for your JSON payload from the Apple docs here.
As mentioned above, when a notification is received by GameMaker, and the game is run, it will generate an Asynchronous Event (further details are given below) where the “data” key of the generated ds_map will be in the form of a JSON string.
Unlike other platforms, It’s not possible to test using a simple http client because the Apple service requires a socket connection and SSL certificate. For development of your game, you can use your PC as the server but for production use, you need at least something like a VPS (Virtual Private Server), as a cheap shared hosting account is just not good enough. You need to be able to run a background process on the server, install an SSL certificate, and be able to make outgoing TLS connections on certain ports.
Example
A very basic example of a payload for a simple push message looks like this:
{ "aps": { "alert": "Hello, world!", "sound": "default" } }
There are other items you can add to the “aps” section to configure the notification. For example:
{ "aps": { "alert": { "action-loc-key": "Open", "body": "Hello, world!" }, "badge": 2 } }
Now “alert” is a dictionary of its own. The “action-loc-key” provides an alternative text for the “View” button. The “badge” field contains the number that will be shown on the application icon.
GameMaker
There are no functions in GameMake to directly deal with remote notifications, as they must all be generated by your server and handled by the respective Service Providers. However, once set up correctly, GameMaker games will receive these notifications, which can then be dealt with in the Asynchronous Push Event, as you would a local notification.
NOTE: To test your game you must create a final executable and test on a device that is registered to your iTunes developer account.
For all available platforms (once you have done the necessary set-up) when the game is run on a device it will register that device with the platforms push notification service. This will trigger an Asynchronous Push Notification Event, and the ds_map key "type" will have the value "register" as well as a new key, "reg_id", containing the registration id for the user device.
You must then send this registration id to your server. Your server must maintain a list of ids for registered devices, as when when you send a push notification message from your server, you use these stored registration ids to send the message to the individual devices (every device that your game is installed on will have a unique registration id).
NOTE: There is no guarantee that remote push notifications will be delivered, and that the allowed data payload for each notification is fairly small.
The Asynchronous Push Event
The Push Notification Event is one that is triggered by the call back from push notifications. It generates a ds_map (more commonly known as a "dictionary") that is exclusive to this event and is stored in the special variable async_load. This ds_map has the following keys:
"type": Value can be "local" for a device local notification, "remote" for a remote notification, or "register" for remote notification registration.
"status": Value will be "1" for success or "0" for an error.
There may be additional key entries based on the "type" returned and the "status" value. For "status", if an error has been returned ("0"), then you will also have the following key:
"error": Contains details of the error received.
If the "status" value is 0 (ie: no errors) then the ds_map will contain the following additional values, depending on the value of the "type" key:
"reg_id": If the "type" received was "register", then this key will hold the device registration id for remote notifications.
"data": If the "type" received was "local" or "remote", then this key will hold the string payload that you defined when you called the notification function. This string is formatted using the JSON standard.
In the event itself you would handle the callback something like this:
var type = ds_map_find_value(async_load, "type");
var status = ds_map_find_value(async_load, "status");
if status == 0
{
//error of some kind
var error = ds_map_find_value(async_load, "error");
show_debug_message("error=" + string(error));
}
else
{
if type == "register"
{
var reg_id = ds_map_find_value(async_load, "reg_id");
//post reg_id to your server
}
else
{
var data = ds_map_find_value(async_load, "data");
//Decode the JSON data and perform any actions according to the contents
}
}