I'm using Firebase with an Android app (Auth, Database and Notification).
I'm trying to send notification from an external server (in nodejs) so an user can send a notification to another user.
So the android app memorize a list of UserId (the same ids from Firebase Auth) and then send this list to the nodejs server.
With this list, the server contact the url 'https://fcm.googleapis.com/fcm/send', but Firebase returns me a InvalidRegistration because i'm sending a list of userId and not the list of registration token created by firebase notification.
Should I memorize those tokens or there is a way to send notification with the user id ?
(And when I try with a list of tokens, of course it's working.)
var requestData = {
"registration_ids": userIds, //Problem is here
"data": {
"message": "A message"
}
};
request({
url: "https://fcm.googleapis.com/fcm/send",
method: "POST",
json: true,
headers: {
"Authorization": "key=firebaseKey",
"content-type": "application/json",
},
json: requestData
},
function(err, response, body) {
});
Yes, you can. For this you have to register these user Ids instead of device Id token. Then firebase recognized your user Ids.
#Override
public void onNewToken(#NonNull String token) {
super.onNewToken(token);
Log.d("user_token: ",token);
}
Related
Anyone can tell me how to send a push notification to a batch of group ids using FCM.
I tried
url = "https://fcm.googleapis.com/fcm/send"
headers = {
"Content-Type":"application/json",
"Authorization":"key={}".format(API_KEY)
}
body = {
"registration_ids":["group_id1","group_id2",...."group_idn"],
"data": {
"hello": "This is a Firebase Cloud Messaging Device Group Message!",
}
}
but it is giving me error.
{"multicast_id":6704816187425274139,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"NotRegistered"}]}
This question already has answers here:
FCM (Firebase Cloud Messaging) Send to multiple devices
(4 answers)
Closed 4 years ago.
I have Created a Chat App and I need to Send Notification when group messages receives,i can send notification to one device but i don't know what to do with group notification.
any idea?
You need to subscribe these token and send notification to that topic.
Subscribe to a topic
var registrationTokens = []
db.collection('room').document({roomId}).get().then(result => {
registrationTokens = result.data().usersTokens // get user tokens in that chat room
})
// Subscribe the devices corresponding to the registration tokens to the
// topic.
admin.messaging().subscribeToTopic(registrationTokens, topic)
.then(function(response) {
// See the MessagingTopicManagementResponse reference documentation
// for the contents of response.
console.log('Successfully subscribed to topic:', response);
})
.catch(function(error) {
console.log('Error subscribing to topic:', error);
});
Now you can send to specific group like this
// The topic name can be optionally prefixed with "/topics/".
var topic = 'highScores';
// See documentation on defining a message payload.
var message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
Let me go straight to the point, with Firebase Cloud Messaging and Android Oreo there have been some major changes when it comes to using their APIs.
I have entered my Firebase Server Api Key in the PubNub Console, push notification works absolutely fine on the Firebase console, but when publishing notification with PubNub, remoteMessage.toString gives => com.google.firebase.messaging.RemoteMessage#ffe9xxx in the OnMessageReceived function.
I am publishing something like this
JsonObject payload = new JsonObject();
JsonObject androidData = new JsonObject();
androidData.addProperty("contentText","test content");
androidData.addProperty("contentTitle","Title");
JsonObject notification = new JsonObject();
notification.add("notification",androidData);
JsonObject data = new JsonObject();
data.add("data", notification);
payload.add("pn_gcm", data);
in
PubNubObject.publish()
.message(payload)
etc..
Any idea why is this happening?
Thank you in advance.
Code on the receiving end
There is a class which extends FirebaseMessagingService, codes for OnMessageReceived function:
if (remoteMessage.getNotification() != null) {
//for testing firebase notification
Log.d(TAG, "Message Notification
Body:"+remoteMessage.getNotification().getBody());
} else {
//for anything else, I wanted to see what was coming from the server
//this is where I am getting the message when using PubNub notification
Log.d(TAG, "onMessageReceived: remoteMessage to
str:"+remoteMessage.toString() );
}
Android getData vs getNotification API
You are nesting the notification key/value inside of the data key and just need to use the API, remoteMessage.getData() instead of remoteMessage.getNotification().
If notification key was at the top level, it would work. See Android docs here.
Instead of this:
{
"pn_gcm": {
"data": {
"notification": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
}
This if switing to remoteMessage.getData():
{
"pn_gcm": {
"data": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
Or this if sticking with remoteMessage.getNotification():
{
"pn_gcm": {
"notification": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
}
PubNub basically just looks for the pn_gcm in the message payload when it is published and grabs whatever is inside of it and passes that directly to Google's FCM service for the devices that are registered (with PubNub) for that channel to receive GCM (FCM).
If the data is not formatted properly we would receive an error back from FCM which should be reported on the channel's -pndebug channel (assuming pn_debug:true was included in the published message payload).
For full details on troubleshooting FCM (GCM) or APONS issues with PubNub, please review How can I troubleshoot my push notification issues?
I am developing an Android app that using Push Notification feature. I need to push from server. I use Firebase for it. This is my first time using Firebase. But when I push from server using PHP and CURL, it is giving me invalid registration error.
I get the Firebase token in Android like this
String token = FirebaseInstanceId.getInstance().getToken();
Then I save sent that token to server and saved in the database.
At server, I am pushing like this
class Pusher extends REST_Controller {
function __construct()
{
parent::__construct();
}
public function notification_get()
{
$rows = $this->db->get('device_registration')->result();
$tokens= array();
if(count($rows)>0)
{
foreach($rows as $row)
{
$tokens[] = $row->token;
}
}
$message = array("message"=>"FCM PUSH NOTIFICATION TESTING");
if(count($tokens)>0)
{
$result = $this->send_notification($tokens,$message);
if(!$result)
{
die("Unable to send");
}
else{
$this->response($result, REST_Controller::HTTP_OK);
}
}
}
function send_notification($tokens,$message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids'=>$tokens,
'data'=>$message
);
$headers = array(
'Authorization:key = AIzaSyApyfgXsNQ3dFTGWR6ns_9pttr694VDe5M',//Server key from firebase
'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)
{
return FALSE;
}
curl_close($ch);
return $result;
}
}
I am using CodeIgniter 3 framework for building Rest API. When I push accessing URL from browser, it returns JSON data with error as in the below screenshot.
As you can see it is giving InvalidRegistration error and message is not pushed to devices. What is wrong with my code?
Additional
This is my FirebaseMessagingService class that show notification in Android
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(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);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setAutoCancel(true)
.setContentTitle("FCM Test")
.setContentText(message)
.setSmallIcon(R.drawable.info)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
}
Although I am not using codeigniter, I was encountering the InvalidRegistration error while sending to an iOS device, so I thought I would share my solution here.
I had to change registration_ids to to in PHP when sending a Notification message to a single device token, and make sure the value of to was a string and not an array.
Change this:
'registration_ids'=>$tokens,
To this:
'to'=>$tokens[0],
Invalid Registration ID Check the formatting of the registration ID
that you pass to the server. Make sure it matches the registration ID
the phone receives in the com.google.firebase.INSTANCE_ID_EVENT
intent and that you're not truncating it or adding additional
characters. Happens when error code is InvalidRegistration.
Please check with both the side app side and your side that the exact same registration id is stored in the server which Application on mobile receives it in on onTokenRefresh method. You should have received the exact same registration token as developer got in FirebaseInstanceId.getInstance().getToken()
As i got your comment and you've updated the code here is some change in your code it is from google doc it self...
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
Firebase has three message types:
Notification messages: Notification message works on background or
foreground. When app is in background, Notification messages are
delivered to the system tray. If the app is in the foreground,
messages are handled by onMessageReceived() or
didReceiveRemoteNotification callbacks. These are essentially what is
referred to as Display messages.
Data messages: On Android platform, data message can work on
background and foreground. The data message will be handled by
onMessageReceived(). A platform specific note here would be: On
Android, the data payload can be retrieved in the Intent used to
launch your activity.
Messages with both notification and data payloads: When in the
background, apps receive the notification payload in the notification
tray, and only handle the data payload when the user taps on the
notification. When in the foreground, your app receives a message
object with both payloads available. Secondly, the click_action
parameter is often used in notification payload and not in data
payload. If used inside data payload, this parameter would be treated
as custom key-value pair and therefore you would need to implement
custom logic for it to work as intended.
For Java in Android Do not use FirebaseInstallation
for generating token i don't know why but it does not return the valid token. every time I receive "InvalidRegistration" when try to POST through FCM REST API.
{
"multicast_id": 8303815118005358735,
"success": 0,
"failure": 1,
"canonical_ids": 0,
"results": [
{
"error": "InvalidRegistration"
}
]
}
Instead Use This:
if (firebaseUser != null) {
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.d(TAG, "getInstanceId failed", task.getException());
return;
}
if (task.getResult() != null) updateToken(task.getResult().getToken());
});
}
private void updateToken(String refreshToken) {
DocumentReference documentReference;
Token token1 = new Token(refreshToken);//just a class with str field
Map<String, Object> tokenMAp = new HashMap<>();
tokenMAp.put("tokenKey", token1.getToken());
Log.d(TAG, "updateToken: " + token1.getToken());
String id = firebaseUser.getUid();
baseref=sp.getString(BASE_REF,DEFAULT);
documentReference= FirebaseFirestore.getInstance().document(baseref);
updateDocWithToken(documentReference,tokenMAp);
}
private void updateDocWithToken(DocumentReference documentReference, Map<String, Object> tokenMAp) {
documentReference.set(tokenMAp, SetOptions.merge());
}
When I send GCM messages to multiple reg_ids some times I get NotRegistered Error.
How can I know which reg_id is not valid
{"multicast_id":5825324801553069805,"success":2,"failure":1,"canonical_ids":0,"results":[{"message_id":"0:1453198766912894%d41b519ed41b519e"},{"message_id":"0:1453198766913761%d41b519ed41b519e"},{"error":"NotRegistered"}]}
The response messages have same order with sent data's reg_id order.
As your example, the 3th reg_id is not registered.
{
"multicast_id":5825324801553069805,
"success":2,
"failure":1,
"canonical_ids":0,
"results":[
{
"message_id":"0:1453198766912894%d41b519ed41b519e"
},
{
"message_id":"0:1453198766913761%d41b519ed41b519e"
},
{
"error":"NotRegistered"
}
]
}