In summary I'm using Firebase Messaging Service and I'm trying to get my messages to show when the app is closed/killed. The weird problem is this sort of works. If I close the application and press send in the Azure Messaging Portal I'll get a notification as you should, however, that is the only notification I'll receive until I open the app and close it again and then I can receive one more. If the app is open I can spam send and I'll get all of the Notifications.
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
[IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" },
Categories = new string[] { "PACKAGEIDENTIFIER" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirstBaseMessagingService";
private int Notification_ID = 2;
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "From: " + message.From);
if (message.GetNotification() != null)
{
Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
SendNotification(message.Data);
}
else
{
SendNotification(message.Data);
}
}
void SendNotification(IDictionary<string,string> message)
{
Drawable drawable = ContextCompat.GetDrawable(this, Resource.Drawable.lsbu);
Bitmap bitmap = ((BitmapDrawable)drawable).Bitmap;
string title = message["title"];
string body = message["body"];
NotificationManager notificationManager = GetSystemService(NotificationService) as NotificationManager;
string ChannelID = GetString(Resource.String.LocalChannelID);
string AppName = GetString(Resource.String.AppName);
NotificationImportance Importance = NotificationImportance.Default;
NotificationChannel mChannel = new NotificationChannel(ChannelID, AppName, Importance);
notificationManager.CreateNotificationChannel(mChannel);
Notification.Builder builder = new Notification.Builder(this, ChannelID)
.SetWhen(DateTime.Now.Second)
.SetSmallIcon(Resource.Drawable.miniwozzad)
.SetLargeIcon(bitmap)
.SetContentTitle(title)
.SetContentText(body)
.SetChannelId(ChannelID);
var notification = builder.Build();
notificationManager.Notify(Notification_ID, notification);
Notification_ID++;
}
}
This being my payload in the Azure Test Portal
{"data":{"body": "Another big message", "test": 1, "title": "A Big Title2" }}
This is my FirebaseMessagingService class, I'm not sure what I'm missing here. Any help would be appreciated!
Related
My app is receiving the notification correctly but is failing to show a notification pop up with the received info (If the app is opened).
N.B.: In case if the app is in the background, the notifications are displayed without any issue.
My Code:
I receive the notification in this method:
#Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
Log.d(TAG, "From: " + remoteMessage.getFrom());
if(remoteMessage!=null)
{
String id = null;
String title = null;
String body = null;
String launchPage = null;
if(remoteMessage.getNotification()!=null)
{
title = remoteMessage.getNotification().getTitle();
body = remoteMessage.getNotification().getBody();
}
if(remoteMessage.getMessageId()!=null)
{
id = remoteMessage.getMessageId();
}
Log.i(TAG, "id: " + id);
Log.i(TAG, "title: "+ title);
Log.i(TAG, "body: " + body);
int notif_id = 0;
sendNotification(notif_id, title, body, launchPage);
}
}
then it calls this one (which is supposed to show the notification as i understand):
private void sendNotification(int id, String title, String messageBody, String launchPage)
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle("OMR - "+title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setChannelId(CHANNEL_ID);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel(notificationManager, CHANNEL_ID);
}
Toast.makeText(this, "Received a notif...", Toast.LENGTH_SHORT).show();
//this line is not showing a notification
notificationManager.notify(id, notificationBuilder.build());
}
Firebase notification
{
"data": {
"message": "data payload only used to force using OnMessageReceived() if in BACKGROUND",
"notif_id": 1
},
"to" : "e04OAVaRw30:APA91bGyv5_tt4IWRkurjlqkqNlCxTBV8oRne18tQ5puniHPItOMgg11kdt56t5jfZnasb4Ms-tH9xUgWQhHy2eM487llRtlM9_V_PoWJI9KSr6XgCaysiDyS",
"notification": {
"title": "Notification",
"body": "This is Notification 2",
"sound":"default"
}
}
Result
the notification is built correctly
sound played correctly
notif put in system tray
BUT no notification popup appears (i have to show a
custom dialog for that)
My Problem lies in this specific line
notificationManager.notify(id, notificationBuilder.build());
which is failing to show the notification
Update
i have read more about Android notifications in
https://developer.android.com/guide/topics/ui/notifiers/notifications
and found out that notifications only show in the notification drawer without popping up (as Heads-up notifications).
and according to this question, i can force the notifications to show as Heads-up notifications if i added a high priority to them. Unfortunately this is not working either.
This image explains it all if you are using FCM.
Well, in my case some of the data I'm passing into the message body is null in the onReceived.
Fixed that and my notification popup was showing again
Change
val notificationManager = packageContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
to
val notificationManager = NotificationManagerCompat.from(packageContext.applicationContext)
helps to me
This is my first question. I have connected my domain into firebase. The push notification is working when I update the post in my Wordpress Blog. Ok, thats good for now. But, i want to save all that notification in a Fragment, and can be clicked from there to start an activity for post id. How to save that Notification?
Here is my Firebase Messaging code:
private static int VIBRATION_TIME = 500; // in millisecond
private SharedPref sharedPref;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
sharedPref = new SharedPref(this);
if (sharedPref.getNotification()) {
// play vibration
if (sharedPref.getVibration()) {
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(VIBRATION_TIME);
}
RingtoneManager.getRingtone(this, Uri.parse(sharedPref.getRingtone())).play();
if (remoteMessage.getData().size() > 0) {
Map<String, String> data = remoteMessage.getData();
FcmNotif fcmNotif = new FcmNotif();
fcmNotif.setTitle(data.get("title"));
fcmNotif.setContent(data.get("content"));
fcmNotif.setPost_id(Integer.parseInt(data.get("post_id")));
displayNotificationIntent(fcmNotif);
}
}
}
private void displayNotificationIntent(FcmNotif fcmNotif) {
Intent intent = new Intent(this, ActivitySplash.class);
if (fcmNotif.getPost_id() != -1) {
intent = new Intent(this, ActivityPostDetails.class);
Post post = new Post();
post.title = fcmNotif.getTitle();
post.id = fcmNotif.getPost_id();
boolean from_notif = !ActivityMain.active;
intent.putExtra(ActivityPostDetails.EXTRA_OBJC, post);
intent.putExtra(ActivityPostDetails.EXTRA_NOTIF, from_notif);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(fcmNotif.getTitle());
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(fcmNotif.getContent()));
builder.setContentText(fcmNotif.getContent());
builder.setSmallIcon(R.drawable.ic_notification);
builder.setDefaults(Notification.DEFAULT_LIGHTS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(Notification.PRIORITY_HIGH);
}
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int unique_id = (int) System.currentTimeMillis();
notificationManager.notify(unique_id, builder.build());
}
}
yes you can store the your Notification payload in database and create list in fragment and show data from Database and click on any row start activity according to Post ID by getting post id by position
You can save notification message when the notificaton arrived inside
onMessageReceived(RemoteMessage remoteMessage)
method like this
A full example of a notification is like this..
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
Map<String, String> data = remoteMessage.getData();
String value1 = data.get("key_1");
String value2 = data.get("key_2");
String title=data.get("title");
String msg=data.get("body");
Log.d("Backgraound", value1);
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.
sendNotification(title,msg,value1,value2);
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
private void sendNotification(String title,String messageBody, String val1,String val2) {
try {
Intent intent = new Intent(this, Notification_activity.class);
//Bundle bundle = getApplicationContext().getExtras();
Bundle basket = new Bundle();
basket.putString("key_1", val1);
basket.putString("key_2", val2);
intent.putExtras(basket);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.spacebar_round)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setColor( getResources().getColor(R.color.colorPrimary))
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher));
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
}
I create an app chat with firebase realtime db, I'm doing add friend step, I want to show a notification when user click add friend. I used the firebase function. Everything works fine but my device still not show notification. I really don't know while. Can someone help me?
My index.js to deploy on firebase:
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/notifications/{user_id}/{notification_id}').onWrite((data, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to: ', user_id);
const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value');
return deviceToken.then(result=>{
const token_id=result.val();
const payload={
notification:{
title: "FRiend Request",
body: "You have received a friend request",
icon:"default"}
};
return admin.messaging().sendToDevice(token_id,payload).then(response =>{
console.log('This was notification feature');
return true;});
});
});
And on firebase function console (It still has a notification sent)
You need a firebase messenging service class.
create a class called MyFirebaseMessagingService which will receive the notification and decode it.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
private static final String CHANNEL_ID = "MyFirebaseMessagingService";
String title;
String message;
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated.
title = "You have a new notification";
message = remoteMessage.getNotification().getBody();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("You have a new notification")
.setContentText(remoteMessage.getNotification().getBody());
int notificationId = (int) System.currentTimeMillis();
// Issue the notification.
NotificationManager notification = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notification != null;
notification.notify(notificationId, mBuilder.build());
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, mBuilder.build());
createNotificationChannel();
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
}
private void createNotificationChannel() {
// 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 = title;
String description = message;
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
assert notificationManager != null;
notificationManager.createNotificationChannel(channel);
}
}
}
Add a meta-data inside your Manifest.xml like the followiing
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#mipmap/ic_launcher" />
Also add the following messaging service to your xml
<service android:name=".services.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
I am having an issue on Oreo devices where notifications are simply just not displayed in the hud when they are sent to client. I can assure that they are being received in the background as i've created a custom vibration effect OnMessageReceived and this works but still nothing is displayed in the Android HUD.
Also, I've noticed another article saying Visual Studio kills the notification service when forcefully closed. This is true because it also killed my vibration effect, but with the app side loaded I can launch from the device and my custom effect is triggered.
I believe what I am doing is 1, registering my tags to the Azure-FCM service.
2nd, I am saying registering my API Endpoint and also the allowed templates.
I think there is something wrong with the payload templates I am registering,
and the payloads I am sending
See below..
Web API that generates Android payload
private string GetAndroidAlertJson(int? fromId, int notificationType, string message)
{
return new JObject(
new JProperty("data",
new JObject(
new JProperty("notification",
new JObject(
new JProperty("badge", 1),
new JProperty("body", message),
new JProperty("title", "wazzup?!"),
new JProperty("priority", "high")
)
),
new JProperty("type_id", notificationType),
new JProperty("user", fromId != null ? fromId.ToString() : ""),
new JProperty("message", message)
)
)
).ToString();
}
Xamarin.Android
//NotificationBuilder
return new NotificationCompat.Builder(ApplicationContext, PRIMARY_CHANNEL)
.SetContentTitle(title)
.SetContentText(body)
.SetSmallIcon(SmallIcon)
.SetPriority(2)
.SetVibrate(new long[0])
.SetAutoCancel(true);
//In MainActivity
public NotificationHelper(Context context) : base(context)
{
var chan1 = new NotificationChannel(PRIMARY_CHANNEL,
PRIMARY_CHANNEL, NotificationImportance.Max);
chan1.LightColor = 2;
chan1.LockscreenVisibility = NotificationVisibility.Public;
Manager.CreateNotificationChannel(chan1);
}
public NotificationCompat.Builder GetNotification1(String title, String body)
{
return new NotificationCompat.Builder(ApplicationContext, PRIMARY_CHANNEL)
.SetContentTitle(title)
.SetContentText(body)
.SetSmallIcon(SmallIcon)
.SetPriority(2)
.SetVibrate(new long[0])
.SetAutoCancel(true);
}
FCMService
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FCMMessagingService : FirebaseMessagingService
{//Foreground Only
const string TAG = "MyFirebaseMsgService";
public override void OnMessageReceived(RemoteMessage message)
{
if (Debugger.IsAttached)
Debugger.Break();
CustomNotificationEffect();
try
{
if (message.Data.Count > 0)
{
var type_id = Convert.ToInt32(RetreiveNotification("type_id"));
var body = RetreiveNotification("message");
MainActivity.SendNotification(type_id, body);
}
}
catch (Exception e)
{
//Was NotificationType null? this should never be null anyways
}
string RetreiveNotification(string key)
{
string value = String.Empty;
message.Data.TryGetValue(key, out value);
return value;
}
}
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class FCMInstanceIDService : FirebaseInstanceIdService
{
const string TAG = "MyFirebaseIIDService";
public static string ProfilePushTag;
public async override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Console.WriteLine("Token Received!: " + refreshedToken);
await SendRegistrationToServer(refreshedToken);
}
public async Task SendRegistrationToServer(string token)
{
//We will have to send our token to the server here
//
string templateBodyFCM =
"{" +
"\"notification\" : {" +
"\"body\" : \"$(messageParam)\"," +
"\"title\" : \"Xamarin U\"," +
"\"icon\" : \"myicon\" }}";
var templates = new JObject();
//templateBodyFCM = "Pyx";
templates["genericMessage"] = new JObject
{
{ "body", templateBodyFCM}
};
try
{
var tags = new List<string>();
if (!String.IsNullOrWhiteSpace(ProfilePushTag))
{
// Register with Notification Hubs
var hub = new NotificationHub("HUB-NAME",
"AZURE-ENDPOINT"
, this);
tags.Add(ProfilePushTag);
var regID = hub.Register(token, tags.ToArray()).RegistrationId;
var hub2 = new MobileServiceClient("https://MyAPI");
await hub2.GetPush().RegisterAsync(token, templates);
}
}
catch (Exception e)
{
}
}
In Android O it's a must to use a channel with your Notification Builder
below is a sample code of how you should use it :
public NotificationCompat.Builder GetNotification1(String title, String body) {
var mynotif = new Notification.Builder(ApplicationContext)
.SetContentTitle(title)
.SetContentText(body)
.SetSmallIcon(SmallIcon)
.SetPriority(2)
.SetVibrate(new long[0])
.SetAutoCancel(true);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O) {
mynotif.SetChannelId(PRIMARY_CHANNEL);
}
}
If you look at my Web API, everything is wrapped inside a "data" type. According to this article How to handle notification when app in background in Firebase the "data" types will not be displayed in the HUD, but the "notification" types will. removing this attribute resolved the issue and is now displayed in the HUD.
I am sending push notification message from Firebase console to my app running on emulator.
The MyFirebaseMessagingService class looks like this:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
if(remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if(remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "my_channel_01");
notificationBuilder.setContentTitle("FCM Notification");
notificationBuilder.setContentText(remoteMessage.getNotification().getBody());
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
notificationBuilder.setContentIntent(pendingIntent);
notificationBuilder.setChannelId("my_channel_01");
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
The constructor for NotificationCompat.Builder for API 26 now takes two params one is Context and another is String channelId. So I just assigned a random string to my channel.
But when I send the message from the firebase console the app on emulator gives me an error TOAST saying:
Failed to post notification on channel "my_channel_01"
What am I doing wrong?
When your build specifies a targetSdkVersion of 26, and you run on an API level 26 device or emulator, you must both specify a channel ID when constructing NotificationCompat.Builder, and also create the channel.
You could use a method like this:
public static final String NOTIF_CHANNEL_ID = "my_channel_01";
...
#RequiresApi(Build.VERSION_CODES.O)
private void createNotifChannel(Context context) {
NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID,
"MyApp events", NotificationManager.IMPORTANCE_LOW);
// Configure the notification channel
channel.setDescription("MyApp event controls");
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = context.getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
Log.d(TAG, "createNotifChannel: created=" + NOTIF_CHANNEL_ID);
}
And because it is only needed for API 26 and requires that level, invoke it like this:
// The channel need only be created for API 26 devices. For devices
// running an API less the 26, there is no way to create a channel and the
// channel ID specified in the constuctor to NotificationCompat.Builder is
// merely a placeholder.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotifChannel(this);
}
It does no harm to recreate the NotificationChannel, which provides some flexibility in where you do it. If your app has multiple entry points (activity, broadcast receiver, etc) take care to ensure the channel is created for all cases. You can also ensure it is only created once using NotificationManager.getNotificationChannel():
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (manager.getNotificationChannel(NOTIF_CHANNEL_ID) == null) {
createNotifChannel(this);
}
}