I'm sending notifications to an android device using node-gcm, and in some cases, I need to send an image with the notification to display as a thumbnail, like so:
notification with thumbnail
And sometimes I need to send notifications without the thumbnail. With the below code I can send the image in the notification, the problem is when another notification is received, they collapse, making the new one overwriting a notification that was already there:
var message = new gcm.Message({
"data" : {
"title" : "Test",
"message" : "Test message!",
"priority" : 2, // Highest priority.
"ledColor" : [255, 0, 0, 1],
"content-available": "1",
"image": req.body.notificationImageUrl, //<-- image URL
},
});
But if I set up the message like below, I can't find a way to send the image but the notifications do not collapse and all of them appear. Another problem is that the led does not activate in this version:
var message = new gcm.Message({
data: {
"priority" : 2, // Highest priority.
"content-available": "1",
"image": req.body.notificationImageUrl, // <-- image URL
},
notification:{
title: "Test",
body: "Test message!",
color: "#892121",
sound: 'default',
vibrationPattern: [300, 150, 300], // Vibrate for 300ms then wait 150ms and then vibrate for 300ms.
ledColor: [255, 0, 0, 1], // <-- this does not work
},
});
What I want is a way to send the notification with the thumbnail in a way that it does not overwrite a notification that was previously there.
EDIT: I forgot to mention, im using Ionic Framework with Cordova so I can't manage the notifications in the device unless there is a way to do it through those frameworks.
Thanks in advance!
While going through the node-gcm issues I found the solution, there is a parameter called "notId" to add a ID to a notification.
var message = new gcm.Message({
"data": {
"title": "Test",
"message": "Test message!",
"priority": 2, // Highest priority.
"ledColor": [255, 0, 0, 1],
"content-available": "1",
"image": req.body.notificationImageUrl,
"notId": parseInt(Math.random() * new Date().getSeconds(), 10), // <-- this solved the problem
},
});
The management of the display of notifications is done on the device. You have to make sure you are setting, on Android, a different NOTIFICATION_ID for each notification, or the last one will always replace the one before it.
// Sets an ID for the notification - make sure to change this for different notifications
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it
mNotifyMgr.notify(mNotificationId, mBuilder.build());
Related
I am working on a iOS version of Xamarin application (android was built by another person). I have used Plugin.FirebasePushNotifications plugin and have successfully set up the apns from Firebase console. The response looks something like this:
2020-09-28 12:50:57.566 Project.iOS[16900:2364597] {
aps = {
alert = {
body = "This is the body of the notitification";
title = "Testing Notification";
};
"mutable-content" = 1;
sound = default;
};
"gcm.message_id" = 1601286657133844;
"gcm.notification.sound2" = default;
"google.c.sender.id" = 633381035766;
}
The notifications successfully arrives on the device and it works perfectly in foreground/background/app killed.
However, when I use different server with different protocol(?) I receive this type of message:
2020-09-28 12:51:30.944 SycretBeauty.iOS[16900:2364597] {
Body = "\U0422\U0415\U0421\U0422 8";
Title = "Title";
aps = {
"content-available" = 1;
};
"gcm.message_id" = 1601286690545984;
}
The id is the same and I receive it ok in VS console. However, the notification doesn't pop up on the screen. What should I do to see the notification popping up on the screen? I can't change the API and Android is already all set up working with that type of response structure...
(and I don't even know why "TEST 8" shows in UNICODE characters...)
I have solved the issue by downstreaming through Postman.
Url: https://fcm.googleapis.com/fcm/send
Headers(2):
ContentType - application/json
Authorization - <your server key from firebase>
Body:
{ "to":"d8bEmMpQJE6EuEYCG4COKq:APA91bG7YCDT7AyyJGS3j5bnpwVrbvSgdrjuUcatjOBLSkKaGpa2xZP7YDhzMAEMYfLDDp7gTgzUzhx-vs4nvr_n3yJQ6FdU9m0sxxw-stzHIxtuvXEPSXNHGy_2yxWBxGLn0IVktsil",
"notification" : {
"Body" : "Notification Body",
"Title" : "Notification Title",
"content_available" : true,
"priority" : "high"
}
}
The notification arrives after I use correct syntax for "body" and "title" all the time.
I am currently working on flutter notification using firebase messaging, I couldn't receive any notification. I sent the notification via server using curl, I could get it work in native android app (Android Studio) but not in flutter, any help would be appreciated. Below is my code.
Flutter Notification code
class FirebaseNotifications {
FirebaseMessaging _firebaseMessaging;
void setUpFirebase() {
_firebaseMessaging = FirebaseMessaging();
firebaseCloudMessaging_Listeners();
}
void firebaseCloudMessaging_Listeners() {
if (Platform.isIOS) iOS_Permission();
_firebaseMessaging.getToken().then((token) {
print(token);
});
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print('on message $message');
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
}
void iOS_Permission() {
_firebaseMessaging.requestNotificationPermissions(
IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
}
}
Android Studio code
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
showNotification(remoteMessage);
}
private void showNotification(RemoteMessage remoteMessage) {
Map data = remoteMessage.getData();
String mesg = "New Notification";
Intent intent;
PendingIntent pendingIntent;
NotificationCompat.Builder builder;
Intent i = new Intent(this,MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(Color.GREEN);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{0, 250, 250, 250});
mNotificationManager.createNotificationChannel(mChannel);
builder = new NotificationCompat.Builder(this, id);
intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentTitle(data.get("title").toString()) // required
//.setStyle(new
NotificationCompat.BigTextStyle().bigText(remoteMessage.getNotification()
.getBod
y().toString()))
.setStyle(new
NotificationCompat.BigTextStyle().bigText(mesg)) //custom data
.setSmallIcon(R.drawable.ic_stat_notification_icon4) //
required
.setContentText(mesg) // custom data
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_ALL)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{0, 250, 250, 250});
}
}
Server side code
function sendtoUser($sendingTarget, $acc_name, $type_message,
$type_of_transaction, $check_amount)
{
#API access key from Google API's Console
$API_ACCESS_KEY = "adazxc";
$registrationIds = $sendingTarget;
#prep the bundle
$fields = array(
'to' => $registrationIds,
'data' => array(
'title' => 'my title',
'keyValue' => true,
'receiverName' => $acc_name,
'transType' => $type_of_transaction,
'totalAmount' => $check_amount
),
);
$headers = array(
'Authorization: key=' . $API_ACCESS_KEY,
'Content-Type: application/json'
);
#Send Reponse To FireBase Server
$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);
}
EDIT
I somehow can receive notification but I noticed that my status bar not receiving the notification but it is printed in the console, however, when I close the app I can get the notification. So how do I able to receive notification in both situation?
data tag only for transferring more information to app, like where it has to redirect, image etc.. you have to add notification tag to display notification on status bar.
its seems you havent added notification content, please refer below sample message and configure same, it'll work
{
"notification": {
"body": "body",
"title": "title"
},
"priority": "high",
"data": {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"id": "1",
"status": "done",
"image": "https://ibin.co/2t1lLdpfS06F.png",
},
"to": <fcm_token>
}
From the docs:
Depending on a devices state, incoming messages are handled differently.
State
Description
Foreground
When the application is open, in view & in use.
Background
When the application is open, however in the background (minimised). This typically occurs when the user has pressed the "home" button on the device, has switched to another app via the app switcher or has the application open on a different tab (web).
Terminated
When the device is locked or the application is not running. The user can terminate an app by "swiping it away" via the app switcher UI on the device or closing a tab (web).
And this:
Notification messages which arrive whilst the application is in the foreground will not display a visible notification by default.
If your app is currently opened and in the foreground, the notification will not be shown even if it was sent successfully. You can confirm this by opening the snackbar in the notification event handler like below:
FirebaseMessaging.onMessage.listen((message) {
print('Got a message whilst in the foreground!');
if (message.notification != null) {
final snackBar = SnackBar(
content: Text(message.notification?.title ?? '', maxLines: 2),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
});
If you're working with android and you want to display notification when in the foreground, you can use flutter_local_notifications package as suggested from the FCM docs here.
Some checks (Version numbers may change):
Add google-services.json (Download from firebase console) to
android/app/
In android/build.gradle:
Add google() to repositories
Add classpath 'com.google.gms:google-services:4.2.0' to dependencies
In android/app/build.gradle:
Add implementation 'com.google.firebase:firebase-messaging:18.0.0' to
dependencies
Add apply plugin: 'com.google.gms.google-services' at the end
Have the applicationId the same like package_name in the
google-services.jon
For what it's worth, I had an issue with receiving onMessage notifications today (didn't try onResume or onLaunch) when it was working fine yesterday. No errors in the Functions logs and tokens were all the same.
Try restarting your device -- this seems to be the most consistent way to fix this if your functions were previously working.
Also, if the messaging seems slow at first, this may be due to cold starting when you aren't using the functions for a while (see this SO question for a bit more information).
Most of the scenarios are already mentioned here. However, along with the checklist mentioned by #Zerj, I would like to add one more point.
Check if your project has environment flavors for dev, staging, prod etc. In that case, the google-services.json file would reside in the respective folders (android/app/development, etc) instead of at the android/app level.
If the above method too gives some problems for you, you can hardcode the credentials in the flavor's MainActivity file using FirebaseOptions class. You can find the usage here
More info about flavors - https://firebase.google.com/docs/projects/multiprojects
You may miss manual configuration for android (as well as ios if required), refer below link
http://myhexaville.com/2018/04/09/flutter-push-notifications-with-firebase-cloud-messaging/
I am using Firebase push notifications in my Android App. I can send correctly notification with custom icon, but I have not managed to play my custom sound. I always get the default sound of my device.
{
"registration_ids": "myToken",
"notification": {
"body": "my body",
"title": "my title",
"icon": "ic_notification",
"sound": "mysound.mp3" // I tried "mysound", "mysound.wav"...
},
"priority": "high"
}
The custom sound is located in /res/raw
I have been able to play my custom sound with onMessageReceived and Firebase data message but not with Firebase notification message.
My android device is Xiaomi Mi A1 and Oreo 8.1., also tried with Xiaomi Mi A2 with same result.
I tried with php and curl, with node.js... always same problem, I get my default sound.
UPDATE
With this code for node.js does not work either:
var registrationToken = 'xxxxxx';
var message = {
notification: {
title: 'my title',
body: 'my body',
},
android: {
ttl: 3600 * 1000,
notification: {
color: '#ff0000',
sound: 'mysound.mp3'
}
},
token: registrationToken
};
Finally I found the solution. For Android 8.0 and higher it's necessary to create a notification channel in your App:
NotificationChannel channel = new NotificationChannel('my_id', name, importance);
(more info: https://developer.android.com/training/notify-user/channels#java)
Then when you send the notification:
var registrationToken = 'xxxxxx';
var message = {
notification: {
title: 'my title',
body: 'my body',
},
android: {
ttl: 3600 * 1000,
notification: {
color: '#ff0000',
sound: 'mysound.mp3',
channel_id: 'my_id' // important to get custom sound
}
},
token: registrationToken
};
I was also looking for the solution to custom sound for firebase notification in the android, And I have solved this problem through Notification Channel.
I have created one notification channel with custom sound, that sound plays after receiving notification in the application background state.
You can refer following links of the notification channel.
https://medium.com/exploring-android/exploring-android-o-notification-channels-94cd274f604c
https://developer.android.com/training/notify-user/channels
You need to put your mp3 file at /res/raw/ path.
Please find the code.
NotificationManager notificationManager = (NotificationManager) getActivity().getSystemService(NotificationManager.class); // If you are writting code in fragment
OR
NotificationManager notificationManager = (NotificationManager) getSystemService(NotificationManager.class); // If you are writting code in Activity
createNotificationChannel function
private void createNotificationChannel() {
Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.sample); //Here is FILE_NAME is the name of file that you want to play
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
CharSequence name = "mychannel";
String description = "testing";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
NotificationChannel channel = new NotificationChannel("cnid", name, importance);
channel.setDescription(description);
channel.enableLights(true); channel.enableVibration(true);
channel.setSound(sound, audioAttributes);
notificationManager.createNotificationChannel(channel);
}
};
createNotificationChannel();
To achieve this you need to pass android_channel_id property in the firebase notification request object.
{
"notification": {
"body": "this is testing notification",
"title": "My App",
"android_channel_id": "cnid"
},
"to": "token"
}
Note - If you create a notification channel once then you can't change the sound. You have to create a new notification channel with the new name with your desired sound.
From the documentation, include the sound in notification object under android object. Give name of the sound file in sound value. The sound files must reside in /res/raw/ . Below is a Node.js example:-
var message = {
notification: {
title: 'sample title',
body: 'Hello, its Tuesday.',
},
android: {
ttl: 3600 * 1000,
notification: {
icon: 'my_icon',
color: '#f45342',
sound: 'filename.mp3',
},
},
apns: {
payload: {
aps: {
badge: 42,
},
},
},
topic: 'industry-tech'
};
Try Enabling Sound From Firebase Console
For More Info Just Look at this answer
https://stackoverflow.com/a/44304089/9024123
may be this should be problem and also try removing '.mp3' in sound element and make it like
"sound":"mySound"
i was also facing the same issue. I always got the default sound but i fixed it as follows . I am using FCM-push (node module) https://www.npmjs.com/package/fcm-push
var message = {
to : device_token,
collapse_key : '<insert-collapse-key>',
// data : {
// '<random-data-key1>' : '<random-data-value1>',
// '<random-data-key2>' : '<random-data-value2>'
// },
notification : {
title : 'Title ',
body : 'some Body',
sound : 'notification' // my .ogg file in /res/raw
},
android: {
sound: 'notification' // my .ogg file name in /res/raw
}
};
I have not tried it with mp3 or wav and in your question it seems you have not tried with .ogg file ( though i doubt if it has anything to do with audio format but you can try)
Maybe this helps :
In my case i tried with the above approach and it did not worked, whenever i was checking in the onMessageReceived (for debug purpose) the channel id
Log.e(TAG, "Message Notification channel id: " + remoteMessage.getNotification().getChannelId());
i always got 'null'.
So reading the documentation from here https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support
I found out that i was using the wrong key for the channel id in the json.
Instead of 'channel_id' key try to use 'android_channel_id' key like this
"notification": {
"body": "Body of Your Notification",
"title": "Title of Your Notification",
"android_channel_id": "channelId",
"icon": "myIcon"
}
If i use it like that it works as expected, custom sound (from res/raw) is played
PS: in my case i set my sound on the channelId when i created it
Good luck !
One mistake I made when trying this was I didn't change the the channel id although I updated the Json and modified the code. My channel was always bound to the device sound. Just after I updated to a different channel id my code started working. Custom sound is now playing for both foreground and background
Following is the JSON which worked for me
{
"to" : "token"
,
"notification": {
"title":"Server Notification Title",
"body":"Notification Body",
"sound":"sound.wav",
"android_channel_id": "ch1"
},
"priority": "high"
}
The code
Uri soundUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/" + R.raw.sound);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "ch1")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText(remoteMessage.getNotification().getBody().toString())
.setAutoCancel(true)
.setSound(soundUri);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
if(soundUri != null){
// Changing Default mode of notification
notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
// Creating an Audio Attribute
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
// Creating Channel
NotificationChannel channel = new NotificationChannel("ch1","App Name",NotificationManager.IMPORTANCE_HIGH);
channel.setSound(soundUri,audioAttributes);
channel.enableLights(true); channel.enableVibration(true);
mNotificationManager.createNotificationChannel(channel);
}
}
mNotificationManager.notify(0, notificationBuilder.build());
I try use FCM to send notification.
I try 2 methods to send notification,
I send notification (FCM) via Firebase Console (Success, push notification appear on top screen)
I send notification via https://fcm.googleapis.com/fcm/send. Here my setup :
let title = "My Title";
let msg = "Test Notification";
let header = {
headers: {
'Authorization': 'key=' + serverKey,
'Content-Type': 'application/json'
},
};
let body = {
"registration_ids": clientToken,
"data": {
'body': msg,
'title': title,
'link': '-',
'click_action': 'OPEN_MAIN_ACTIVITY',
}
}
My Question is The first method work fine (notification appear). But
why when i send FCM with the second method, on Android not appear the
push notification? Can you find what mistake of the code ?
When multiple mails arrive one by one, Gmail groups them and shows only one notification message on the Notification Area. I would like to do the same thing. I searched Google and found that I need to set tag, but setting the same tag just replaced the previous one, not showing multiple messages as Gmail.
Should I not use the notification-type, but use the data-type only and handle notifications myself? If so, this should be something a lot of people are ding. Is there a sample project that I can start with?
Also, if I can somehow use the notification-type for grouping, it gives the data as Intent extras. How does it pass multiple data to my activity, if the notification is showing multiple items as Gmail?
{
"to": "/topics/that",
"notification": {
"title": "Title 686",
"body": "My body",
"tag": "xxx"
},
"data": {
"title": "Title 686",
"body": "My body",
}
}
You can use inbox style with notification builder
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_glyph)
.setContentTitle(title)
.setColor(context.getResources().getColor(R.color.colorPrimary))
.setContentText(contentText);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
for (int i = 1; i < 11; i++) {
inboxStyle.addLine(("Message " + i);
}
inboxStyle.setBigContentTitle(title);
mBuilder.setStyle(inboxStyle);