I have a little problem: If I send a notification to my android device via php from the web, a notification gets built, but isn't vibrating outside the app. It is only vibrating while I am inside the app.
Here are my codes:
PHP:
function send_notification ($token, $message, $Raum, $Notruf){
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array('to' => $token, 'notification' => array('body' => "Raum ".$Raum.", Notruf ".$Notruf), 'data' => array ('message' => $message));
$headers = array ('Authorization:key = (HERE IS MY AUTH 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_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result == FALSE) {
die ('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
$sql = 'SELECT token FROM devices as d, Sani as s WHERE d.sean = s.sean AND s.Status!=0';
$result = mysqli_query($db, $sql);
$tokens = array ();
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)){
$tokens[] = $row["token"];
}
}
mysqli_close($db);
$message = array ("message" => "Raum ".$Raum.", Notruf ".$Notruf);
for ($i = 0; $i < count($tokens); ++$i) {
$message_status = send_notification ($tokens[$i], $message, $Raum, $Notruf);
echo $message_status;
}
My Android Notification Code:
public class MyNotificationManager {
private Context mCtx;
private static MyNotificationManager mInstance;
private MyNotificationManager(Context context){
mCtx=context;
}
public static synchronized MyNotificationManager getInstance(Context context){
if(mInstance== null){
mInstance = new MyNotificationManager(context);
}
return mInstance;
}
public void displayNotification(String title, String body){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mCtx, Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.sirenlight)
.setContentTitle(title)
.setVibrate(new long[] {0, 5000, 100, 5000, 100, 5000, 100, 5000, 100, 5000, 100, 5000})
.setContentText(body);
Intent intent = new Intent(mCtx, EinsatzInterface.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mCtx, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager = (NotificationManager) mCtx.getSystemService(Context.NOTIFICATION_SERVICE);
if(mNotificationManager!=null){
mNotificationManager.notify(1, mBuilder.build());
}
}
}
I couldn't get any fixes online, so I am asking here.
How I said, the vibration is working, but only inside the app. If I close it, even without stopping the process, it only shows the notification and doesn't vibrate or show the correct logo.
When inside the app the notification looks like this (vibrating and icon showing):
When outside the app the notification looks like this (not vibrating and icon not showing):
Related
I'm currently implement firebase cloud messaging to receive notification from mysql database when a condition in table row data is met. What i currently have right now is just a simple push notification when i enter a php file using browser. Below is all my coding.
push_notification.php
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message
);
$headers = array(
'Authorization:key = AAAA0********* ',
'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_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
$conn = mysqli_connect("localhost", "root", "", "fcm");
$sql = " Select fcm_token From fcm_notification";
$result = mysqli_query($conn, $sql);
$tokens = array();
if(mysqli_num_rows($result) > 0 ){
while ($row = mysqli_fetch_assoc($result)) {
$tokens[] = $row["fcm_token"];
}
}
mysqli_close($conn);
$message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
MyFirebaseInstanceIDService.java
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
registerToken(token);
}
private void registerToken(String token) {
OkHttpClient client = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("fcm_token", token)
.build();
Request request = new Request.Builder()
.url("http://192.168.1.5/fcm/register.php")
.post(body)
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
showNotification(remoteMessage.getData().get("message"));
}
private void showNotification(String message) {
Intent i = new Intent(this,MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setContentTitle("FCM Test")
.setContentText(message)
.setLights(Color.BLUE,1,1)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
}
fcm_token table
token
Right now how do i able to receive a notification from mysql database when a user balance is less than 0.5 and this is my user table
user table
You have set up your system good enough to do the basic thing of sending and receiving the Push Notification.
From what I get is, you are having a system where you want to send a push notification when the user balance is less than 0.5. You can write code in PHP where there is balance manipulation to check user's current balance and send the Push Notification.
OR
You can set up a cron to check balance of each user and send them notification if there balance is less than 0.5
I want to send notification using FCM. I have added project to Firebase Console got the API key and device_token.
Now I am sending a push notification from PHP, I get the message in logs, but it's showing some exception. I have followed this tutorial.
PHP script function:
function sendInvite()
{
$database = new Database(ContactsConstants::DBHOST, ContactsConstants::DBUSER, ContactsConstants::DBPASS, ContactsConstants::DBNAME);
$dbConnection = $database->getDB();
$stmt = $dbConnection->prepare("select * from Invitation where user_name =? and sender_id = ?");
$stmt->execute(array($this->user_name,$this->sender_id));
$rows = $stmt->rowCount();
if ($rows > 0) {
$response = array("status" => -3, "message" => "Invitation exists.", "user_name" => $this->user_name);
return $response;
}
$this->date = "";
$this->invitee_no = "";
$this->status = "0";
$this->contact_id = 0;
$stmt = $dbConnection->prepare("insert into Invitation(sender_id,date,invitee_no,status,user_name,contact_id) values(?,?,?,?,?,?)");
$stmt->execute(array($this->sender_id, $this->date, $this->invitee_no, $this->status, $this->user_name,$this->contact_id));
$rows = $stmt->rowCount();
$Id = $dbConnection->lastInsertId();
$stmt = $dbConnection->prepare("Select device_id from Users where user_id =?");
$stmt->execute(array($this->sender_id));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$token = $result["device_id"];
$server_key = 'AIzaJaThyLm-PbdYurj-bYQQc';
$fields = array();
$fields['data'] = $data;
if(is_array($token)){
$fields['registration_ids'] = $token;
}else{
$fields['to'] = $token;
}
//header with content_type api key
$headers = array(
'Content-Type:application/json',
'Authorization:key='.$server_key
);
$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_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('FCM Send Error: ' . curl_error($ch));
}
curl_close($ch);
echo $result;*/
$message = 'Hi,add me to your unique contact list and you never need to update any changes anymore!';
$data = array("message"=>"Hi,add me to your unique contact list and you never need to update any changes anymore!","title"=>"You got an Invitation.");
if (!empty($token)) {
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'to' => $token,
'data' => $data
);
$fields = json_encode($fields);
$headers = array(
'Authorization: key=' . "AIzaSyBGwwJaThyLm-PhvgcbdYurj-bYQQ7XmCc",
'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, $fields);
$result = curl_exec($ch);
echo $result;
curl_close($ch);
}
$stmt = $dbConnection->prepare("select * from Invitation where invitation_id=?");
$stmt->execute(array($Id));
$invitation = $stmt->fetch(PDO::FETCH_ASSOC);
if ($rows < 1) {
$response = array("status" => -1, "message" => "Failed to send Invitation., unknown reason");
return $response;
} else {
$response = array("status" => 1, "message" => "Invitation sent.", "Invitation:" => $invitation);
return $response;
}
}
MessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
public static final String PUSH_NOTIFICATION = "pushNotification";
private NotificationUtils notificationUtils;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage == null)
return;
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getNotification().getBody());
}
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
private void handleNotification(String message) {
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
}else{
// If the app is in background, firebase itself handles the notification
}
}
private void handleDataMessage(JSONObject json) {
Log.e(TAG, "push json: " + json.toString());
try {
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
// boolean isBackground = data.getBoolean("is_background");
String imageUrl = data.getString("image");
String timestamp = data.getString("timestamp");
// JSONObject payload = data.getJSONObject("payload");
Log.e(TAG, "title: " + title);
Log.e(TAG, "message: " + message);
// Log.e(TAG, "isBackground: " + isBackground);
// Log.e(TAG, "payload: " + payload.toString());
Log.e(TAG, "imageUrl: " + imageUrl);
Log.e(TAG, "timestamp: " + timestamp);
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
} else {
// app is in background, show the notification in notification tray
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("message", message);
// check for image attachment
if (TextUtils.isEmpty(imageUrl)) {
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
} else {
// image is present, show notification with image
showNotificationMessageWithBigImage(getApplicationContext(), title, message, timestamp, resultIntent, imageUrl);
}
}
} catch (JSONException e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
/**
* Showing notification with text and image
*/
private void showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);
}
}
Exception:
E/MyFirebaseMessagingService: From: 321839166342
10-12 11:49:14.744 21621-27002/com.example.siddhi.contactsapp E/MyFirebaseMessagingService: Data Payload: {title=You got an Invitation., message=Hi,add me to your unique contact list and you never need to update any changes anymore!}
10-12 11:49:14.745 21621-27002/com.example.siddhi.contactsapp E/MyFirebaseMessagingService: Exception: Unterminated object at character 12 of {title=You got an Invitation., message=Hi,add me to your unique contact list and you never need to update any changes anymore!}
What's going wrong here?
I also want to make notification responsive. As it should have Accept and Reject option and on click of that, I want to perform an action.
Can anyone help with this please? Thank you..
Try with below example with manually device token pass
<?php
define("ANDROID_PUSHNOTIFICATION_API_KEY",'API_KEY_HERE'); // FCM
define("ANDROID_PUSHNOTIFICATION_URL",'https://fcm.googleapis.com/fcm/send'); // FCM
function push_android($devicetoken,$param){
$apiKey = ANDROID_PUSHNOTIFICATION_API_KEY; //demo
$registrationIDs[] = $devicetoken;
// Set POST variables
$url = ANDROID_PUSHNOTIFICATION_URL;
$fields = array(
'registration_ids' => $registrationIDs,
'data' => $param,
);
$headers = array(
'Au
thorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Open connection
$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 );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields ) );
// Execute post
$result = curl_exec($ch);
//print_r($result); exit;
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}else{
//echo "success notification";
//print_r($result);
//echo curl_error($ch);
}
// Close connection
curl_close($ch);
return $result;
} ?>
Hope this will help!
This exception is thrown when you have used special characters.Try removing the , before the fullstop.
And to make it responsive like adding accept and reject you can look into the firebase documentation
this is a good explanation
I'm trying to send notifications to my Windows Phone 8 app using an authenticated server, but I'm getting a 401 error whenever a notification is tried to be sent.
I've been following the instructions on the MSDN pages, namely http://msdn.microsoft.com/library/windows/apps/ff941099(v=vs.105).aspx where it says The Key-Usage value of the TLS certificate must be set to include client authentication. I've no idea what this means though and searching online doesn't give me any clues either.
It could be that, that is incorrect or it could be my code so that is shown below.
VB.NET CODE:
Private Async Sub ApplicationBarPin_Click(sender As Object, e As EventArgs)
' Holds the push channel that is created or found.
Dim pushChannel As HttpNotificationChannel
' The name of our push channel.
Dim channelName As String = "WindowsPhoneTrainTileNotification"
' Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName)
' If the channel was not found, then create a new connection to the push service.
If pushChannel Is Nothing Then
pushChannel = New HttpNotificationChannel(channelName, "redsquirrelsoftware.co.uk")
uri_timer = New DispatcherTimer
uri_timer.Interval = TimeSpan.FromSeconds(5)
AddHandler uri_timer.Tick, AddressOf UriTimerTick
uri_timer.Start()
' Register for all the events before attempting to open the channel.
AddHandler pushChannel.ChannelUriUpdated, AddressOf PushChannel_TileChannelUriUpdated
AddHandler pushChannel.ErrorOccurred, AddressOf PushChannel_TileErrorOccurred
pushChannel.Open()
pushChannel.BindToShellTile()
Else
' The channel was already open, so just register for all the events.
AddHandler pushChannel.ChannelUriUpdated, AddressOf PushChannel_TileChannelUriUpdated
AddHandler pushChannel.ErrorOccurred, AddressOf PushChannel_TileErrorOccurred
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(pushChannel.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
End If
ShellTile.Create(New Uri("/Route.xaml?scheduleId=" & scheduleId, UriKind.Relative), secondaryTile, True) 'Create SecondaryTile and pass querystring to navigation url.
Catch ex As Exception
End Try
End If
End Sub
Private Async Sub PushChannel_TileChannelUriUpdated(sender As Object, e As NotificationChannelUriEventArgs)
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(e.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
End Sub
Private Sub PushChannel_TileErrorOccurred(sender As Object, e As NotificationChannelErrorEventArgs)
MessageBox.Show("Error creating live tile, please try again")
End Sub
Private Async Sub UriTimerTick(sender As Object, e As EventArgs)
Try
If pushChannel.ChannelUri IsNot Nothing Then
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(pushChannel.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
uri_timer.Stop()
End If
Catch ex As Exception
End Try
End Sub
That works as expected and the URI is stored in my database (starting with HTTPS, and doesn't contain throttledthirdparty in the URI either, suggesting that this code works).
train_movements.php:
<?php
include 'WindowsPhoneTilePush.php';
$WPN = new WPN($packageSID, $clientSecret);
$xml_data = $WPN->build_tile_xml($sched_id, strtoupper($loc), "$eventTypeStr $dt (". strtolower($variation_status) . ")");
$WPNResponse = $WPN->post_tile($uri, $xml_data);
if($WPNResponse->error == true) {
$my_file = $logFile;
$handle = fopen($my_file, 'a') or die('Cannot open file: '.$my_file);
$data = $WPNResponse->httpCode . ":" . $WPNResponse->message . "\n";
fwrite($handle, $data);
}
?>
WindowsPhoneTilePush.php: (adapted from here)
<?php
class WPNTypesEnum{
const Toast = 'wns/toast';
const Badge = 'wns/badge';
const Tile = 'wns/tile';
const Raw = 'wns/raw';
}
class WPNResponse{
public $message = '';
public $error = false;
public $httpCode = '';
function __construct($message, $httpCode, $error = false){
$this->message = $message;
$this->httpCode = $httpCode;
$this->error = $error;
}
}
class WPN{
private $access_token = '';
private $sid = '';
private $secret = '';
function __construct($sid, $secret){
$this->sid = $sid;
$this->secret = $secret;
}
private function get_access_token(){
if($this->access_token != ''){
return;
}
$str = "grant_type=client_credentials&client_id=$this->sid&client_secret=$this->secret&scope=notify.windows.com";
$url = "https://login.live.com/accesstoken.srf";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "$str");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output);
if(isset($output->error)){
throw new Exception($output->error_description);
}
$this->access_token = $output->access_token;
}
public function build_tile_xml($tile_nav_uri, $wide2, $wide3){
$msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
"<wp:Notification xmlns:wp=\"WPNotification\" Version=\"2.0\">" .
"<wp:Tile Id=\"/Route.xaml?scheduleId=$tile_nav_uri\" Template=\"IconicTile\">" .
//"<wp:SmallIconImage>$image_url_small</wp:SmallIconImage>" .
//"<wp:IconImage>$image_url_large</wp:IconImage>" .
//"<wp:WideContent1>$wide1</wp:WideContent1>" .
"<wp:WideContent2>$wide2</wp:WideContent2>" .
"<wp:WideContent3>$wide3</wp:WideContent3>" .
//"<wp:Count>$count</wp:Count>" .
//"<wp:Title>$title</wp:Title>" .
//"<wp:BackgroundColor>#00FFFFFF</wp:BackgroundColor>" .
"</wp:Tile>" .
"</wp:Notification>";
return $msg;
}
public function post_tile($uri, $xml_data, $type = WPNTypesEnum::Tile, $tileTag = '', $count = 0){
if($this->access_token == ''){
$this->get_access_token();
}
$headers = array('Content-Type: text/xml', "Content-Length: " . strlen($xml_data), "X-WNS-Type: $type", "Authorization: Bearer $this->access_token");
if($tileTag != ''){
array_push($headers, "X-WNS-Tag: $tileTag");
}
$ch = curl_init($uri);
# Tiles: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868263.aspx
# http://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx
curl_setopt($ch, CURLOPT_CAPATH, "/var/www/clients/client1/web1/ssl/");
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$response = curl_getinfo( $ch );
curl_close($ch);
$code = $response['http_code'];
if($code == 200){
return new WPNResponse('Successfully sent message', $code);
}
else if($code == 401){
$my_file = '/var/log/WPNotify.txt';
$handle = fopen($my_file, 'a') or die('Cannot open file: '.$my_file);
$data = date("d-M-y H:i:s:") . "401 Authorisation Error:" . $this->access_token . "\n";
fwrite($handle, $data);
if($count == 10) {
exit;
}
$this->access_token = '';
return $this->post_tile($uri, $xml_data, $type, $tileTag, $count++);
}
else if($code == 410 || $code == 404){
return new WPNResponse('Expired or invalid URI', $code, true);
}
else{
return new WPNResponse('Unknown error while sending message', $code, true);
}
}
}
?>
There could be an error in my code, or it could be that I'm not setting up the backend stuff correctly (most of the MSDN docs are aimed at Windows Servers and .aspx, so I've tried to replicate those instructions but could have gone wrong somewhere along the line!).
If anyone can help in either fixing errors in the code, or with the client authentication for the SSL certificate it would be much appreciated!
Thanks,
Jake
take a look at
Windows Notifications Service: 401 Invalid Token when trying to create a Toast notification in PHP
invalid-token-when-trying-to-create-a-toast-n
make sure you're sending package SID of your app as the 'client_id' parameter instead of your app's client_id when requesting access token.
This is really confusing ,doing both are able to get access_token from Microsoft's server, but only the token requested with you package SID won't give you 401 error when sending toast notification.
I am working for a few days on an app which is based on real time communication between devices. In the past I was using GCM for notifications via POST methods using the OkHttp library. So far, so good.
But when it comes to real time communication I face a lot of issues around connection timeouts or even mesages which are never delivered.
My implementation is simple. First the user from his phone sends a request via POST and my online server to another phone (driver) which than confirms the request and replies back to the sender via another POST method and via the online server.
But only about 80% of the replies get back to the user, or they arrive after several minutes.
Can the problem be in my implementation?? Or should I switch to GCM Cloud Connection Server (XMPP)??
I am in serious need of some suggestions, please light me up.
Regards.
Php implementation:
<?php
include_once '../includes/db_connect.php';
// Query database for driver's regId
if(!empty($_POST["str"])) {
$sql = "SELECT * FROM DRIVERS WHERE NAME = '$_POST[driver]' " ;
$result = mysqli_query($mysqli, $sql);
$row = mysqli_fetch_assoc($result);
$gcmRegID = $row["REGID"];
$clientId = $_POST["clientId"];
$street = $_POST["str"];
$number = $_POST["nr"];
$bloc = $_POST["bl"];
$scara = $_POST["sc"];
if (isset($gcmRegID)) {
$gcmRegIds = array($gcmRegID);
$message = array("jstr" => $street, "jnr" => $number, "jbl" => $bloc, "jsc" => $scara, "jId" => $clientId);
$pushStatus = sendPushNotificationToGCM($gcmRegIds, $message);
}
}
// Reply to the client if available or not
if(!empty($_POST["response"])) {
$gcmRegID = $_POST["clientId"];
$response = $_POST["response"];
$gcmRegIds = array($gcmRegID);
$message = array("jresp" => $response);
$pushStatus = sendPushNotificationToGCM($gcmRegIds, $message);
}
//generic php function to send GCM push notification
function sendPushNotificationToGCM($registatoin_ids, $message) {
//Google cloud messaging GCM-API url
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registatoin_ids,
'data' => $message
);
// Google Cloud Messaging GCM API Key
define("GOOGLE_API_KEY", "**************");
$headers = array(
'Authorization: key=' . GOOGLE_API_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_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
?>
Order Activity - for sending request to the driver
public void callDriver (View view){
MySendTask send = new MySendTask();
send.execute();
Toast.makeText(getApplicationContext(), "Button Pressed :)",
Toast.LENGTH_SHORT).show();
}
private class MySendTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
progressb.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
String str = streetName.getText().toString();
String nr = streetNr.getText().toString();
String bl = bloc.getText().toString();
String sc = scara.getText().toString();
SharedPreferences prefs = getSharedPreferences("Notification", MODE_PRIVATE);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
try {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(10000, TimeUnit.MILLISECONDS);
RequestBody formBody = new FormEncodingBuilder()
.add("clientId", registrationId)
.add("driver", "Peter Bleul")
.add("str", str)
.add("nr", nr)
.add("bl", bl)
.add("sc", sc)
.build();
Request request = new Request.Builder()
.url("http://edmon.net/andr/index.php")
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(), "Order successfully sent!",
Toast.LENGTH_SHORT).show();
progressb.setVisibility(View.INVISIBLE);
}
}
}
GCM does not guarantee message delivery. GCM also throttles message delivery which can often result in significant delays. For more details on this topic see: http://developer.android.com/google/gcm/adv.html (goto the "Lifetime of a Message" section").
I have experienced issues similar to yours in the app I work on.
Thus it does not seem that GCM is a good candidate for real-time communication.
I have found an excellent example, with great sample applications explaining the process wonderfully, thanks to: Antoine Cambell
I reccomend it for everyone seaking answers for a simmilar application.
function tratar_hotmail(){
$client_id = '0xxxxxxxxxxxxxxxx2';
$client_secret = 'Wyyyyyyyyyyyyyyyyyp';
$redirect_uri = 'http://example.com/';
$auth_code = $_GET["code"];
$fields=array(
'code'=> urlencode($auth_code),
'client_id'=> urlencode($client_id),
'client_secret'=> urlencode($client_secret),
'redirect_uri'=> urlencode($redirect_uri),
'grant_type'=> urlencode('authorization_code')
);
$post = '';
foreach($fields as $key=>$value) { $post .= $key.'='.$value.'&'; }
$post = rtrim($post,'&');
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,'https://login.live.com/oauth20_token.srf');
curl_setopt($curl,CURLOPT_POST,5);
curl_setopt($curl,CURLOPT_POSTFIELDS,$post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
$result = curl_exec($curl);
curl_close($curl);
$response = json_decode($result);
$accesstoken = $response->access_token;
$url = 'https://apis.live.net/v5.0/me/contacts?access_token='.$accesstoken.'';
$xmlresponse = curl_file_get_contents($url);
echo $xmlresponse;
$xml = json_decode($xmlresponse, true);
foreach($xml['data'] as $emails)
{
echo $emails['name'];
}
}
which outputs:
{ "error": { "code": "request_token_invalid", "message": "The access token isn't valid." } }
How can I get the request_access_token?
-EDIT-
Forgot the curl function
function curl_file_get_contents($url)
{
$curl = curl_init();
$userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)';
curl_setopt($curl,CURLOPT_URL,$url); //The URL to fetch. This can also be set when initializing a session with curl_init().
curl_setopt($curl,CURLOPT_RETURNTRANSFER,TRUE); //TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5); //The number of seconds to wait while trying to connect.
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); //The contents of the "User-Agent: " header to be used in a HTTP request.
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); //To follow any "Location: " header that the server sends as part of the HTTP header.
curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE); //To automatically set the Referer: field in requests where it follows a Location: redirect.
curl_setopt($curl, CURLOPT_TIMEOUT, 10); //The maximum number of seconds to allow cURL functions to execute.
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); //To stop cURL from verifying the peer's certificate.
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
$contents = curl_exec($curl);
curl_close($curl);
return $contents;
}
Here's a class I've just thrown together for talking to the API:
<?php
// Note: the test script below assumes this is in a
// file called class.liverestapiconsumer.php
class LiveRESTAPIConsumer {
protected $accessTokenURI = 'https://login.live.com/oauth20_token.srf';
protected $restAPIBaseURI = 'https://apis.live.net/v5.0';
protected $appId;
protected $appSecret;
protected $accessToken;
protected $accessTokenExpires;
public function __construct($appId = NULL, $appSecret = NULL, $accessToken = NULL, $accessTokenExpires = NULL) {
$this->setAppId($appId);
$this->setAppSecret($appSecret);
$this->setAccessToken($accessToken);
$this->setAccessTokenExpires($accessTokenExpires);
}
public function getAppId() {
return $this->appId;
}
public function setAppId($appId) {
$this->appId = $appId;
}
public function getAppSecret() {
return $this->appSecret;
}
public function setAppSecret($appSecret) {
$this->appSecret = $appSecret;
}
public function getAccessToken() {
return $this->accessToken;
}
public function setAccessToken($accessToken) {
$this->accessToken = $accessToken;
}
public function getAccessTokenExpires() {
return $this->accessTokenExpires;
}
public function setAccessTokenExpires($accessTokenExpires) {
$this->accessTokenExpires = $accessTokenExpires;
}
public function accessTokenIsExpired() {
return $this->accessTokenExpires <= time();
}
public function fetchAccessToken($code, $redirectURI) {
if (!isset($code, $redirectURI, $this->appId, $this->appSecret)) {
throw new \Exception('Cannot fetch access token without an authorization code, redirect URI, application id and application secret');
}
$postFields = array(
'client_id' => $this->appId,
'client_secret' => $this->appSecret,
'code' => $code,
'redirect_uri' => $redirectURI,
'grant_type' => 'authorization_code'
);
$bodyData = http_build_query($postFields);
$headers = array(
'Content-Type: application/x-www-form-urlencoded'
);
$ch = curl_init($this->accessTokenURI);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
} else if (!isset($responseObj->access_token)) {
throw new \Exception('Live API did not return an access token; error: '.$responseObj->error_description);
}
$this->setAccessToken($responseObj->access_token);
$this->setAccessTokenExpires(time() + $responseObj->expires_in);
}
protected function normalizeAPIPath($path) {
return $path[0] == '/' ? $path : '/'.$path;
}
public function apiCall($method, $path, array $params = array(), $data = NULL) {
if (!isset($this->accessToken)) {
throw new \Exception('Cannot make API requests without an access token');
} else if ($this->accessTokenIsExpired()) {
throw new \Exception('The currently defined access token has expired');
}
$ch = curl_init();
$url = $this->restAPIBaseURI.$this->normalizeAPIPath($path);
if ($params) {
$url .= '?'.http_build_query($params);
}
curl_setopt($ch, CURLOPT_URL, $url);
$method = trim(strtoupper($method));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
$headers = array();
$headers[] = 'Authorization: Bearer '.$this->accessToken;
if ((array) $data) {
$bodyData = json_encode($data);
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
}
return $responseObj;
}
}
...and the test script (yes, I am fully aware that my HTML skills are terrible - I don't write very much of it):
<?php
session_start();
require 'class.liverestapiconsumer.php';
// Your details as assigned by Microsoft
$appId = '<your client id>';
$appSecret = '<your client secret>';
// The public (internet) URL of this script
$localUrl = 'http://example.com/path/to/file.php';
// Work out whether we have a valid access token or not
$haveAccessToken = FALSE;
$accessTokenExpiresIn = 'N/A';
if (isset($_SESSION['accessToken'])) {
$now = time();
$haveAccessToken = $now < $_SESSION['accessTokenExpires'];
$accessTokenExpiresIn = ($_SESSION['accessTokenExpires'] - $now).' seconds';
if (!$haveAccessToken || isset($_GET['destroy'])) {
unset($_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
}
if (isset($_GET['destroy'])) {
header('HTTP/1.1 302 Found');
header('Location: '.$localUrl);
}
}
function parse_body_data($str) {
$result = array();
$items = preg_split('/[\r\n]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($items as $item) {
$item = explode(':', $item, 2);
if (count($item) !== 2) {
return FALSE;
}
$result[trim($item[0])] = trim($item[1]);
}
return $result;
}
?>
<html>
<head>
<title>Live API Test</title>
<style>
div.label {
margin-top: 10px;
}
</style>
</head>
<body>
<div>Do we have an access token? <b><?php echo $haveAccessToken ? 'Yes <sup>(destroy)</sup>' : 'No'; ?></b> (Expires: <?php echo $accessTokenExpiresIn; ?>)</div>
<?php
if (isset($_POST['path'])) { // get something from the API
do { // do-while so we can easily break out of it on error
$client = new LiveRESTAPIConsumer($appId, $appSecret, $_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
$path = $_POST['path'];
$method = $_POST['method'];
$paramStr = trim($_POST['params']);
$params = array();
if (!empty($paramStr)) {
parse_str($paramStr, $params);
}
if (($body = parse_body_data($_POST['body'])) === FALSE) {
echo "<div>Error: Body data invalid</div>";
break;
}
try {
$result = $client->apiCall($method, $path, $params, $body);
// The class returns the response data decoded to an object, so json_encode() it again for display
echo '
Result:
<pre>'.json_encode($result, JSON_PRETTY_PRINT).'</pre>
';
} catch (\Exception $e) {
echo "<div>Exception: ".$e->getMessage()."</div>";
break;
}
} while(FALSE);
echo '<div>Back</div>';
} else if (isset($_GET['code'])) { // handle redirect from live API
try {
$client = new LiveRESTAPIConsumer($appId, $appSecret);
$client->fetchAccessToken($_GET['code'], $localUrl);
$_SESSION['accessToken'] = $client->getAccessToken();
$_SESSION['accessTokenExpires'] = $client->getAccessTokenExpires();
echo '
<div>Successfully retrieved access token: '.$_SESSION['accessToken'].'</div>
<div>Go to form</div>
';
} catch (\Exception $e) {
echo '
<div>Exception: '.$e->getMessage().'</div>
<div>Back</div>
';
}
} else if ($haveAccessToken) { // Output form
echo '
<form action="'.$localUrl.'" method="post">
<div>
<div class="label">API Path</div>
<div><input name="path" type="text"></div>
</div>
<div>
<div class="label">Parameters (query string)</div>
<div><input name="params" type="text"></div>
</div>
<div>
<div class="label">Method</div>
<div>
<select name="method">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
<option value="MOVE">MOVE</option>
<option value="COPY">COPY</option>
</select>
</div>
</div>
<div>
<div class="label">Body Data (key: value, newline separated)</div>
<div><textarea name="body" rows="10" cols="40"></textarea></div>
</div>
<input type="submit" value="Send Request">
</form>
API Reference
';
} else { // Don't have access token yet
$opts = array(
'client_id' => $appId,
'scope' => 'wl.basic',
'response_type' => 'code',
'redirect_uri' => $localUrl
);
echo '<div>Get access token</div>';
}
?>
</body>
</html>
All the parts that I think need explanation are commented. If you have any questions let me know.
Note that I haven't extensively tested the class, and it may be lacking when it comes to the more advanced API functionality. Seems to work fairly well for simple contact manipulation though.
In addition to the answer of DaveRandom and the comment of saveATcode: You should submit the redirect url given in $localUrl as a valid redirect url at account live application. They must be exactly the same or else you will get the 'The provided value for the input parameter 'redirect_uri' is not valid....' message. I just mentioned it because mine had a typo and i experienced the same error.