Older push notifications are being sent repeatedly from APNS - ios

I have an iPhone application that receives push notifications sent from a PHP server. I implemented the tutorial on Raywenderlich for this task.
I am sending push notifications for schedules in user's calender and some users have reported that the push notifications reminding user about a particular schedule gets sent repeatedly.
To be precise, when first notification comes it behaves normally, but when second comes it displays older notification too. The time of older notification is old as well. Only the current notification shows Now, the older notifications show some something like 10 hours ago. Then third notification shows 3 notifications and so on.
Someone told me to use APNSPHP library and set a unique custom identifier on every notification but that didn't help either.
What I am doing is that I am sending several push notifications (albeit to different users) over a single connection to APNS. The payload contains a key and a list of arguments corresponding to a list of localised formatted strings stored in Localizable.strings in the iPhone app.
function __push_data($push_notifications, $push_content) {
$ctx = stream_context_create();
if (ENVIRONMENT == 'development') {
stream_context_set_option($ctx, 'ssl', 'local_cert', 'dev.combined.pem');
} else if (ENVIRONMENT == 'production') {
stream_context_set_option($ctx, 'ssl', 'local_cert', 'prod.combined.pem');
}
stream_context_set_option($ctx, 'ssl', 'passphrase', A_PRIVATE_KEY);
/* Open a connection to the APNS server */
$apns_server = "ssl://gateway.sandbox.push.apple.com:2195";
if (ENVIRONMENT == 'production') {
$apns_server = "ssl://gateway.push.apple.com:2195";
}
$fp = stream_socket_client(
$apns_server, $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if ($fp) {
foreach ($push_notifications as $index => $push_notification) {
$body = array();
/* Create the payload body */
$body['aps'] = array('alert' => array('loc-key' => $push_notification['key'], 'loc-args' => $push_notification['message']), 'sound' => 'default');
$body['sopnc'] = $push_content;
/* Encode the payload as JSON */
$payload = json_encode($body);
/* Build the binary notification */
$msg = chr(0) . pack('n', 32) . pack('H*', $push_notification['push_token']) . pack('n', strlen($payload)) . $payload;
/* Send it to the server */
$result = fwrite($fp, $msg, strlen($msg));
if (!$result) {
echo 'Message not delivered' . PHP_EOL;
} else {
echo 'Message successfully delivered' . PHP_EOL;
}
}
/* Close the connection to the server */
fclose($fp);
}
}
Has somebody else encountered such problem?

Related

Apple APNs push notification is not working

My team is using the Apple push notifications for the last 7 years which was working like a Gem. Recently generated builds in both the Development certificate and the App Store certificate are not receiving notifications.
The notification is sent from the PHP code.
<?php
// Put your device token here (without spaces):
$deviceToken = '****************';
// Put your private key's passphrase here:
$passphrase = '******';
// Put your alert message here:
$message = 'Hi User!';
//$message =$_REQUEST['message'];
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'cert.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
/* Open a connection to the APNS server*/
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
echo $result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
The Push notification results as a success. But the App is not receiving the notification. Is there any new update in this code? Is there any chance for errors in receiving notifications on the device?
If you was sending push using p12 or pem file then it's stopped.
You have to use new way using P8 files
Check below link for further details.
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/

PHP For iOS Push Notifications, Sometimes More Than 1 Device

I am building an app in which I am using NSUserDefaults to store various pieces of information, including the deviceToken that is used for APNS on iOS. The way it is currently working is that a user submits a request, and it adds an entry to an XML, one of the elements in that XML is called deviceToken. When someone responds to that request, it triggers the PHP at the bottom of the page to send a Push Notification to the deviceToken of that particular request. My issue is that some people have more than one device, and it would be nice to send the Push Notification to all of that owner's devices. As you can see in the code below, I have 2 areas for deviceTokens. If the XML contains 2 device tokens, everything is great. The issue is that for the ones that there is only 1 token, it will fail to deliver even the one. How can I fix this PHP so that it will be able to accept 2 deviceTokens, but still deliver if only 1 is available?
<?php
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$title = $_POST['title'];
$deviceToken = $_POST['deviceToken'];
$deviceToken2 = $_POST['deviceToken2'];
$xml = simplexml_load_file("http://www.URL.xml") or die("Not loaded!\n");
$passphrase = 'passphrase';
// Put your alert message here:
$message = 'Someone just responded to you!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
$msg2 = chr(0) . pack('n', 32) . pack('H*', $deviceToken2) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
$result = fwrite($fp, $msg2, strlen($msg2));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
What you can do is use the function as a generic one: that is, it accepts a device token object. This could be a single string, or an array of multiple strings.
Then, check whether$deviceToken is an array using the is_array function. Ref:http://us3.php.net/manual/en/function.is-array.php
For this, you may have to rewrite small bits of the code. So overall, it would look something like this:
if(is_array($deviceToken)) {
// Iterate over the array and call the same function with each string
return;
}
// You're code to actually send the push notification just as you have it above.

APNS: First push delivers only

I've a really strange behavior in my app.
Only the first push notification send will be delivered.
All other won't arrive. I waited for 1 week, and still it wasn't delivery.
But if I reinstall the app, the first notification will be delivered instantaneously.
I never had this problem before. All other apps are working with APNS.
Thanks,
Maik
EDIT:
<?php
// Put your device token here (without spaces):
$deviceToken = 'token';
// Put your private key's passphrase here:
$passphrase = 'pw';
// Put your alert message here:
$message = 'message';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
(i tested development and production push)
fixed it, created a new app id. Think the problem was, that i deleted the appId from the old account and created it on the new developer account.

How to setup push notification for development?

I've developed an app for ios and it has been published on the app store.
The push notification system worked fine in development but now, i receive no notification at all.
Before publishing, i've generated the Development Provisioning Profiles associated with an App Id having enabled the push and configurated the Production Push SSL Certificate. I've downloaded the Production Push SSL Certificate and installed it in my keychain access, exported it and its private key, converted them to pem and united them in a unique pem file, which i uploaded to my server containing the php script which send the notifications.
I've changed the server in my php script to the one of production (ssl://gateway.push.apple.com:2195).
Still the script seems to send the notification and doesn't fire any error.
What i'm missing?
Here's my php script:
<?PHP
/* Here there's Code to retrieve device tokens and put it in a variable $deviceToken from my online database and then...*/
$message = "Message to be sent";
$payload = '{
"aps" :
{ "alert" : "'.$message.'",
"badge" : 1,
"sound" : "bingbong.aiff"
}
}';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', 'secret');
// se l'app è già sull'appstore togliere sandbox e lasciare solo gateway.push.apple.com:2195
// invece di gateway.sandbox.push.apple.com:2195
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if(!$fp){
print "Failed to connect $err $errstrn";
return;
} else {
print "Notifications sent! </br>";
}
foreach($devArray as $deviceToken){
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack ("n",strlen($payload)) . $payload;
print "sending message :" . $payload . "n to device:".$deviceToken."</br>";
fwrite($fp, $msg);
}
fclose($fp);
?>
Cause you have to regenerate the PEM with a valid "Production Push SSL Certificate" not with the "Development Push SSL Certificate".
EDIT: Sorry i've read two times the wrong row. The procedure looks good, i post the php code that i always use, it looks very similar but you can try to edit it.
<?php
// Passphrase for the private key (ck.pem file)
// $pass = ”;
// Get the parameters from http get or from command line
$message = 'Testo Notifica Push';
$badge = 1;
$sound = 'default';
// Put your private key's passphrase here:
$passphrase = '';
// Construct the notification payload
$body = array();
$body['aps'] = array('alert' => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
/* End of Configurable Items */
// Put your device token here (without spaces):
$deviceToken = '20afc981ce9f0c63b5beb83d561d086a1338b2d42dd6defef67e4b7dbabe72b9';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'cert.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Construct the notification payload
$body = array();
$body['aps'] = array(’alert’ => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
One last step to do when setting up push is be sure you didn't mixed production and development device token!
In my case, in my db the first device token the push was send to, was a development one. When this happens, Apple server kill the connection, avoid any other notification to be sent. Thanks Apple!

How to parse dropbox rss feed on a server

I am developing an ios app that uses Dropbox SDK. I want to notify user when any of the files in Dropbox is edited. I dont know If Dropbox provides any API's but I am thinking Apple's push notification would be nice. According to my research there is something like /delta in Dropbox SDK but there is not enough resource or example codes out internet to understand /delta.
What I want is:
Dropbox files changes----> My server detects what is changed and sends to apple-----> Apple push notification service send notification--------> IOS device receive notification
So Currently I completed push notification part of my application, I can send a simple notification to my app with via local apache server and php script. Device receives notification.
My question is how can I achieve
This part Dropbox files changes----> My server detects what is changed and sends to apple----->
I do not know how to parse rss feed of my dropbox folder. What language Should I use to parse data on dropbox?
Should I continuously poll and check if any of the files is edited?
or Is there a way that dropbox send a notification directly to my server or to apple notification server so I wont need to poll for changes all the time?
Thanks in Advance
what you would want to is to create a php script that will parse your rss feed and send the push notification to your app. And use a server that allows cron commands so you can continously run this script and check for updates.
<?php
//set the time zone
date_default_timezone_set('America/New_York');
//get xml file from dropbox event page
$completeurl ='your xml url';
//equal badge to zero
$badge=0;
//format date and time
$format = 'D, d M Y H:i:s O';
// Put your alert message here:
$message;
//parse the xml file
$item = $xml->channel->item;
for ($i = 0; $i < sizeof($item); $i++) {
$title = $item[$i]->title;
$description=$item[$i]->description;
$pubDate = $item[$i]->pubDate;
//search title for word 'edited'
if (strpos($title,'edited') !== false) {
echo "Edited word is found in title true \n";
$inDate = DateTime::createFromFormat( $format, $pubDate);//input date and time
$postDate = new DateTime();// current date and time
$diff = $inDate->diff( $postDate); // difference current-input
// If the total number of days is > 0, or the number of hours > 0, or the number of minutes > 30, then its an invalid timestamp.
if( $diff->format( '%a') > 0 || $diff->format( '%H') > 0 || $diff->format( '%i') > 30) {
echo "update is not recent\n";
}else{
//if true increase badge by one
$badge = $badge + 1;
}
}
}
//print total updates
echo "Total Badge= " . $badge. "\n";
//if total updates is bigger or equal to one send notification
if($badge>=1){
// Put your device token here (without spaces):
$deviceToken = 'yourdevicetoken';
// Put your private key's passphrase here:
$passphrase = 'yourpassphrase in your.cem file';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'badge' => $badge
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
}else
echo "There is no update available \n";
?>

Resources