I try to implement FCM in my app but I have a problem. Whenever I send the notification, instead of calling my custom code, it just show the default notification. What am I doing wrong?
Those are the services:
<service
android:name="com.backgroundws.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name="com.backgroundws.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
And this is my Java code:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("MyFirebaseMessaging", "GotMessage");
WSListener.sendEvent(this, "Push");
}
}
And I see this in the logcat when I get the notification on the device:
I/SendBroadcastPermission: action:com.google.android.gms.gcm.ACTION_SCHEDULE, mPermissionType:0
I/SendBroadcastPermission: action:com.google.android.gms.gcm.ACTION_SCHEDULE, mPermissionType:0
This is how I send the notifications:
function send_gcm_notify($reg_id, $message, $url, $key) {
$fields = array(
'to' => $reg_id ,
'priority' => "high",
"notification" => array("body"=>$message),
'data' => array( "url"=> $url)
);
$headers = array(
'Content-Type: application/json',
'Authorization: key=' . $key
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://fcm.googleapis.com/fcm/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);
if ($result === FALSE) {
//die('Problem occurred: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
Of course I tested and the path to the service is correct.
If you want your server's content with notification in both modes(Background and Foreground), You have to send payload from server inside 'data' only.
For more you can refer here How to handle Android FCM Messages when application is in Background with data payload?
Related
The response says the notification was successful, but it has not been displayed on my Android phone.
Response:
{"multicast_id":6696507350475373329,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1486651908616097%298b4204f9fd7ecd"}]}
PHP (src: https://gist.github.com/prime31/5675017)
<?php
// API access key from Google API's Console
define( 'API_ACCESS_KEY', ThisIsMyKey);
$registrationIds = array( $_GET['id'] );
// prep the bundle
$msg = array
(
'message' => 'TestNachricht',
'title' => 'TestTitel',
'subtitle' => 'TestSubTitle',
'vibrate' => 1,
'sound' => 1,
'priority' => 10,
'smallIcon' => 'small_icon'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/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 );
echo $result;
Android:
I did not add onReceive-Methods because I am able to broadcast notifcations and send notifications to specific devices (RegistrationId) using FireBase Console. All of them are displayed on my device.
private String getRegistrationId() {
return FirebaseInstanceId.getInstance().getToken();
}
<service android:name=".MyFirebaseInstanceIdService" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
When sending push notifications via the Firebase Console, it is classified as a notification message payload. By default, Android will handle this message when your app is in background.
In your PHP code, you're sending a data-only message payload, which can be handled in Android by implementing onMessageReceived().
If you still prefer not to implement onMessageReceived(), you'll have to modify your PHP side code to use a notification-only message payload.
Note that the notification payload only has predefined parameters that can be used.
More details here:
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json
I am trying to use cordova fcm plugin on Android to implement the data sent by Firebase Cloud Messaging. I successfully received the notifications, but when I tap them they are not giving the alert I want.
Here is the code used in index.js:
onDeviceReady: function() {
app.receivedEvent('deviceready');
FCMPlugin.onNotification(
function(data){
if(data.wasTapped){
//Notification was received on device tray and tapped by the user.
alert( JSON.stringify(data) );
}else{
//Notification was received in foreground. Maybe the user needs to be notified.
alert( JSON.stringify(data) );
}
},
function(msg){
alert('onNotification callback successfully registered: ' + msg);
},
function(err){
alert('Error registering onNotification callback: ' + err);
}
);
},
And here is the php code I used to send the notification:
function pushAndroidNotification ($productUrl, $message, $deviceToken) {
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => array($deviceToken),
'notification' => array(
"title" => "rBUX",
"body" => $message,
"icon" => "name_of_icon" ),
'data' => array("url" => $productUrl)
);
$jfields = json_encode($fields);
echo "\r\n<br>Post json:".$jfields;
$headers = array(
'Authorization: key = AIzaSyBPRoJ7zgmevPYIzoDweVgNTbmsPBW5ofo',
'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, $jfields);
$result = curl_exec($ch);
if ($result === FALSE) {
echo "\r\n<br>Notify Failed:".curl_error($ch);
die('Curl failed: '.curl_error($ch));
}else{
echo "\r\n<br>Notify passed:".$result;
}
$jresponse = json_decode($result, true);
curl_close($ch);
return $jresponse;
}
But every time I launch the app, I can see the alert "onNotification callback successfully registered: OK", so the FCM plugin is not completely disabled.
I would like to launch the url when I tap on the notification, but for now it appears that I can't even use the data. If anyone knows how to solve this please tell me, and please let me know how to use stringified data to launch the url in cordova inAppBrowser, thank you.
For "cordova-plugin-fcm" plugin, You need to set click_action to FCM_PLUGIN_ACTIVITY in the notification payload part.
I got the following from their website:
{
"notification":{
"title":"Notification title", //Any value
"body":"Notification body", //Any value
"sound":"default", //If you want notification sound
"click_action":"FCM_PLUGIN_ACTIVITY", //Must be present for Android
"icon":"fcm_push_icon" //White icon Android resource
},
"data":{
"param1":"value1", //Any data to be retrieved in the notification callback
"param2":"value2"
},
"to":"/topics/topicExample", //Topic or single device
"priority":"high", //If not set, notification won't be delivered on completely closed iOS app
"restricted_package_name":"" //Optional. Set for application filtering
}
I am developing Firebase push notification using Server API call in Android application.it works perfectly when application is in foreground but when application is not in foreground i am not able to get the push notification.
I am sending JSON data in which header contains Server API key and content type and the value contains data which have body as array. Appreciate any help.
PHP code:
$url = 'https://fcm.googleapis.com/fcm/send';
$fields =array('registration_ids' => $tokens,'data' => $message);
$headers = array('Authorization:key = value','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);?>
Look at my code. Maybe it will help you:
$token = getTokenDevice($dn);
$path_to_firebase_cm = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'to' => $token,
'priority' => 'normal',
'content_available' => true,
'data' => array('type' => $type, 'title' => $title, 'body' => $message)
);
$headers = array(
'Authorization:key='.$server_key,
'Content-Type:application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $path_to_firebase_cm);
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);
curl_close($ch);
I use content_available for iOS devices. That code works for me in Android and iOS when apps are in background.
So you should check your FirebaseMessaging service. Mine looks like this:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Auth auth = new Auth(getApplicationContext());
Map<String, String> data = remoteMessage.getData();
if (auth.isNotificationEnabled(data.get("type"))) {
Log.e(TAG, "data: " + remoteMessage.getData());
sendNotification(data.get("title"), data.get("body"));
}
}
I too felt this was happening in the beginning but then discovered that my Android App was indeed waking up. Unfortunately it was not waking up enough to do what I wanted (send a heartbeat REST message to my Server). So I will answer your question with a question - why did you decide you did not get a push notification ? For me, when I logged messages from within the onMessageReceived ....
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData());
}
It proved the App got woken up each time the Fire Cloud Messaging service sent a message, regardless if the App was in foreground or background.
Other mistakes, I made initially I shall share with you:
I had to make some changes to my Server side to ensure that the Android App onMessageReceived() method was always called even in background mode. My messages were JSON and HTTP and Upstream. My server is written in C#.
In Firebase there are 2 types of payload downstream messaging. (a) Notification and (b) Data. The type depicts how the App behave when receiving messages depend on whether the app is in background or the foreground. Hence I needed (b) Data type payload to meet my requirement. Just add the “data”
I then had to make my messages High Priority rather than normal. I did a load of tests with both normal and high. Normal did not work once the Android App went into Doze mode. I found this reference useful. https://developer.android.com/training/monitoring-device-state/doze-standby.html#support_for_other_use_cases
I'm trying to send a non-collapse message via Google Cloud Messaging. For some reason a new message always replaces the previous one. I've tried to use different collapse-keys with no effect. Also omitting the collapse key does not work. What could be the problem?
This is an example code:
<?php
$ids[] = '<notification registration id of the test phone>';
sendNotification($ids, "test message 1", "key1");
sendNotification($ids, "test message 2", "key2");
function sendNotification($ids, $message, $collapseKey)
{
$apiKey = '<api key here>';
$url = 'https://android.googleapis.com/gcm/send';
$data['title'] = 'AppName';
$data['message'] = $message;
$post['registration_ids'] = $ids;
$post['data'] = $data;
if ($collapseKey) {
$post['collapse_key'] = $collapseKey;
}
$headers = array(
'Authorization: key=' . $apiKey,
'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, json_encode( $post ) );
$result = curl_exec( $ch );
if ( curl_errno( $ch ) )
{
echo 'GCM error: ' . curl_error( $ch );
}
curl_close( $ch );
echo $result;
}
?>
From the GCM collapse key documentation, omitting the collapse-key should prevent replacing the old messages. Unless some of your messages already expired or your devices are not connected.
Also, the NOTIFICATION_ID with notify method call is implemented in your client application, not your service side code. So it should not be mattered if you are using HTTP server. You can refer to this documentation about NOTIFICATION_ID in your client application's broadcast receiver. Also this StackOverflow answer about how to generate unique NOTIFICATION_ID.
I am going to answer my own question.
There are two scenarios:
For instance: you send two messages when your phone is offline (no wifi, no data, turned off)
Background/killed app -
I only get one notification, but actually i get the two data-message
Foreground -
I get the two notification
Please remember not to add "collapse_key" parameter.
Hope this can help anyone else with the same problem.
I have implemented the rest api of payment with paypal in android application using this code
:
if (isset($_POST['paypal_response']) ) {
$json = json_decode( $_POST['paypal_response'], true );
if (isset($json['proof_of_payment']['rest_api']) ) {
echo 'rest api et voila le payment_id : '.$json['proof_of_payment']['rest_api']['payment_id'].'\n';
$http_header_card = array(
'Content-Type:application/json',
'Authorization:Bearer ENxom5Fof1KqAffEsXtxwEDa6E1HTEK__KVdIsaCYF8C'
);
$ch = curl_init();
$get_request = "https://api.sandbox.paypal.com/v1/payments/payment/{".$json['proof_of_payment']['rest_api']['payment_id']."}";
curl_setopt($ch, CURLOPT_URL, $get_request);
curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header_card );
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$html = curl_exec ($ch);
echo $html;
I have also implemeted the verification of proof for adaptive payment (with paypal account)
but this one above, always send me this response :
{"name":"INTERNAL_SERVICE_ERROR","message":"An internal service error has occurred","information_link":"https://api.sandbox.paypal.com/docs/api/#INTERNAL_SERVICE_ERROR"}1
I don't know the reason knowing that I have followed the official documentation here
here is the code of the doc which I have converted to php :
curl https://api.sandbox.paypal.com/v1/payments/payment/PAY-5YK922393D847794YKER7MUI \
-H "Content-Type:application/json" \
-H "Authorization:Bearer ENxom5Fof1KqAffEsXtxwEDa6E1HTEK__KVdIsaCYF8C"
how can I fix this issue
thanks