LiveCode LessonsLiveCode LessonsHow To - LiveCode Mobile Tasks iOS TasksHow to send HTTP/2 based Push Notifications in iOS

How to send HTTP/2 based Push Notifications in iOS

Apple supports push notifications based on the HTTP/2 network protocol. In fact, the legacy binary protocol on which the previous LiveCode lesson was based, will no longer be supported, as of April 2021.

In this lesson, we will show how to send http/2 push notifications to an iOS app, using token authentication.

This lesson is structured into the following 5 logical sections:

1. Creating an App ID in your developer account and enabling the push notification entitlement.

2. Generating the signing key

3. Creating the Push Notification Provisioning Profile

4. Writing a LiveCode Application with Push Notification Support

5. Sending a Push Notification

1. Creating an App ID in your developer account and enabling the push notification entitlement.

Visit https://developer.apple.com/account and then go to Certificates, Identifiers & Profiles. Click on Identifiers and press the + icon to create a new identifier:

Choose App IDs and press Continue.

Choose App and press Continue.

Provide a Description and a Bundle ID. Ensure the Bundle ID does not contain an asterisk (*). Scroll down, and in the Capabilties section, enable Push Notifications, and click Continue.

Now click Register.

The new app ID is now register. Now go back to the list of all app IDs, you should see the ID you just created:

2. Generating the signing key

Now go to the Keys section at the left pane:

Choose Create a key:

Provide a Key Name, enable Apple Push Notifications service (APNs), and click Continue

Then click Register

and then click Download

Store your key in a safe place. Make sure you write down your Key ID as well.

The key is a .p8 file, and its name should be something like AuthKey_<Key_ID>.p8

3. Creating the Push Notification Provisioning Profile

Each application that supports Push Notifications requires its own Provisioning Profile. The following steps lead you through the process of creating the Provisioning Profile for your application.

Log into your Apple Dev account and select Profiles on the left hand navigation panel. Click on the + button:

Choose iOS App Development and click Continue

In the App ID dropdown, choose the App ID you created in section 1 of this lesson, and click Continue.

In the next screen, choose the certificate(s) that you want to include in this provisioning profile, and click Continue.

In the next screen, choose the test devices on which the Provisioning Profile should operate, and click Continue.

Then provide a Provisioning Profile Name and click Generate.

In the next screen, click on Download

Then, double click on the downloaded profile to open it with Xcode. This will ensure that the profile will be selectable from within LiveCode.

4. Writing a LiveCode Application with Push Notification Support

Now that you have completed all of the work that is needed to support Push Notifications in LiveCode, it is time to implement code that acts upon a notification. Push Notifications are delivered by LiveCode in form of a message. Add the following or similar code to the stack script of your application:

on pushNotificationReceived pMessage
	  answer "Push Notification Message:" && quote & pMessage & quote with "Okay"
end pushNotificationReceived

Note: Look this message up in the dictionary and follow links to related dictionary entries.

Starting the application

The first time you start your Push Notification enabled LiveCode application you should get a message that is similar to the one shown here. The message only ever appears the first time the application is launched and does not appear again. This indicates that the iOS device is aware that the application can received Push Notifications and sets up the necessary parameters to allow notifications to be delivered to the application.

Getting the device identifier

The Device Identifier can be retrieved using the following LiveCode function:

mobileGetDeviceToken
answer the result with "Okay"

The Device Identifier is submitted to the server when registering for Push Notifications and provides the means by which the iOS device is identified when the notification is sent from the server.

Note: You don't get a deviceToken until after you get a Registered message. You can check this with the pushNotificationRegistered function

 

on pushNotificationRegistered pToken
   put ptoken into fld 1
end pushNotificationRegistered

5. Sending a Push Notification

Push Notifications are normally sent from a server, but we can simulate this action from a terminal. You can use the following code example as a template. Update the the first 6 lines with your own details and save it to a .sh file. In this example we are calling the file: send.sh

TEAM_ID=CDI79NSGHP
TOKEN_KEY_FILE_NAME=/Users/panos/Documents/PushNotificationAppAssets/NEW/AuthKey_9S733W8972.p8
AUTH_KEY_ID=9S733W8972
TOPIC=com.livecode.pushNotificationAppHttp2
DEVICE_TOKEN=62dfb121dfaa34c014rra9b4ed2d8ebcda43ed0ca7fafa8b7f45c512d60cdd30
APNS_HOST_NAME=api.sandbox.push.apple.com

JWT_ISSUE_TIME=$(date +%s)
JWT_HEADER=$(printf '{ "alg": "ES256", "kid": "%s" }' "${AUTH_KEY_ID}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
JWT_CLAIMS=$(printf '{ "iss": "%s", "iat": %d }' "${TEAM_ID}" "${JWT_ISSUE_TIME}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
JWT_HEADER_CLAIMS="${JWT_HEADER}.${JWT_CLAIMS}"
JWT_SIGNED_HEADER_CLAIMS=$(printf "${JWT_HEADER_CLAIMS}" | openssl dgst -binary -sha256 -sign "${TOKEN_KEY_FILE_NAME}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
AUTHENTICATION_TOKEN="${JWT_HEADER}.${JWT_CLAIMS}.${JWT_SIGNED_HEADER_CLAIMS}"

curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: alert" --header "authorization: bearer $AUTHENTICATION_TOKEN" --data '{"aps":{"alert":"You have a new message"},"payload":"Hello from LiveCode"}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

From a terminal run your .sh file using this syntax (replace the file name with the name you created for the code):

sh /path/to/send.sh

panoss-MBP:~ panos$ sh /Users/panos/Documents/PushNotificationAppAssets/NEW/send.sh
*   Trying 17.188.166.29...
* TCP_NODELAY set
* Connected to api.sandbox.push.apple.com (17.188.166.29) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
*  start date: Apr 17 17:37:51 2019 GMT
*  expire date: May 16 17:37:51 2021 GMT
*  subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"
*  issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fdfa9002c00)
> POST /3/device/62dfb121dfaa34c01yhui9b4ed2d8ebcda4e140ca7fafa8b7f45c512d60cdd30 HTTP/2
> Host: api.sandbox.push.apple.com
> User-Agent: curl/7.54.0
> Accept: */*
> apns-topic: com.livecode.pushNotificationAppHttp2
> apns-push-type: alert
> authorization: bearer eyAiYWxnIjogIkVTMjU2hujgImtpZCI6ICI5Uzc5SjY4OTjhyiB9.eyAiaXNzIjogIktSNjQ5TlNHSFAiLCAiaWFoiuhgMTYxNTk4NzU5OSB9.MEUCICJ5C97K244rRLoLUyej1yPN4v1LU7BLuPeHe7dPzQeBAiEAtJsb5YNke93QVBxJCUY-5jsNJ60-bhooEjzw2_GZatY
> Content-Length: 74
> Content-Type: application/x-www-form-urlencoded
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200 
< apns-id: 96FCFEF1-93EF-1086-A5D3-22UHYGA9DFAA
< 
* Connection #0 to host api.sandbox.push.apple.com left intact
panoss-MBP:~ panos$ 

After successfully running the script, you should see a notification in your device, displaying the alert part of the json data that is sent.

Tapping on the notification will open the app, and the pushNotificationReceived message will be sent to the stack, with the payload part of the json data:

Sending Push Notifications using LiveCode

Here is a sample stack, which you can use to send push notifications. You just need to fill in the details for:

  • Team ID
  • Signing Key (P8 Certificate)
  • Private Key ID
  • Bundle Identifier
  • Device Token
  • APNs Hostname

Then fill in the actual data you want to send, and click on the Send button:

Note: There are several third party apps you can use to send push notifications, for example the PushNotifications utility.

 

Also, in a production environment, you should use

APNS_HOST_NAME=api.push.apple.com

instead of

APNS_HOST_NAME=api.sandbox.push.apple.com

The signing key you have created in the Apple Developer portal will be the same for both development and production environment.

For each notification, you provide a payload with app-specific information and details about how to deliver the notification to the user. The payload is a JSON dictionary object (as defined by RFC 4627) that you create on your server. The JSON dictionary object must contain an aps key. For more information, see here

Troubleshooting Common Issues

Here are a couple problems you might encounter:

No notifications arrive at the device: Make sure you have allowed the app to receive push notifications. You can check that in the Settings app. Also make sure you are connected to the Internet and the device clock is set to the correct date and time.

Some notifications arrive, but not all: If you’re sending many push notifications simultaneously but you receive only a few, this is expected. There is a queue of size 1, so if you send multiple notifications, the last notification is overridden.

Problem connecting to Push Notification Service: One possibility could be that there is a firewall blocking the ports used by APNs. Make sure you unblock these ports. Also, make sure the device is connected to the Internet, and the device clock is set to the correct date and time.

0 Comments

Add your comment

E-Mail me when someone replies to this comment