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
Related
I was able to get an authorisation code but I have problems with getting Access Token.
While making a Request to get an Access Token, Every time I get Fatal error: Uncaught Exception: HTTP 404 {"error": "Resource not found"}
Here is my request:
$url = "https://api.etsy.com/v3/public/oauth/token?grant_type=authorization_code&client_id={MY_ Etsy_App_ API_ Key }&redirect_uri={MY_REDIRECT_URL}&code=".$code."&code_verifier=".$code_verifier;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = array(
'x-api-key: ={ MY_ Etsy_App_ API_ Key } ',
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response_body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (intval($status) != 200) throw new Exception("HTTP $status\n$response_body");
Where can be a mistake?
You're making a GET request to the token endpoint, but you should be making a POST request and sending the parameters in the request body.
curl_setopt($curl, CURLOPT_POST, true);
$headers = array(
"Content-Type: application/x-www-form-urlencoded",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$data = "grant_type=authorization_code&code=".$code."&redirect_uri="...
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
I think you don't need the x-api-key header when making a call to the token endpoint.
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...
Here is the situation.
I have an Android app, which can send voice file with HTTP POST anywhere I specify. Also I would like to download these voice files to Telegram bot automatically. I wrote a PHP bot and I can accept and translate to Telegram any fields that come in said POST. One thing I miss is the file itself.
I don't know how to "say" to telegram API I download a file.
So what do I have: present file in $_FILE stream (I can read the name of it), I throw it in sendVoice function as $voice, also I do know I have to use simple multipart/form-data POST method to send file.
My question is: is it possible to use something but CURL to POST right from PHP? If not, what am I missing then? Other methods I use are messages and photo sending via file_get_contents(), I wonder if it's still suitable for voice file?
Here is the code I have now, which I found somewhere (I have 0 cURL knowledge):
function sendVoice($chat_id, $voice, $caption) {
$boundary = uniqid();
$delimiter = '-------------' . $boundary;
$fields = array(
"chat_id" => $chat_id,
"caption" => $caption
);
$post_data = build_data_files($boundary, $fields, $voice);
$ch = curl_init($GLOBALS['api'].'/sendVoice');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
//"Authorization: Bearer $TOKEN",
"Content-Type: multipart/form-data; boundary=" . $delimiter,
"Content-Length: " . strlen($post_data))
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_exec($ch);
curl_close($ch);
}
function build_data_files($boundary, $fields, $files){
$data = '';
$eol = "\r\n";
$delimiter = '-------------' . $boundary;
foreach ($fields as $name => $content) {
$data .= "--" . $delimiter . $eol
. 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol
. $content . $eol;
}
foreach ($files as $name => $content) {
$data .= "--" . $delimiter . $eol
. 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol
//. 'Content-Type: image/png'.$eol
. 'Content-Transfer-Encoding: binary'.$eol
;
$data .= $eol;
$data .= $content . $eol;
}
$data .= "--" . $delimiter . "--".$eol;
return $data;
}
This was actally much easier. Since we have file present in $_FILES, we can do all of the cURL in just sendVoice() function without any hassle of rebinding boundaries or specifying content types.
Here is the final code which worked for me:
function sendVoice($chat_id, $voice, $caption) {
$filepath = realpath($_FILES['file']['tmp_name']);
$post_data = array(
'chat_id' => $chat_id,
'voice' => new CURLFile($filepath),
'caption' => $caption
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $GLOBALS['api'].'/sendVoice');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_exec($ch);
curl_close($ch);
}
That will download an .OGG file as voice message (because I do not want any files to appear in my music player). Later it is possible to just add more fields such as duration in $post_data array and Telegram would eat them accordingly.
I'm using phonegap-plugin-push to send push notifications to Android devices.
I'm trying to figure out how to send notification to iOs.
I've registered at https://developers.google.com/mobile/add?platform=ios&cntapi=gcm&cnturl=https:%2F%2Fdevelopers.google.com%2Fcloud-messaging%2Fios%2Fclient&cntlbl=Continue%20Adding%20GCM%20Support&%3Fconfigured%3Dtrue
I'get token at client app same way as in Android:
var push = PushNotification.init({
android: {
senderID: "5993...475"
},
ios: {
alert: "true",
badge: true,
sound: 'false'
},
windows: {}
});
push.on('registration', function(data) {
$.ajax({
url: '/save-token/',
data: {token: data.registrationId},
success: function (json) {
}
});
});
After I get client's token, I try to send'em push notification:
$to = ModelGcmTokens::getInstance()->getToken($userId);
$API_KEY = 'AIzaS...HcEYC346zQ';
$message = array(
'data' => array(
'title' => ($title) ? $title : 'Test!',
'message' => $message
),
'to' => $to
);
$message = json_encode($message);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://gcm-http.googleapis.com/gcm/send");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Authorization:key={$API_KEY}",
"Content-Type:application/json",
));
// receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
// further processing ....
if ($server_output == "OK") {
return true;
} else {
return false;
}
Google cloud messaging responds with InvalidRegistration error:
{"multicast_id":4701637331500989392,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
As I googled this error - it's said that I got client's token wrong.
But I get it with excat same script as on Android. And it works on Android.
The only difference, that I see - is format of the token:
Can anyone tell me how do I get push plugin working on iOs? What's wrong with iOs token and how do I supposed to send messages to GCM, to be received by iOs?
Thanks a lot in advance for any advice. I'm really stuck.
The way you are calling the init method requests the registration ID from APNS not GCM. If you read the documentation on GCM on iOS at the phonegap-plugin-push repository you will see that init needs to be called like this:
var push = PushNotification.init({
android: {
senderID: "5993...475"
},
ios: {
senderID: "5993...475",
gcmSandbox: true,
alert: "true",
badge: true,
sound: 'false'
},
windows: {}
});
If the iOS options has a senderID it will register with GCM.
Also, I notice in the response to one of the comments you don't know the difference between production and development environments on APNS. Well, you really need to read up on this. On iOS devices the APNS environment is different depending if you production and development environment. IF you setup your app as development and you send a push through production it will never arrive at your device.
Now you may be asking why I'm talking about APNS. That's because when you use GCM on iOS you would send your push message to GCM which then will forward your message to the APNS servers and finally to your device.
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