I'm using firebase notifications. This is FirebaseMessagingService:
class mFirebaseMessagingService : FirebaseMessagingService() {
private lateinit var notification: Notification
private val badgeCount = 3 //value to show in badge
override fun onMessageReceived(remoteMessage: RemoteMessage) {
sendNotification(remoteMessage.notification.body)
}
private fun sendNotification(message: String) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val builder = NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.img)
.setLargeIcon(BitmapFactory.decodeResource(this.resources, R.drawable.img))
.setContentTitle(this.getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true)
notification = builder.build()
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(0, notification)
ShortcutBadger.applyNotification(applicationContext, notification, badgeCount) //trying to use it
}
}
I need to set icon badge count to my value, but Firebase set it to count of notifications. I'm trying to use ShortcutBadger library but it doesn't work well with firebase notifications. Works only if notifications creating programmatically (by the button for example). Any idea?
Related
I am trying to show a custom notification when I get a push notification from firebase, when the app is in background.
When the app is in background, the log messages START and END gets printed but does not show the notification on Android which I created as customNotification.
This is how I created a notification.
Could you please suggest what should be corrected please
override fun onMessageReceived(message: RemoteMessage) {
Log.d("FCMService", "onMessageReceived START")
//super.onMessageReceived(message)
// Get the layouts to use in the custom notification
val notificationLayout = RemoteViews(packageName, R.layout.plugin_requires_approval_notification_small)
val notificationLayoutExpanded = RemoteViews(packageName, R.layout.plugin_requires_approval_notification_large)
// Apply the layouts to the notification
val customNotification = NotificationCompat.Builder(this, "FcmService")
.setSmallIcon(R.mipmap.ic_launcher)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutExpanded)
.build()
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(0, customNotification)
Log.d("FCMService", "onMessageReceived END")
}
Thanks in advance
R
EDIT
it is fixed now, the issue was with the CHANNEL_ID I provided.
for reference channelID should be the one used in the notificationChannel() function which looks like the bellow code, this is in the project App class.
private fun createNotificationChannels() {
// Do this only on API 26+ because the NotificationChannel
// class is new and not in the AndroidX library
if (SDK_INT >= O) {
val caInfoNotifChannel = NotificationChannel(CaInfoProcessingService.NOTIFICATION_CHANNEL_ID,
getString(R.string.ca_info_service_notif_channel_name),
IMPORTANCE_LOW).apply {
description = getString(R.string.ca_info_service_notif_channel_desc)
}
// Register the channel with the system
getSystemService<NotificationManager>()?.createNotificationChannel(caInfoNotifChannel)
}
}
I'm creating a chat app that sends and receives notifications through Firebase Cloud Functions. Let's suppose I have 2 friends, and each friend sends me 5 messages(5 notifications). When I open a chat in my chat list, I want all notifications for that chat to be dismissed and the others not.
Currently I can only dimiss 1 notification. If I get more than one notification the notificationManager.cancel(notificationId) doesn't work. I don't want to use notificationManager.cancelAll() as I just want to dismiss some notifications.
override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.notification.let { notification ->
val type = remoteMessage.data[NOTIFICATION_TYPE]
val notificationChannelId = getNotificationChannelId(type)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val intent = Intent(this, HomeActivity::class.java)
val notificationIntent = setIntent(remoteMessage.data)
val stackBuilder: TaskStackBuilder = TaskStackBuilder.create(this)
stackBuilder.addParentStack(HomeActivity::class.java)
stackBuilder.addNextIntent(intent)
stackBuilder.addNextIntent(notificationIntent)
val pendingIntent: PendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationBuilder = NotificationCompat.Builder(this, notificationChannelId)
.setContentTitle(notification?.title ?: "")
.setContentText(notification?.body ?: "")
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(notification?.body ?: "")
)
.setSmallIcon(R.drawable.ic_stat)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSound(soundUri)
.setColor(ContextCompat.getColor(applicationContext, R.color.colorNotification))
.setVibrate(vibrationPattern)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
notify(remoteMessage.data, notificationManager, notificationBuilder)
}
}
private fun notify(
data: Map<String, String>,
notificationManager: NotificationManager,
notificationBuilder: NotificationCompat.Builder
) {
when (data[NOTIFICATION_TYPE]) {
CHAT_MSG -> {
if (data[NotificationUtils.CHAT_ID] != ChatActivity.currentChat) {
notificationManager.notify(
CHAT_MSG_NOTIFICATION_ID,
notificationBuilder.build()
)
}
}
FRIEND_REQUEST -> {
notificationManager.notify(
FRIEND_REQUEST_NOTIFICATION_ID,
notificationBuilder.build()
)
}
}
}
OnStart():
fun dismissNotifications(notificationId: Int) {
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(notificationId)
}
My thoughts is:
Save all notificationIds in map where:
key is userName/userId in message.
value is List of notificationId
When you need to clear all notifications you just ask you map and clear all that notificationIds for that userName/userId
In my application I have several activities and one is chat. In this screen I have the ID of who is chatting with me and every time I send a message a push notification is sent with the message and the id of the person with whom I am chatting. While I'm chatting with this person I need to block notifications from them and only receive them if I don't have an open chat with that person. How do I do this? I'm using Firebase as a backend.
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.notification?.let { notification ->
val data = remoteMessage.data
val type = data["type"] // chat message,like etc
val id = data["id"] //userId
val notificationChannelId = getString(R.string.default_notification_channel_id)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val intent = setIntent(remoteMessage).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(notificationChannelId, CHANNEL_SPEEACHT, NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(notificationChannel)
}
val notificationBuilder = NotificationCompat.Builder(this, notificationChannelId)
.setContentTitle(notification.title ?: "")
.setContentText(notification.body ?: "")
.setSmallIcon(R.drawable.ic_stat)
.setSound(soundUri)
.setColor(ContextCompat.getColor(applicationContext, R.color.colorNotification))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
notificationManager.notify(0, notificationBuilder.build())
}
}
I think this is not firebase-cloud-messaging related, because firebase-cloud-messaging is just a message channel, so you should do it in your own bussiness code.
A suggested way is that you can make a condition. if the activity is visable and the userid you received in onMessageReceived is the same as the userid you are chatting with, then you should not create your own notification in onMessageReceived function.
I need to develop custom turn off/on push notification. Value "on" or "off" I get from SharedPreferences.
In Foreground the option of turn off works well because it can set in onMessageReceived.
But how to do this options for Kill and Background modes?
For sending push notifications I use Postman.
My code in FMC:
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val CURRENT_PUSH = "currentPush"
private var sPref: SharedPreferences? = null
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
if(loadCurrentPushNotification()) {
if (remoteMessage!!.data != null) sendNotification(remoteMessage)
}
}
private fun sendNotification(remoteMessage: RemoteMessage) {
val data = remoteMessage.data
val title = data["title"]
val content = data["content"]
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val NOTIFICATION_CHANNEL_ID = "1234"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
#SuppressLint("WrongConstant") val notificationChannel = NotificationChannel(NOTIFICATION_CHANNEL_ID,
"SA Notification",
NotificationManager.IMPORTANCE_MAX)
notificationChannel.description = "SA channel notification"
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.vibrationPattern = longArrayOf(0, 1000, 500, 1000)
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
}
val notificationBuilder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
notificationBuilder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.sa_launcher)
.setContentTitle(title)
.setContentText(content)
.setContentInfo("Breaking")
notificationManager.notify(1, notificationBuilder.build())
}
private fun loadCurrentPushNotification(): Boolean { //to read the status push notification from SharedPreferences
sPref = getSharedPreferences("pushesOnOff", Context.MODE_PRIVATE)
return sPref!!.getBoolean(CURRENT_PUSH, true)
}
}
I suspect that your push notification payload/content contains the notification key like
notification : {
'title':'This is title'
}
If this is true, then you will not receive the onMessageReceived callback when your app is killed and hence your check will not work. In order to prevent this, remove the notification from your payload and only send data and it should work without any change on android side.
You can read about this behavior HERE.
I am working on an app in which I have to save all the notification coming from the server using firebase. I can save which notification is coming in the foreground and also I can save if notification is coming in the background but in a condition that if I clicked on the notification I can able to save it. But my main concern is if the user swipes the notification or clear the notification that means a user will not click on the notification, then how can I save it. Is there any method? Please help me to find a solution for this.
You probably have a class that extends FirebaseMessagingService so you can do stuff on the onMessageReceived function. You can use the RemoteMessage function getData() see docs to ge the message payload. From there you can access the title and other information. Of course you'll need to know about the structure of the notification received. So, to answer you question you can save the notification information when it is received in the background by simply saving it in the onMessageReceived method of your FirebaseMessagingService.
FCM stops receiving notifications when the app is killed see. So your best approach is to do as #D10S suggested and implement the saving and the sending in cloud functions. here's an example of how to send notifications. You'll need to make your app save the notification token to the real time database so the cloud function can read it and send the notification to the correct user.
To save your token to the Real Time database you'll need to add some code in your FirebaseInstanceIdService, specially in the onTokenRefresh method. You can have a location in your database called tokens and you can create an object with the user ID. So you could add the token to the server like so:
DatabaseReference ref = database.getReference("tokens");
Map<String, String> users = new HashMap<>();
users.put(userUID, token);
ref.setValueAsync(users);
Notifications which are coming from server will be received in onMessageReceived(RemoteMessage remoteMessage) , From remoteMessage object you will get title and body , which you can store in sqlite or in SharedPreference.
For Example:-
class FBMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.i("PVL", "MESSAGE RECEIVED!!");
if (remoteMessage.getNotification().getBody() != null) {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
} else {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
}
}
}
onMessageReceived will get event in every state :-Killed ,background,foreground.
You can not save the notification if the user doesn't open it in the app, so if he swipes the notification there is no way to save it within the app.
An option is use Cloud Functions for Firebase:
https://firebase.google.com/docs/functions/
So you can create a function that send notification to your users, and then add code to add the behaviour that you are looking for: when you send a notification, save it.
#Suppress("DEPRECATION")
class MyFirebaseMessagingService : FirebaseMessagingService() {
val TAG = "FirebaseMessagingService"
#SuppressLint("LongLogTag")
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "sent phone: ${remoteMessage.from}")
if (remoteMessage.notification != null) {
showNotification(remoteMessage.notification?.title, remoteMessage.notification?.body)
}
}
private fun showNotification(title: String?, body: String?) {
val databaseHelper = DatabaseHelper(this)
// sharedPreferences=this.getSharedPreferences("SHARED_PREF" , Context.MODE_PRIVATE)
val intent = Intent(this, MenuscreenActivity::class.java)
databaseHelper.insertData(title, body, databaseHelper.FIRST_TABLE_NAME)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
startActivity(intent)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(0, notificationBuilder.build())
}
}
#Suppress("DEPRECATION")
class MyFirebaseMessagingService : FirebaseMessagingService() {
val TAG = "FirebaseMessagingService"
#SuppressLint("LongLogTag")
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "sent phone: ${remoteMessage.from}")
if (remoteMessage.notification != null) {
showNotification(remoteMessage.notification?.title, remoteMessage.notification?.body)
}
}
private fun showNotification(title: String?, body: String?) {
val databaseHelper = DatabaseHelper(this)
// sharedPreferences=this.getSharedPreferences("SHARED_PREF" , Context.MODE_PRIVATE)
val intent = Intent(this, MenuscreenActivity::class.java)
databaseHelper.insertData(title, body, databaseHelper.FIRST_TABLE_NAME)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
startActivity(intent)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(0, notificationBuilder.build())
}
}