I am really struggling with this. This piece of code wasn't created by me but I have changed it so it sort of works. My goal is for it to be able to send push notifications to all devices that use the app. I am an ios and andriod programmed so I will try my best. I have cleaned up and changed the code that was given to me so that it will now send a notification to just one device.
This is the code
<?php
include 'conn.php';
if ( $_REQUEST['key'] == 'notification' ) {
include 'notifications.php';
$message = $_REQUEST['text'];
$text = mysql_real_escape_string( $_REQUEST['text'] );
$start = $_REQUEST['start'];
$end = $_REQUEST['end'];
$date = date( "Ymd", strtotime( $_REQUEST['date'] ) );
$callus = $_REQUEST['callus'];
$in = "INSERT INTO `notifications` (`date`, `start_time`, `end_time`, `text`, `call_us`) VALUES ('$date', '$start', '$end', '$text', '$callus');";
mysql_query($in);
} else {
$message = mysql_real_escape_string( $_REQUEST['text'] );
$time = date( 'Y-m-d H:i:s' );
$in = "INSERT INTO `alerts` (`text`, `time`) VALUES ('$message', '$time');";
mysql_query( $in );
$sel="SELECT * FROM `users` GROUP by device_token";
$rs = mysql_query( $sel ) or die('');
if ( mysql_num_rows( $rs ) != 0 ) {
while( $row=mysql_fetch_array( $rs ) ) {
$regi = array();
$regi[] = $row['device_token'];
$dev = $row['device_token'];
if( strlen ( $dev ) > 65 ) {
$regis[] = $row['device_token'];
} else {
$ios[] = $dev;
}
}
}
$url = 'https://android.googleapis.com/gcm/send';
$fields = array( 'registration_ids' => $regis, 'data' => array( 'message'=>$message,'count'=>1 ) );
$headers = array(
'Authorization: key=AIzaSyCMysH7TySEgdbvRoCLoZk8uFF1x_A3uxg',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode ( $fields ) );
$result = curl_exec( $ch );
curl_close ( $ch );
//Apple Push notification
// This this a fake device id:
$deviceToken = "5d8b3165fc03645d23c2651badd69f07d028aee801acf1d25a4d230882156755";
// fake password:
$passphrase = '123456789';
$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' => '1'
);
// 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);
}
include 'index.php';
?>
I add the ios device token to the $deviceToken and the android device token to the $regi and it will send to the phones. The only part I have changed is the Apple push notification part which didn't work. Before I changed it the apple push notification was using the $dev variable and android was using $regi. Now I know that the device tokens are being sent to the server when the app is launched so my guess is that they are not being stored in the variables. Is there any problems you can see and how can I print them out to see if they are empty?
Thanks
I figured this out a while ago and though I would share for anyone else that is struggling.
<?php
include 'conn.php';
if ( $_REQUEST['key'] == 'notification' ) {
$message = $_REQUEST['text'];
$text = mysql_real_escape_string( $_REQUEST['text'] );
$start = $_REQUEST['start'];
$end = $_REQUEST['end'];
$date = date( "Ymd", strtotime( $_REQUEST['date'] ) );
$callus = $_REQUEST['callus'];
$in = "INSERT INTO `notifications` (`date`, `start_time`, `end_time`, `text`, `call_us`) VALUES ('$date', '$start', '$end', '$text', '$callus');";
mysql_query($in);
include 'notifications.php';
}
else {
$message = mysql_real_escape_string( $_REQUEST['text'] );
$time = date( 'Y-m-d H:i:s' );
$in = "INSERT INTO `alerts` (`text`, `time`) VALUES ('$message', '$time');";
mysql_query( $in );
$sel="SELECT * FROM `users` GROUP by device_token";
$rs = mysql_query( $sel ) or die('');
if ( mysql_num_rows( $rs ) != 0 ) {
while( $row=mysql_fetch_array( $rs ) ) {
$regi = array();
$regi[] = $row['device_token'];
$dev = $row['device_token'];
if( strlen ( $dev ) > 65 ) {
$regis[] = $row['device_token'];
}
else if ( strlen ($dev) > 25 ) {
$ios[] = $dev;
}
}
}
$deviceToken=$_REQUEST['device'];
$json=json_decode($deviceToken);
//google Push notification
// API access key from Google API's Console
define( 'API_ACCESS_KEY', 'AIzaSyCMysH7TySEgdbvRoCLoZk8uFF1x_A3uxg' );
//build the message
$fields = array
(
'registration_ids' => $regis,
'data' => array( 'message'=> $message,'count'=>1 )
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
//Apple Push notification
// Certificate password:
$passphrase = '123456789';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ckStudioeast.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);
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'badge' => '1'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Loop though device tokens
foreach($ios as $dev) {
if($dev!=''){
// 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));
}
}
if (!$result)
echo 'Message not delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
include 'index.php';
}
?>
The problem seemed to be that the app was sending the database a development device token so I updated my didRegisterForRemoteNotificationsWithDeviceToken function in xcode to this:
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
#ifdef DEBUG
// Update the database with our development device token
NSLog(@"IN DEVELOPMENT MODE!!!!!!!");
#else
// Update the database with our production device token
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"content---%@", token);
kSetValueForKey(@"device_token", token);
[self updateDeviceToken:token];
#endif
}
Also I found that if a user denies the request to allow push notifications that it send a device token of 0 to my database, which if used stops the notifications from being sent. So where I'm sorting my device tokens in my php file I added more logic to ignore all the tokens that where just 0.
I simply just checked that the length was more than 25 characters before I added it to my $ios array, where as before I wasn't
Old code:
if( strlen ( $dev ) > 65 ) {
$regis[] = $row['device_token'];
} else {
$ios[] = $dev;
}
New code:
if( strlen ( $dev ) > 65 ) {
$regis[] = $row['device_token'];
} else if ( strlen ($dev) > 25 ) {
$ios[] = $dev;
}
One of the main problems I found is if you send a device token to apples production push notification server that isn't a valid production device token, it just doesn't send the notification to any device. This is why I It wasn't working and I have added in the extra logic to my php code and Objective-c code to filter out all the invalid device tokens.
Hope this helps people.
while ($row = mysql_fetch_array($result1)) //fetch datafrom loop
{
$dev = $row["device_token"]; // your devide token
if( strlen ( $dev ) > 65 ) { // for android
$regis[] = $row['device_token'];
}
else
{
$ios[] = $row['device_token']; // for ios
}
}
foreach($regis as $dev1) {
$id=$dev1;
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array (
'to' => $id,
'notification' => array (
"body" => $mess,
"icon" =>"icon",
"sound"=> ""
)
);
$fields = json_encode ( $fields );
$headers = array (
'Authorization: key=' . "---your key---",
'Content-Type: application/json'
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, true );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $fields );
$result = curl_exec ( $ch );
}
foreach($ios as $dev) {
if($dev!='')
{
$deviceToken=$dev;
$passphrase = '';
// Put your alert message here:
$message = $mess;
$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);
// Create the payload body
$body['aps'] = array(
'alert' => array(
'body' => $message,
),
'badge' => +1,
'sound' => 'default',
'content-available' => '1',
);
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));
}
}
if (!$result)
{
?>
<script>
alert("Push notification is successfully sent");
</script>
<?php
}
else
{
?>
<script>
alert("Mesaage is successfully sent");
</script>
<?php
}
curl_close ( $ch );
fclose($fp);
}