I am implementing a push notification in my application.
Server: php
Client: iphone
Sever side Coding:
function pushToIphone($deviceToken, $badge){
ini_set('display_errors','on');
error_reporting(E_ALL);
//$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$pem_path = dirname(__FILE__);
$pem_path = $pem_path .'\cert';
$apnsCert = $pem_path.'\apns_cer.pem';
echo $apnsCert."<br/>";
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if($apns) {
echo "Connection Established<br/>";
$payload = array();
//$payload['aps'] = array('alert' => 'BiiMe finds product for you', 'badge' => $badge, 'sound' => 'default');
//$payload = get_payload_message('BiiMe finds product for you',$badge);
//$payload['server'] = array('serverId' => $serverId, 'name' => $serverName);
//$payload = json_encode($payload);
$payload = get_payload_message('BiiMe finds product for you',$badge);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
echo $apnsMessage."<BR/>";
$fwrite = fwrite($apns, $apnsMessage);
echo $fwrite." bytes written<BR/>";
} else {
echo "Connection fail<br/>";
}
//socket_close($apns);
fclose($apns);
}
function get_payload_message($message_text,$badge,$sound='default')
{
$PAYLOAD_MAXIMUM_SIZE = 256;
$payload['aps'] = array("alert" => "$message_text", 'badge' => $badge, 'sound' => $sound);
$payload = json_encode($payload);
$nJSONPayloadLen = strlen($payload);
if($nJSONPayloadLen > $PAYLOAD_MAXIMUM_SIZE)
{
$nTextLen = strlen($message_text);
if($nJSONPayloadLen - $nTextLen <= $PAYLOAD_MAXIMUM_SIZE)
{
$badge_count = substr($message_text, 0, $nTextLen - ($nJSONPayloadLen - $PAYLOAD_MAXIMUM_SIZE));
$payload = get_payload_message($message_text);
}
}
return $payload;
}
Iphone side i added:
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"It comes<<<<<<<<<<<<<---------------------------------------");
NSString *str = [NSString
stringWithFormat:#"Device Token=%#",deviceToken];
NSLog(str);
NSString *token = [NSString stringWithFormat:deviceToken];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:token forKey:#"deviceId"];
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"It comes with error---------------------------->>>>>>>>>>>>>>");
NSString *str = [NSString stringWithFormat: #"Error: %#", err];
NSLog(str);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:str forKey:#"deviceId"];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
for (id key in userInfo) {
NSLog(#"key: %#, value: %#", key, [userInfo objectForKey:key]);
}
}
also i use:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIImageView *loading = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
[loading setImage:[UIImage imageNamed:#"Default.png"]];
[window addSubview:loading];
[loading release];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound)];
}
This is my whole code that used:
iPhone Log shows while Device is Connected:
2012-02-03 19:51:32.872 BiiMe[7544:707] It comes<<<<<<<<<<<<<---------------------------------------
2012-02-03 19:51:32.873 BiiMe[7544:707] Device Token=<26d906c5 c273446d 5f40d2c1 73ddd3f6 869b2666 b1c7afd5 173d69b6 629def70>
all times server side:
Connection Established
What is missing by me..? or what should i implemented in my code:
your answer will help me.
use this code in didFinishLaunchingWithOption in AppDelegete
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)];
gateway.push.apple.com is used for released application or AdHoc application. If you are checking with development profile you might need to change it to gateway.sandbox.push.apple.com
Hope this helps.
Related
I'm trying to send a remote notification from own php server to app.
Here's the code in AppDelefate.m:
#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
#interface AppDelegate ()
#end
#implementation AppDelegate
#define SYSTEM_VERSION_GRATERTHAN_OR_EQUALTO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self registerForRemoteNotifications];
return YES;
}
- (void)registerForRemoteNotifications {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
if(!error){
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}];
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"User Info : %#",notification.request.content.userInfo);
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
//Called to let your app know which action was selected by the user for a given notification.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSLog(#"User Info : %#",response.notification.request.content.userInfo);
completionHandler();
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"%#", userInfo);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"%#", userInfo);
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)applicationDidFinishLaunching:(UIApplication *)app {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
// Handle remote notification registration.
- (void)application:(UIApplication *)app
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
NSString *token = [[devToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"content---%#", token);
}
- (void)application:(UIApplication *)app
didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"Remote notification support is unavailable due to error: %#", err);
}
- (void)applicationWillResignActive:(UIApplication *)application {
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
#end
When I run the app, it ask for notification privilege, after accepted. Console print the following token:
content---13eeb8d33de4f0ba55f520469f9b0970e973faa6904a38428b2193b04ac3782b
So I use this token in my PHP server for testing:
<?php
// Put your device token here (without spaces):
$deviceToken = '13eeb8d33de4f0ba55f520469f9b0970e973faa6904a38428b2193b04ac3782b';
// Put your private key's passphrase here:
$passphrase = 'xoxoxo';
// Put your alert message here:
$message = 'Test push.';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'BDSPKCertificates.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
var_dump($ctx);
// Open a connection to the APNS server
$apns = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); // production
echo "<p>Open Connection</p>";
if(!$apns)
{
echo "<p>Failed to connect!<br />Error Number: " . $err . " <br />Code: " . $errstr . "</p>";
return;
}
else
{
echo "<p>Connected</p>";
// Create the payload body
$body = array();
$body['aps'] = array(
"title"=>"Test title",
'alert' => $message,
'sound' => 'default',
'badge' => 1
);
// Encode the payload as JSON
$payload = json_encode($body);
echo "<p>Message: ";
print_r($payload);
echo "</p>";
// Build the binary notification
$msg = chr(0) . pack("n",32) . pack('H*',str_replace(' ', '', $deviceToken)) . pack ("n", strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($apns, $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($apns);
}
?>
When i run this PHP code, it prints the following:
resource(2) of type (stream-context)
Open Connection
Connected
Message: {"aps":{"title":"Test title","alert":"Test push.","sound":"default","badge":1}}
Message successfully delivered
However my app receive nothing. Please help me to find what is missing in my codes. Thanks.
please confirm, you have open 2195 port in server firewall. Apple push notification sent via 2195 port. So it should open.
I think you are using sandbox environment but in your PHP script your socket client is production, use sandbox for development like below.
Sandbox
ssl://gateway.sandbox.push.apple.com:2195'
// Open a connection to the APNS server
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); // sandbox
Production
ssl://gateway.push.apple.com:2195'
// Open a connection to the APNS server
$apns = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); // production
Here is my NodeJS code , which is working totally fine.
var options = {
//production
"cert": readCredentialsFile(cert_file),
"key": readCredentialsFile(cert_key_file),
"production" : production_val,
"passphrase": "mypassphrase",
"gateway": gateway_val,
"port": 2195,
"enhanced": true,
"cacheLength": 5,
"retryLimit":-1
};
options.errorCallback = apnError;
var feedBackOptions = {
"cert": readCredentialsFile(cert_file),
"key": readCredentialsFile(cert_key_file),
"passphrase": "mypassphrase",
"production" : production_val,
"batchFeedback": true,
"interval": 300
};
var apnConnection, feedback;
module.exports = {
initAPN : function(){
try {
apnConnection = new apn.Connection(options);
feedback = new apn.Feedback(feedBackOptions);
feedback.on("feedback", function (devices) {
devices.forEach(function (item) {
//TODO Do something with item.device and item.time;
});
});
} catch (error) {
console.log(error);
}
},
sendIOSNotification : function (device_token,message,params){
var myDevice, note;
try{
console.log("iOS device_token ", device_token);
var randomID = require("random-id");
var payloadMultiCast = {
"data": {
"id": randomID(),
"status": params.notification_type,
"title": message,
"body": params,
"message": message
}
};
myDevice = new apn.Device(device_token);
note = new apn.Notification();
note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
note.badge = 1;
note.sound = "ping.aiff";
note.alert = message;
note.payload = payloadMultiCast;
console.log("iOS Notification ", note);
if(apnConnection) {
apnConnection.pushNotification(note, myDevice);
console.log("iOS res "+ device_token+":::"+JSON.stringify(apnConnection));
}else{
console.log("NO APNS CONNECTION");
}
}catch(err){
console.log("error:-"+err);
}
}
}
And below is my php code , which is not working with same "pem" file and same credentials:-
$streamContext = stream_context_create();
stream_context_set_option($streamContext, $options);
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 60000, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns)
$errrrr = json_encode(error_get_last());
echo("Failed to connect 11amarnew: $err $errstr $errrrr" . PHP_EOL);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $dev)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
fclose($apns);
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $file);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$err = ""; $errstr = "";
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195',
$err,
$errstr,
600000,
STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,
$ctx);
if (!$fp)
$errrrr = json_encode(error_get_last());
exit("Failed to connect amarnew: $err $errstr $errrrr" . PHP_EOL);
//echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$message = "Hello Moto!!";
$body['aps'] = array(
'badge' => +1,
'alert' => $message,
'sound' => 'default'
);
$payload = json_encode($body);
$deviceToken = "ed3d13a56a92027acbb9805bfa5f9a3d6da4fdcf24a57b375bfb638259e9d31c";
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $dev) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
//echo "<pre>"; print_r($result); die();
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered amar'.$message. PHP_EOL;
// Close the connection to the server
fclose($fp);
The error i am getting is -
Failed to connect amarnew: 0 {"type":2,"message":"stream_socket_client(): unable to connect to ssl:\/\/gateway.sandbox.push.apple.com:2195 (Unknown error)","file":"\/var\/www\/html\/push.php","line":42}
FYI , I have allowed 2195 , 2196 ports also on my sever for PHP , NodeJS doesn't need port to be opened.
Then what is issue that causing not working in PHP and working in NodeJS, finally i have to use the php only hence i need to solve the issue.
Thanks,
Push notification badge count not increasing.It shows always 1.I have used php to send the push from server and here is the code following:
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsCert = 'project_dev.pem';
$apnsPort = 2195;
$badgecount=1;
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns){
exit("Failed to connect: $error $errorString" . PHP_EOL);
}else{
$messageHeader = (strlen($message) > 26) ? substr($message,0,26).'...' : $message;
$msgd=explode(':',$message);
$payload['aps'] = array('alert' => $messageHeader,'badge' => $badgecount, 'sound' => 'default','mess'=>$fromUserId.'||'.$userNamee.'||'.$userimage.'||'.$message,'type'=>'reply', 'unread_count'=>$unread_count);
$output = json_encode($payload);
$token = pack('H*', str_replace(' ', '', $token));
$apnsMessage = chr(0) . chr(0) . chr(32) . $token . chr(0) . chr(strlen($output)) . $output;
fwrite($apns, $apnsMessage);
fclose($apns);
}
badgecount always send by server side.it seems you are sending $badgecount=1; always.Update it with other value then check.It definitely reflect on IOS.
In your code you have send your badge always one that's why you getting only $badgecount 1 badge into application side.
you need to use following type to send notification badge.
$query = "SELECT badgecount FROM pushnotifications WHERE device_token = '{$device_token}'";
$query = $this->db->query($query);
$row = $query->row_array();
$updatequery = "update pushnotifications set badgecount=badgecount+1 WHERE device_token ='{$device_token}'";
$updatequery = $this->db->query($updatequery);
$device = $device_token;
$payload['aps'] = array('alert' => $pushmessage, 'badge' =>$row["badgecount"]+1, 'sound' => 'default');
$payload = json_encode($payload);
I think you now more clearify with above code.
This is the code that I am using for notification from PHP to iOS
#--------------- initializations ------------------------------
$message = substr($message, 0, 255);
$sound = 'default';
$development = true;
$badge = '1';
$payload['aps'] = array(
'alert' => $message,
'badge' => intval($badge),
'sound' => $sound
);
$payload = json_encode($payload);
$apns_url = NULL;
$apns_cert = NULL;
$apns_port = 2195;
#-------------------------(/initializations)---------------
// developement or live server certificate
if($development)
{
$apns_url = 'gateway.sandbox.push.apple.com';
$apns_cert = __DIR__.'/app_dev.pem';
}
else
{
$apns_url = 'gateway.push.apple.com';
$apns_cert = __DIR__.'/app_prod.pem';
}
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
$apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_CONNECT, $stream_context);
$device_tokens = $receivers;
foreach($device_tokens as $device_token)
{
$apns_message = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_token)) . chr(0) . chr(strlen($payload)) . $payload;
$result = fwrite($apns, $apns_message,strlen($apns_message));
}
#socket_close($apns);
fclose($apns);
The error I am getting is
Warning: stream_socket_client(): unable to connect to
ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out)
Can anybody see what is wrong with code ?I have read many posts related to this but nothing is helping me .
i'm developing an app that need push notification.
I'm following this tutorial to implement push notification with php.
So i'm using production certificate.
This is the code in the applicationDelegate:
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
const unsigned* tokenBytes = [deviceToken bytes];
NSString* tok = [NSString stringWithFormat:#"%08x%08x%08x%08x%08x%08x%08x%08x",
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
NSLog([NSString stringWithFormat:#"token 1 = %#",tok]);
[[NSUserDefaults standardUserDefaults] setObject:tok forKey:#"token"];
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"Received notification: %#", userInfo);
}
and this is the server side php page:
<?php
//$token = $_GET['t'];
$token = "xxxxxxxxxxx....xxxxxx";
$who =$_GET['c'];
$notification = $_GET['n'];
$message = 'Hello';
$badge = 3;
$sound = 'default';
$payload = array();
$payload['aps'] = array('alert' => $message, 'badge' => intval($badge), 'sound' => $sound);
$payload = json_encode($payload);
$apns_url = NULL;
$apns_cert = NULL;
$apns_port = 2195;
$apns_url = 'gateway.push.apple.com';
$apns_cert = 'cert-prod.pem';
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
$apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 2, STREAM_CLIENT_CONNECT, $stream_context);
$device_tokens = array();
$device_tokens[0] = $token;
foreach($device_tokens as $key=>$device_token)
{
$apns_message = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_token)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apns_message);
}
#socket_close($apns);
#fclose($apns);
?>
Nothing happen when i launch php page.. why? who can help me?
i think your token isnt correct. try:
NSString *token = [NSString stringWithCString:[deviceToken bytes]];
this should help:
NSString *deviceTokenStr = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: #"<" withString: #""]
stringByReplacingOccurrencesOfString: #">" withString: #""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"Device Token: %#", deviceTokenStr);