push notification not working on ios 9 devices - ios

Ever since iOS 9.0 - 9.2 was implemented users of my app that are using it no longer receive push notifications.
My code works fine when sending to Android devices as I am separating the two platforms (iOS and Android) into 2 different arrays and processing them accordingly.
The result from the APNs server does not return an error at all.
Are there known issues documented on what could have changed on the push notification server? If so please provide links to them.
Below is the code that i am using to send the push notifications(PHP):
public function send_notification($message) {
$title = 'My App';
$platform = '';
$users = mysql_query("select * FROM push_devices");
$no_of_users = mysql_num_rows($users);
// Initialize the array for storing the platform specific tokens
$iOSusers = array();
$androidUsers = array();
if($no_of_users > 0){
// Seperate the tokens
while ($row = mysql_fetch_array($users)) {
$platform = $row['platform'];
if($platform == 'Android' || $platform == 'android'){
// Add to android list
$androidUsers[] = $row['push_id'];
}
if($platform == 'iOS' || $platform == 'ios'){
$iOSusers[] = $row['push_id'];
}
}// endwhile
}
if(!empty($androidUsers)){
$messageAndTitle = array(
'message' => $message,
'title' => $title
);
// Set POST variables
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $androidUsers,
'data' => $messageAndTitle,
);
$headers = array(
'Authorization: key=' . ***GOOGLE_API_KEY***,
'Content-Type: application/json'
);
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
// Increase the timeout
curl_setopt($ch, CUROPT_CONNECTTIMEOUT, 1000);
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
// Execute post
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
echo $result . '<br/>';
// close the connection
curl_close($ch);
}
// Handle iOS push
if(!empty($iOSusers)){
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', **PUSH_CERT_FILE**);
stream_context_set_option($ctx, 'ssl', 'passphrase', **PUSH_PARAPHRASE**);
// Open a connection to the APNS server
$fp = stream_socket_client(
PUSH_SERVER, $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;
$badgeCount = 2;
$badge = (int)$badge;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'badge' => $badge,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
//Note: $deviceToken is an array for android push
foreach ($iOSusers as $token) {
$msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
//echo 'Device token: ' .$deviceToken[0];
if (!$result)
echo 'Message not delivered' . PHP_EOL . $token . '<br/>';
else
echo 'Message successfully delivered' . PHP_EOL . $token . '<br/>';
}
fclose($fp);
} // iOS
}

There are hundreds of thread over the Internet about notifications not working on iOS 9, but I think that the problem is server-side.
I noticed an issue with Push notifications on my iPhone 5 (iOS 7.1.2) in the last couple of weeks, and I discovered that the problem is originating from the Apple Push Notification Server.
I am now receiving about 10% of notifications on Whatsapp and 0% on Facebook Messenger, but I am sure other apps are involved too.
With another app (Bspotted), installed more recently, I'm receiving 100% of notifications.
So I've downloaded the profile PersistentConnectionLogging.mobileconfig in order to enable logging for push notifications.
Turns out that the Apple Push Server is sending notifications with TOKEN (null), so of course the apps can't handle them:
copyTokenForDomain push.apple.com (null)
Moreover, it seems that all notifications I received with token null (on Whatsapp and Messenger) came from Android devices. I received a message on Whatsapp from an iPhone, and it was the first notification I received in two weeks.
Maybe is a coincidence, because now I managed to receive 10% of notifications on Whatsapp also from Android devices (for two weeks it was 0%).
I tried all of this:
Reset in-app notifications
Reset iOS app notifications
Reinstall the app
Reset iOS network configuration
Forced iPhone restart
Uninstall the app, set the date 2 days forward, reinstall the app (in order to force the app to ask for permission on notifications)
I hope this will help.
Best Regards

Related

Push Notification issue in iOS 13

I am using Remote Push Notification feature in my iOS application. Currently i am facing a strange issue. I am receiving push notifications into devices which are have iOS < 13 but those devices which are have iOS 13 not getting push notifications.
I searched a lot over stackoverflow and other platform and found that apple suggested that in iOS 13 we need to add "apns-push-type" into header as well as in payload body. I have done it over server side where i write push notifications related code.
I developed my application using XCode 11 and using FCM (Firebase Cloud Messaging) service to send push notifications.
public function pushSurveyorNotificationios(){
$url = "https://fcm.googleapis.com/fcm/send";
$token = 'XXXX-XXXXX-XXXXX';
$serverKey = 'XXXX-YYYYY-ZZZZZ';
$title = "Push Notification Testing";
$body = "Push Notification Testing detail";
$notification = array('title' =>$title , 'body' => $body, 'sound' => 'default', 'badge' => '1');
$arrayToSend = array('to' => $token, 'notification' => $notification, 'apns' => array('headers' => array('apns-push-type' => 'alert')));
$json = json_encode($arrayToSend);
//die($json);
$headers = array();
$headers[] = 'apns-push-type: alert';
$headers[] = 'Content-Type: application/json';
$headers[] = 'Authorization: key='. $serverKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,
"POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
//Send the request
$response = curl_exec($ch);
//Close request
if ($response === FALSE) {
die('FCM Send Error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
Above function i am using to send push notifications to devices.
I got this link over apple for iOS 13 push notifications issue.
https://developer.apple.com/forums/thread/118420

APNS Push notification Background non working anymore

Sorry to repost this question as it was asked a few times, but no answer was ok for me.
My app don't wake up anymore on background notification.
So I updated my php script and added HEADERs field as documented here and here
But no luck.
Here my sample code :
<?php
$device_token = 'd98e1d488acac56305a9f83b...b616bc5b5b3bf238dc';
//$device_token = '27b296397f81f48590a....fe2742e0b2a051ae2cefffded85d7';
// Put your private key's passphrase here:
$pem_secret = '';
$pem_file = 'pushcert.pem';
$url = "https://api.development.push.apple.com/3/device/$device_token";
//$body = '{"aps":{"alert":"balbla","badge":0,"sound":"default"}}';
$body = '{"aps":{"content-available":1},"acme1":"bar"}';
$header = ['apns-topic'=>'com.blabla.bla',
'apns-push-type'=>'background',
'apns-priority'=>'5'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_SSLCERT, $pem_file);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $pem_secret);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$information = curl_getinfo($ch);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//On successful response you should get true in the response and a status code of 200
//A list of responses and status codes is available at
//https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1
//var_dump($header);
//var_dump($information);
var_dump($response);
var_dump($httpcode);
?>
I never enter the iOS methode to catch this notification :
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[NSUserDefaults standardUserDefaults] setValue:userInfo forKey:#"testtesttest"];
// Method called when user click on notification and application is in background
application.applicationIconBadgeNumber = 0;
NSLog(#"did received remote notification"); }
Also in my device console, it seems that the device is canceling my notifications or something a don't get.
Also not that standard notifications (not in Background) works fine.
testing iOS 13.3.1
Thanks a lot for any help you could get me.
Background mode enabled :
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>location</string>
<string>processing</string>
<string>remote-notification</string>
</array>
App Settings also configured :
I managed to make it Work with that sample code:
<?php
// open connection
if (!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}
$device_token = 'd56e9ef8b5ea558f07584cf8...498824ece60a36229446a2003116'; //David
// Put your private key's passphrase here:
$pem_secret = '';
$pem_file = 'pushcert.pem';
$url = "https://api.development.push.apple.com/3/device/$device_token";
$app_bundle_id = "com.blabla.blabla";
//$body = '{"aps":{"alert":"balbla","badge":0,"sound":"default"}}';
$body = '{
"aps":{"content-available":1},
"type":"LOCATION",
"idRequest":"538EAC3E765A4BDC89B554C40F5B14EF"
}';
$headers = array(
"apns-topic: {$app_bundle_id}",
"User-Agent: My Sender",
"apns-push-type:background",
"apns-priority:5"
);
var_dump($body);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_PORT,443);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST,TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSLCERT, $pem_file);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
$response = curl_exec($ch);
$information = curl_getinfo($ch,CURLOPT_HTTPHEADER);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//On successful response you should get true in the response and a status code of 200
//A list of responses and status codes is available at
//https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1
//var_dump($header);
var_dump($information);
var_dump($response);
var_dump($httpcode);
?>
Well at least it seems that the application is waking up (seen in the device log)
So this morning I launch the code from yesterday (with no modifications at all) and it worked for a few times, like 4 or 5 times.
Now it doesn't work anymore. Same as yesterday (iOS system seems to catch the payload, but application is not waked up)
-> conclusion, this a system limitation, and this is so confusing when you need to perfom tests. I'm gonna put this in production with no assurance it will work properly...

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.

Older push notifications are being sent repeatedly from APNS

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?

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