How do I use Push Notifications with iOS?

UPDATE: This lesson will be deprecated as of April 2021, since it uses the legacy binary API for push notifications.

See the new lesson on how to send HTTP/2 based push notifications here

You can download the sample stack from this url: https://tinyurl.com/y978y46k

Introduction

Push Notifications allow you to send notifications from a server directly to an iOS device. This reduces network bandwidth for applications that may normally poll a server at intervals, in order to receive an update on information the user may be waiting for.

Although Push Notifications are convenient and reduce network traffic, they are not supported by every service, both on the server side and the application side.

In order to set up Push Notifications, it is necessary that the devices register with the server. The server needs information on what device the notification is to be sent to. The device also needs to be able to receive the notification and act upon it. This communication between the server and the device is encrypted and requires appropriate keys and certificates to be created.

This lesson is accompanied by a sample stack written by John Craig and uses the Json library by Mark Smith. The stack provides support for the certificate generation process and allows you to send Push Notifications from LiveCode. A demonstration on how to use the stack is provided by the author under the following YouTube link: http://www.youtube.com/watch?v=v7nR_aEAdKA.

Note: Button Send Notification PWD and the Password field were added to the original sample stack to allow integration into the original lesson. This additional functionality allows you to supply a Passphrase for the Private Key when sending a notification to the server.

This lesson is structured into the following six logical sections:

1. Generating the Certificates

2. Testing the Certificates

3. Creating the Push Notification Provisioning Profile

4. Writing a LiveCode Application with Push Notification Support

5. Sending a Push Notification

6. Trouble Shooting

Generating the Certificates

Push Notifications occur over encrypted communication and involve a sequence of handshakes between the Push Notification Server and the iOS device. The handshakes take place very much in the background when using the LiveCode syntax, but you have to create the certificates and keys that are used for the encrypted communication. The certificate and key generation process follows standard steps via Keychain Access and the Apple Provisioning Portal. More information on this process is available in the reference material of the Apple Provisioning Portal.

Creating a Certificate Signing Request

Creating a Certificate Signing Request

The first step is to create a Certificate Signing Request. Open the Keychain Access application on your Mac. This should be accessible under Applications/Utilities. Then select KeychainAccess -> Certificate Assistant -> Request a Certificate From a Certificate Authority... . This should launch the Certificate Assistant as is shown in this step.

Fill in your e-mail address and the common name you are using for the application that is to support Push Notifications.

Note: Each new application that supports Push Notifications needs its own Certificate Signing Request.

Once you have entered your e-mail address and the common name of the application, select the Save to disk radio button. Then select Continue. This allows you to save the Certificate Signing Request to your file system. In this example the certificate was saved as: PushNotificationApp.certSigningRequest

Note: Save the Certificate Signing Request into a common location for files that are specific to the application that is to support Push Notifications. Throughout this lesson, further certificates and keys are added to the same location, in this case the PushNotificationAppAssets folder.

Saving the Private Key

Saving the Private Key

Once you have created the Certificate Signing Request for the Push Notification application, you can save the Private Key to your file system. Remain in the Keychain Access application and open the Keychain Access interface. Select login from the Keychains panel and Keys from the Category panel. The list window should now display the Keychain Keys. You should find a private key with the common name you provided when you created the Certificate Signing Request. Right click on the certificate and select Export "the common name". In this example the private key was saved as PushNotificationApp.p12. Make sure you save this in the same folder where you saved the file PushNotificationApp.certSigningRequest. Also you need to enter a passphrase that protects the private key.

Creating the Application ID

Creating the Application ID

Log into the iOS Provisioning portal and select Identifiers from the left panel. This should provide you with a window that is similar to the one shown in this step. Then click on the + button to create a new app identifier:

 

Choose App IDs and click on Continue button:

 

 

Enter the Description for the application that is to support Push Notifications. Then choose Explicit in the Bundle ID field and enter a bundle identifier. This is usually written as the reverse of a domain name with the application name post fixed. This may be your domain name and your application name. In this example, we are using the name: com.livecode.pushNotificationApp. Then scroll down and check "Push Notifications", and then click Continue.

 

You should see this screen:

 

Click Register.

The Application ID

The Application ID

After clicking on Register, the Bundle ID you just added is included in the list of the Identifiers. Click on com.livecode.pushNotificationApp to edit it:

 

Scroll down, find Push Notifications and click on Configure:

This dialog should appear:

Ensuring Push Notification is Supported

Then select the kind of Push SSL Certificate you would like to create. In this lesson we are using the Development SSL Certificate for demonstration purposes. A final production application should use the Production SSL Certificate. Then you should see this screen:

Certificate Signing Request Reminder

In the Upload a Certificate Signing Request field, choose the file PushNotificationApp.certSigningRequest we created in the beginning of this lesson (which is saved in the PushNotificationAppAssets folder). Then click on Continue:

The certificate is now created. Click on the Download button, to download the certificate to your file system. The certificate name should look something like: aps_development.cer.  Again, make sure you save this in the same folder where we have saved all the necessary files so far, that is PushNotificationAppAssets in this lesson. Once the certificate is saved, double click on it. This will add it to your Keychain.

Testing the Certificates

Now that you have created your certificates, you should test if they work. This step does not yet require you to implement a LiveCode application and can be executed from your Mac Terminal.

In order to run the test you first have to create a PEM file that contains both, the Apple Push Notification Service SSL Certificate and your Private Key. Once this PEM file is created, you can test whether or not the certificates work.

Creating your PEM file

In order to use the certificates you generated, you need to create a PEM file that stores both, your Apple Push Notification Service SSL Certificate and your Private Key. You can create the PEM file from a terminal.

Navigate to the directory that contains the certificates and key you generated earlier:

Then execute the following steps. The file names here reflect the names of the certificates that were generated as part of this lesson. You have to update the syntax according the names you gave your certificates.

First create the application certificate PEM file. You can do this by double clicking on the aps_development.cer certificate file, then opening the Keychain Assistant and exporting the certificate as a p12 file and then converting it to a PEM file, in the same fashion as the PushNotificationApp.p12 is converted to a PEM file. Alternatively you can use a single command line that converts the aps_development.cer certificate file directly to a PEM file. Here we are opting for the single command line option,  as follows:

 

openssl x509 -inform der -outform pem -in aps_development.cer -out PushNotificationAppCertificate.pem

Verify the file PushNotificationAppCertificate.pem is created in the folder PushNotificationAppAssets:

Now create the application key PEM file as follows. You need to enter the import password and PEM pass phrase:

 

openssl pkcs12 -in PushNotificationApp.p12 -out PushNotificationAppKey.pem -nocerts      

Enter Import Password:

MAC verified OK

Enter PEM pass phrase:

Verifying - Enter PEM pass phrase:

Now concatenate the two files:

cat PushNotificationAppCertificate.pem PushNotificationAppKey.pem > PushNotificationAppCertificateKey.pem

This should create a new file named PushNotificationAppCertificateKey.pem in the same folder:

Talking to the Push Notification Server

Open a Mac terminal and execute the following line from the directory that contains the certificates you generated:

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushNotificationAppCertificate.pem -key PushNotificationAppKey.pem

You are then asked to enter the pass phrase for the key you submitted:

Enter pass phrase for PushNotificationAppKey.pem:

If everything worked, then the server should send you a lot of information that may look something like the following:

CONNECTED(00000003)

depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

verify error:num=20:unable to get local issuer certificate

verify return:0

...

Key-Arg \  : None

Start Time: 1326899631

Timeout   : 300 (sec)

Verify return code: 0 (ok)

At the end of this, you can enter some text and then select the return key. We entered the text "Hello World".

Hello World

closed

 

This completes the communication with the server and verifies that our certificates work.

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.

Development Provisioning Profiles

Development Provisioning Profiles

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

 

Choose Development, and then iOS App Development and click Continue.

 

Creating a new Development Provisioning Profile

Creating a new Development Provisioning Profile

In the App ID dropdown, choose pushNotificationApp and click Continue:

In the next screen, tick all the certificates that you want to include in this provisioning profile. Make sure they are Development certificates, as this will be a Development provisioning profile. Then click Continue.

 

Then select the test devices on which the Provisioning Profile should operate. Once you have provided all of the required information, click Continue.

The new Push Notification Provisioning Profile

The new Push Notification Provisioning Profile

Finally, choose a name for this profile, and click Generate:

The new Development provisioning profile is now ready. Click on Download, and make sure you save it in the same folder (PushNotificationAppAssets). In this example, the profile is called: Panos_PushNotificationApp.mobileprovision. Double click on the profile, once it is downloaded, this makes it available for you to use.

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 card 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 your Application

Starting your 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.

Disallowing Push Notifications

Disallowing Push Notifications

If the user switched off Push Notifications for the application, then a dialog is displayed when the application starts up. This indicates that Push Notifications have been disabled.

Configuring Push Notification Settings

Configuring Push Notification Settings

The user can configure the Push Notification Settings by selecting: Settings -> Notifications from their iOS device. This allows them to toggle supported features.

Accessing 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.

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

 

on pushNotificationRegistered pToken
   answer "Registered for Push Notification:" && quote \
         & pToken & quote with "Okay"
end pushNotificationRegistered
Click to copy

 

 

Sending a Push Notification (PHP)

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 highlighted code section with code that is specific to your requirements and save it to a .php file. In this example we are calling the file: PushNotifications.php

<?php
// Provide the Host Information.
$tHost = 'gateway.sandbox.push.apple.com';
$tPort = 2195;
// Provide the Certificate and Key Data.
$tCert = 'PushNotificationAppCertificateKey.pem';
// Provide the Private Key Passphrase (alternatively you can keep this secrete 
// and enter the key manually on the terminal -> remove relevant line from code).
// Replace XXXXX with your Passphrase
$tPassphrase = 'XXXXX';
// Provide the Device Identifier (Ensure that the Identifier does not have spaces in it).
// Replace this token with the token of the iOS device that is to receive the notification.
$tToken = 'b3d7a96d5bfc73f96d5bfc73f96d5bfc73f7a06c3b0101296d5bfc73f38311b4';
// The message that is to appear on the dialog.
$tAlert = 'You have a LiveCode APNS Message';
// The Badge Number for the Application Icon (integer >=0).
$tBadge = 8;
// Audible Notification Option.
$tSound = 'default';
// The content that is returned by the LiveCode "pushNotificationReceived" message.
$tPayload = 'APNS Message Handled by LiveCode';
// Create the message content that is to be sent to the device.
$tBody['aps'] = array (
	'alert' => $tAlert,
	'badge' => $tBadge,
	'sound' => $tSound,
	);
$tBody ['payload'] = $tPayload;
// Encode the body to JSON.
$tBody = json_encode ($tBody);
// Create the Socket Stream.
$tContext = stream_context_create ();
stream_context_set_option ($tContext, 'ssl', 'local_cert', $tCert);
// Remove this line if you would like to enter the Private Key Passphrase manually.
stream_context_set_option ($tContext, 'ssl', 'passphrase', $tPassphrase);
// Open the Connection to the APNS Server.
$tSocket = stream_socket_client ('ssl://'.$tHost.':'.$tPort, $error, $errstr, 30, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $tContext);
// Check if we were able to open a socket.
if (!$tSocket)
	exit ("APNS Connection Failed: $error $errstr" . PHP_EOL);
// Build the Binary Notification.
$tMsg = chr (0) . chr (0) . chr (32) . pack ('H*', $tToken) .  pack ('n', strlen ($tBody)) . $tBody;
// Send the Notification to the Server.
$tResult = fwrite ($tSocket, $tMsg, strlen ($tMsg));
if ($tResult)
	echo 'Delivered Message to APNS' . PHP_EOL;
else
	echo 'Could not Deliver Message to APNS' . PHP_EOL;
// Close the Connection to the Server.
fclose ($tSocket);
?> 

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

php PushNotificatiopns.php

Sending a Push Notification (LiveCode)

You can send a Push Notification from LiveCode using the sample stack that John Craig provided. We are listing a modified version of his server call code here to provide a comparative algorithm to the PHP code that is shown in the previous step. You can use the following code with LiveCode 8.x and 9.x:

on mouseup
   # Provide the Host Information.
   local tHost = "gateway.sandbox.push.apple.com"
   local tPort = 2195
   # Provide the Certificate and Key Data.
   local tCert = "PushNotificationAppCertificateKey.pem"
   # Provide the Private Key Passphrase (alternatively you can keep this secrete and 
   # enter the key manually on the terminal -> remove relevant line from code).
   # Replace XXXXX with your Passphrase
   local tPassphrase = "XXXX"
   # Provide the Device Identifier (Ensure that the Identifier does not have spaces in it).
   # Replace this token with the token of the iOS device that is to receive the notification.
   local tToken = "XXXX"
   # The message that is to appear on the dialog.
   local tAlert = "You have a LiveCode APNS Message"
   # The Badge Number for the Application Icon (integer >=0).
   local tBadge = 8;
   # Audible Notification Option.
   local tSound = "default"
   # The content that is returned by the LiveCode "pushNotificationReceived" message.
   local tPayload = "APNS Message Handled by LiveCode"
   # The target folder. Ensure this folder contains all the certificates and keys needed
   local tFolder = "/Users/panos/Documents/PushNotificationAppAssets"
   # Keep note of the current folder.
   local tSavedFolder
   put the defaultFolder into tSavedFolder
   set the defaultFolder to tFolder
   # Create the notification.
   local tBody
   put tAlert into tBody["aps"]["alert"]
   put tBadge into tBody["aps"]["badge"]
   put tSound into tBody["aps"]["sound"]
   put tPayload into tBody["payload"]
   local tNotification
   put arrayToJson(tBody) into tNotification
   # Build the binary notification to send.
   local tBinary
   put empty into tBinary
   repeat for each item tCode in "0,0,32"
      put numToChar(tCode) after tBinary
   end repeat
   put binaryEncode("H*", tToken) after tBinary
   put binaryEncode("n", length(tNotification)) after tBinary
   put tNotification after tBinary
   # Write the binary to a file and send via openssl
   put tBinary into URL("binfile:Notification.bin")
   get shell("cat Notification.bin | openssl s_client -connect" && tHost & ":" & \
         tPort && "-cert" && tCert && "-pass pass:" & tPassphrase)
   answer "Result after attempting to send notification to server:" & LF & LF & it
   set the defaultFolder to tSavedFolder
end mouseup
Click to copy

Trouble Shooting

The following steps list some of the issues that were encountered when writing this lesson.

Could not Validate that the Certificates Work

If it was not possible to validate that the certificates work, then it is possible that you do not have access to the Push Notification Server.

Open a Mac terminal and enter the following line:

ping -c 5 gateway.sandbox.push.apple.com

You should get the following or similar response:

	PING gateway.sandbox.push-apple.com.akadns.net (17.172.233.65): 56 data bytes
	Request timeout for icmp_seq 0
	Request timeout for icmp_seq 1
	Request timeout for icmp_seq 2
	Request timeout for icmp_seq 3

If you do not get the above response, then it is possible that you do not have internet access or a firewall is blocking your access to that server.

If you do get this response, then it is possible that your certificates are not correct. Try debugging the process that you used to created the certificates.

Unable to get Local Issuer Certificate

You may get a verify error:num=20:unable to get local issuer certificate message when trying to talk to the Push Notification Server. This is possibly the case if the Push Notification Server does not send the client certificates in the Acceptable Certificate Authority List. This message on its own does not indicated a problem with the implementation of LiveCode Push Notification Certificates.

You should find that the following command from a Mac terminal also produces the error message:

openssl s_client -showcerts -connect gateway.sandbox.push.apple.com:2195

Push Notification does not seem to be Supported on my App

Push Notification does not seem to be Supported on my App

If you try your application, but you do not appear to have support for Push Notifications enabled, then this may be because the app ID has not all the necessary Certificates for Push Notifications. Go to Apple Dev Portal, choose the app identifier from the Identifiers section, and scroll down to Push Notifications. Click Edit.

In this example, we see that this app identifier has only a Development SSL certificate. So, this means that Push Notifications will only work in Development mode. If you want Push Notifications to work in a Production app, you need to follow the same steps as above for the generation of a Production SSL Certificate. Also you'll need to do all the previous steps again, but this time for Production instead of Development. Finally, in the sample code, you'll need to replace the host information from

gateway.sandbox.push.apple.com

to

gateway.push.apple.com

32 Comments

Patrick

Thanks for this lesson.
But thing I am not sure about is the token.
Do I need to know each device token, which has my app installed and willingly to receive the notifications?

In other words: Do I send push notifications to each device with a single command, or do I send the notification to my app users with a single command. When yes, how is this done?

Hanson Schmidt-Cornelius

Hi Patrick,

yes, when your application starts up on a device, you can read the device token. You will need to implement a mechanism that sends the token to your server.

The token is unique to every phone that is running your application.
You must push data out to every device using the keys of the particular devices that are to receive the message.

The push notification feature is not a broadcast mechanism that allows you to submit to every device that is running your application. This means that you can also be selective on the devices that are to receive the message.

Kind Regards,

Hanson

Thomas McGrath

Will the "Sending Push Notification (Livecode)" work in an app on the iPad? Since it uses a shell call? If not, How can this be done from within an iPad app???

Thanks
Tom

Bernardo

Hi
I followed every step and all are excellent, the cert are ok, the connection are fine also I send the message from the php and I received the "Delivered Message to APNS", checked the internet, the ports everything work perfect, but (always there is a "but") I don't receive any message in my device, I changed 2 devices (iPhone 4/4S) I checked the code inside the app I able to receive push notification, checked the settings are ok, I have token (development/production) i test the device under development, all the provisional cert are good, but I don't know what happens, I checked every possible error and nothing.

any advice, maybe something extra?

thanks.

Hanson Schmidt-Cornelius

Hi Thomas,

no, you cannot run any shell commands on a iOS device. What you need to do is interact with a server that can do the shell calls for you. I have included two possible approaches.

I would not recommend keeping the device identifiers of other peoples' devices on your device. So the first example is not one I would recommend, but would fit in with the requirements you have. Example 1 should probably be seen more as an academic investigation into a minimalist approach that should be expanded to fit your requirements.

Example 1 (not recommended):
1. Set up a server that is visible from the internet.
2. Create am iOS LiveCode script that passes relevant device identifier information to the server, including the message to be sent.
3. Execute the shell script on the server, using the data passed from your iOS device.

Example 2 (more viable):
1. Set up a server that is visible from the internet.
2. Set up a database on that server.
3. The database should contain people information and the device identifiers of their devices.
4. Implement a LiveCode stack for iOS that allows users to look for possible contacts on your server.
5. Create associations between people who know each other on the server.
6. Use the association information in posts to your server to activate push notification exchanges between people.

You would have to ensure that appropriate registration and security measures are put in place so that the information of the users remains private.

Kind Regards,

Hanson

Hanson Schmidt-Cornelius

Hi Bernardo,

hmm, if everything is okay and works then all I can assume is that you have an error in the content of the variable tToken. This would allow you to talk with the APNS but you would not get a message on your device.

I tried both, the PHP and the LiveCode implementation in this lesson and it worked for me. Have you had a look around the forums (http://forums.runrev.com/)? Maybe someone has come across the same problem.

Kind Regards,

Hanson

Dan

EXCELLENT Lesson! Thank you! I was able to get everything working perfectly. One question... say my app has 10,000 users and I want to send out a alert to all users. Do I make a stack that simply loops through each token and pass it to the php script on my server? 10,000 times? Won't something get overloaded?

Thanks in advance,
Dan

Hanson Schmidt-Cornelius

Hi Dan,

push notifications are not sent as a broadcast to all possible devices, but are sent as individual messages to particular devices, that are registered to receive a messages. This means that somewhere along the line there will be the need to send a message to every single devices. How this is scheduled and managed is very much dependent on how the server side application is structured.

Sending a high number of push notifications may require increased bandwidth requirements and a potentially high CPU usage while the notifications are sent.

With high volumes of notifications you also need to consider if and how much a services provider may charge for providing the services you need to send the notifications.

Kind Regards,

Hanson

Jordan

My question is how do I implement other third party push notification services into LC (like Push IO or Urban Airship) ... the reason being is that they have much more robust targeting systems already built in place. Integrating their push into my LC project would be much simpler ...

Hanson Schmidt-Cornelius

Hi Jordan,

we have not investigated how to integrate LiveCode push notifications with other vendors.
I am not saying that it is impossible, but it is outside of the scope of a lesson here.

If I intended to integrate push notification capabilities from a different vendor, then I would consider two approaches:

1. Find out what information is required in their payloads and see if you can replicate that with the LiveCode implementation. This may allow you to bypass their SDKs.
2. Consider creating an iOS external that incorporates the SDK they provide. This may cause clashes with methods that have already been implemented in LiveCode to handle push notifications.

I cannot say if either of these approaches would work, but this is where I would start.

Kind Regards,

Hanson

Waprothero

Could you provide more info on the "server". Is this a commercial notification service? I assume that a push notification server is required and wouldn't the code to access that server depend on its implementation? The tutorial shows how to simulate a server, but what about the real world implementation?

Elanor Buchanan

Dear Waprothero

The server side of things really depends on the app. The lesson, it shows how to implement the server side code to send the notification, as well as the app side code to receive the notification and fetch the ID of the current device. There are third party tools that take care of part of the server side of things, offering dashboards that allow you to send targeted notifications among other things. Though I've not had any experience working with them, so can't say how well they integrate with LiveCode apps.

Typically, an app that uses push notifications will already have a server component. Or will at least need one. i.e. there needs to be something remotely that is doing some processing and notifies the local app, like when an email is received or goal is scored. If the notifications are purely local, like time based reminders, then you can use local notifications. Which are a separate thing.

I hope that helps.

Kind regards

Elanor

Tom Owen

Thanks for your detailed guide to "Certificate" based APN. Worked like a charm with the PHP sample as well. Hopefully Apple will continue to support "certificate" based APNs and not require us to use the "Token" based method - not all of us have HTTP/2 access etc.

Simon Schvartzman

Hi team, is there any update to this lesson I should take into account? I can't make it work...this is my Terminal screen copy showing my test failure

Last login: Wed Jun 19 14:22:43 on ttys000
Simons-MacBook-Air:~ simonschvartzman$ cd desktop/certificates
Simons-MacBook-Air:certificates simonschvartzman$ openssl x509 -inform der -outform pem -in com.luckro.PushNotificationApp.cer -out PushNotificationAppCertificate.pem
Error opening Certificate com.luckro.PushNotificationApp.cer
4450629228:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('com.luckro.PushNotificationApp.cer','r')
4450629228:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
unable to load certificate
Simons-MacBook-Air:certificates simonschvartzman$ openssl x509 -inform der -outform pem -in PushNotificationApp.cer -out PushNotificationAppCertificate.pem
Error opening Certificate PushNotificationApp.cer
4470806124:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('PushNotificationApp.cer','r')
4470806124:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
unable to load certificate
Simons-MacBook-Air:certificates simonschvartzman$ openssl pkcs12 -in PushNotificationApp.p12 -out PushNotificationAppKey.pem -nocerts
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Simons-MacBook-Air:certificates simonschvartzman$ cat PushNotificationAppCertificate.pem PushNotificationAppKey.pem
cat: PushNotificationAppCertificate.pem: No such file or directory
Bag Attributes
friendlyName: PushNotificationApp
localKeyID: 4E 4C E7 82 8E CB 9B 51 7B 10 0F 47 9A 2B 80 1D 3F 30 55 57
Key Attributes:
-----BEGIN ENCRYPTED PRIVATE KEY-----
XXX....XXX
-----END ENCRYPTED PRIVATE KEY-----
Simons-MacBook-Air:certificates simonschvartzman$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushNotificationAppCertificate.pem -key PushNotificationAppKey.pem
Enter pass phrase for PushNotificationAppKey.pem:
Error opening client certificate file PushNotificationAppCertificate.pem
4563605100:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('PushNotificationAppCertificate.pem','r')
4563605100:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
unable to load certificate
Simons-MacBook-Air:certificates simonschvartzman$

it seems I'm failing to generate the "PushNotificationAppCertificate.pem" file which I really don't know how to generate.

Help please!

Elanor Buchanan

Hi Simon

It looks like there is an issue with the certificate
---
Error opening Certificate com.luckro.PushNotificationApp.cer
---
Have you followed all the steps in the lesson up to that point? Which step is the point where the instructions don't work? Did you manage to generate the certificates before getting to the "Creating your PEM file" step?

Kind regards

Elanor

Simon Schvartzman

Hi Elanor, I started all over again and followed all the lesson's steps and made some progress. Even though the actual Mac screens do not match the Lesson's I managed to generate the certificates and was able to register my iPhone and get its token. So far so good., but when I try to send a notification using the APNsAssistant script supplied with the lesson I receive the following error message:

Result after attempting to send notification to device:
unable to load client certificate private key file
4480951916:error:09FFF06C:PEM routines:CRYPTO_internal:no start line:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.260.1/libressl-2.6/crypto/pem/pem_lib.c:683:Expecting: ANY PRIVATE KEY
Please let me know what am I doing wrong...

Simon Schvartzman

Elanor, in order to help you help me I'm just adding some (hopefully helpful) information to my previous post.

This is the contents of my directory:
PushNotifications.php
AppCertKey.pem
AppCert.pem
Notification.bin
development.cer
App.certSigningRequest
PublicKey.pem
PrivateKey.pem
PushNotificationAppKey.pem
PushNotificationAppCertificate.pem
aps.cer
aps_development.cer
PushNotificationApp.p12
CertificateSigningRequest.certSigningRequest

And this is the Terminal Output when running the unmodified version of pushnotifications.php
Simons-MacBook-Air:certificates simonschvartzman$ php pushnotifications.php

Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure in /Users/simonschvartzman/Desktop/Certificates/pushnotifications.php on line 38

Warning: stream_socket_client(): Failed to enable crypto in /Users/simonschvartzman/Desktop/Certificates/pushnotifications.php on line 38

Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Unknown error) in /Users/simonschvartzman/Desktop/Certificates/pushnotifications.php on line 38
APNS Connection Failed: 0
Simons-MacBook-Air:certificates simonschvartzman$

Simon Schvartzman

Elanor, here I'm again, after watching the video with the demo (I didn't see it before, shame on me) I was able to get it working. Anyway I think this lesson deserves to be updated.
Many thanks for your support

Elanor Buchanan

Hi Simon

I'm glad to hear you got it working. We'll get this lesson updated with more up to date screenshots etc

Kind regards

Elanor

simon

Hi Elanor & all, as described on my previous post I was able to receive notifications on my iPhone by following the instructions provided on the Youtube video at the beginning of the lesson. It works fine when I install the device App directly from my Mac to the device using Apple Configurator 2 meaning I'm using a Development profile to generate the standalone. The bad news is that when I generate the standalone using the Distribution profile, successfully upload to the Apple Store using "Application Loader", install on the device and finally update the tokenID then notifications are not received any more!!! I'm pretty sure I'm somehow doing something wrong with the Certificates + IDs + Profiles but can't find out what it is. Can you please help? Many thanks!!!

Elanor Buchanan

Hi Simon

Have you checked that Push Notifications are enabled on the App Identifier you are using?

Also did you allow notifications when the app was first installed? If you had a previous version of the app on your device it is probably worth deleting it, and its data, and trying to install again. You should then be presented with the permission dialog for notifications.

I hope that helps.

Elanor

simon

Hi Elanor, many thanks for your reply, see answers below:

Have you checked that Push Notifications are enabled on the App Identifier you are using?
Yes and as I said it works fine when I install straight from the Mac to the Device. I'd guess it wouldn't work in both situations if it wasn't enabled.

Also did you allow notifications when the app was first installed?
Yes I did, and I double checked afterwards..

If you had a previous version of the app on your device it is probably worth deleting it, and its data, and trying to install again. You should then be presented with the permission dialog for notifications.
I already did as suggested, nothing changed.

Is there any way to contact John Craig? As author of the stack he probably will easily identify what the problem is...I searched him on the follow in order to send him a Private Message but found one "Craig" that I'm not sure if the right one...

Regards

Elanor Buchanan

Hi Simon,

I don't believe John Craig is currently very active in the community. It might be worth asking on the forums as many users are using push notifications and may have some suggestions.

https://forums.livecode.com/

If everything works with your development certificate it does sound like there is something wrong with your distribution certificate. Have you compared your development and distribution certificates and ensured they have the same options?

Are you handling pushNotificationRegistrationError? This might help you work out what is failing.

Sorry I can't be more help.

Kind regards

Elanor

Andrew Bell

You can use this command to take users directly from your Livecode stack to the app preferences in the system settings panel of their iOS device (replace com.your.appname with your specific app bundle id):

launch url "app-settings:root=Privacy&path=com.your.appname"

Juan Bernardo

Hi!!

We have an application that use the method explained on this lesson for receiving push notifications on IOS devices. This works fine until IOS 13 update. From this version, the token on IOS 13 devices obtained with mobileGetDeviceToken function is returning something like this "{ length = 32, bytes = 0xfa46fd1b 815ad2b1 c838faf3 b3321eff ... a70dbc00 d7da42cd }" The result of the function mobileGetDeviceToken() is the descripction field of NSData object, but now we need to use the device token data instead of the description.

Anybody knows how to solve this issue?

Thanks

Elanor Buchanan

Hi Juan

This is an issue we are aware of, you can find the bug report here

https://quality.livecode.com/show_bug.cgi?id=22577

The fix should be available in LC 9.6 DP-3. A solution in the meantime is to use LiveCode 9.5.1 where this bug does not occur. This is because with 9.5.1 you need to use Xcode 10.1 (i.e. the iOS 12.1 SDK), so it will work, even on devices that run iOS 13.

If going back to LiveCode 9.5.1 is not a workable solution for you please let us know.

Kind regards

Elanor

Simon Schvartzman

Hi, I'm confused as how do I link the App sending the notification (lets call it SenderApp) to the App that is to receive it (lets call it RecApp). In other words let's say I have RecApp installed on a given device (DeviceA) and I know the token of such device, can two different SenderApps send notifications to the same RecApp that is installed on DeviceA?

Hope I made myself clear, I'm really confused with all the details that are to be taken into account for this to work as expected.
As a matter of fact I guess a diagram detailing everything that is needed on each side should be very helpful. I'm willing to put together such diagram but I'll need some help. Elanor would you consider to help me build such diagram?

Many thanks

Elanor Buchanan

Hi Simon

Push notifications come from a server, so as long as your RecApp is set up to receive push notifications and the server(s) knows the ID of the device to send the notification to then your RecApp should be able to receive push notifications from more that one sender. The app will need to send its device token to each of the services.

To link the RecApp with the SenderApp(push notification server) the RecApp will need to send its device token to the server. How you do this will depend on how the SenderApp service is set up but in RecApp you use the mobileGetDeviceToken function to get the device token. LiveCode registers for push notifications with the operating system when your application starts. The operating system sends a callback message pushNotificationRegistered to your application once registration is complete so the mobileGetDeviceToken function should not be called until you receive the pushNotificationRegistered message.

If you think a diagram would be a helpful addition to the lesson then I'd be happy t work with you to create one.

Kind regards

Elanor

simon

Thanks Elanor, I guess I got it now. I will try to find some time to draft the diagram and will send it to you by mail for you to judge if it is worth to be added. Regards

simon

As I understand it, due to Apple depreciating the service (see below) this Lesson will not longer work after March 31, 2021...

"The HTTP/2‑based Apple Push Notification service (APNs) provider API lets you
take advantage of great features, such as authentication with a JSON Web Token,
improved error messaging, and per‑notification feedback. If you still send push
notifications with the legacy binary protocol, make sure to upgrade to the APNs
provider API as soon as possible. APNs will no longer support the legacy binary
protocol after March 31, 2021."

I wonder when will it be updated

Elanor Buchanan

Hi Simon

We are aware of this and we are working on an update to the lesson. I'll post here again when the lesson has been updated.

Kind regards

Elanor

Elanor Buchanan

Add your comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.