I have checked in my onMessageReceived method whether the app is in foreground or background and I only show the notification when app is in background or the app is not visible, the notification is working fine but in both cases the notification sound gets played I don't want the notification sound to get played when the app is in foreground. Here is the code for onMessageReceived
override fun onMessageReceived(p0: RemoteMessage?) {
var sh = SharedPreferencesHelper.getInstance(applicationContext, Constants.PREFS)
if (sh.getInt(Constants.LOGIN_STATE)!=Constants.STATE_COMPLETED) {
return
}
var data = p0?.data
val send = Intent(Constants.NOTIFICATION_RECEIVED)
// You can also include some extra data.
send.putExtra(Constants.COUNT, data?.get(Constants.COUNT))
LocalBroadcastManager.getInstance(this).sendBroadcast(send)
var title = p0?.data?.get("title")
var message = p0?.data?.get("message")
var intent: Intent? = null
if (data?.get("status") == "follow") {
intent = Intent(this, ViewProfileActivity::class.java)
intent.putExtra(Constants.PROFILE_ID, data?.get("userid"))
intent.putExtra(Constants.SEEN_ID, data?.get("id"))
intent.putExtra(Constants.SEEN, "")
} else if (data?.get("status") == "reply" || data?.get("status") == "direct reply") {
val notify = Intent(Constants.REPLIES_AVAILABLE)
// You can also include some extra data.
LocalBroadcastManager.getInstance(this).sendBroadcast(notify)
intent = Intent(this, NowwtReplyActivity::class.java)
intent.putExtra(Constants.NOWWT_ID, data?.get("nowwtid"))
intent.putExtra(Constants.SEEN_ID, data?.get("id"))
intent.putExtra(Constants.SEEN, "")
} else if (data?.get("status") == "direct nowwt") {
intent = Intent(this, NowwtReplyActivity::class.java)
intent.putExtra(Constants.DIRECT_NOWWT, true)
intent.putExtra(Constants.NOWWT_ID, data?.get("nowwtid"))
intent.putExtra(Constants.SEEN_ID, data?.get("id"))
intent.putExtra(Constants.SEEN, "")
} else if(data?.get("status") == "people"){
intent = Intent(this, DashboardActivity::class.java)
intent.putExtra(Constants.NAVIGATE_PEOPLE,true)
} else if (data?.get("status") == "simple") {
intent = Intent(this, SplashActivity::class.java)
}
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
try {
if (FireNotificationUtils.isAppIsInBackground(applicationContext)) {
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
val notificationBuilder = NotificationCompat.Builder(applicationContext, "yoyo")
notificationBuilder.setContentTitle(title)
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round_nowwt)
notificationBuilder.setLargeIcon(BitmapFactory.decodeResource(applicationContext.resources,
R.drawable.logo_))
notificationBuilder.setContentText(message)
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
notificationBuilder.setDefaults(0)
notificationBuilder.priority = NotificationCompat.PRIORITY_MAX
notificationBuilder.setAutoCancel(true)
// notificationBuilder.setSound(defaultSoundUri)
notificationBuilder.setContentIntent(pendingIntent)
val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val CHANNEL_ID = "my_channel_01"// The id of the channel.
val name = getString(R.string.channel_name)// The user-visible name of the channel.
val importance = NotificationManager.IMPORTANCE_HIGH
val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
notificationBuilder.setChannelId(CHANNEL_ID)
notificationManager.createNotificationChannel(mChannel)
}
notificationManager.notify(0, notificationBuilder.build())
super.onMessageReceived(p0)
}
} catch (e: Exception) {
}
}
Related
I'm creating notification using Firebase and FCM
class FcmServices: FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
sendNotification(remoteMessage)
}
override fun onNewToken(token: String) {
super.onNewToken(token)
}
private fun sendNotification(remoteMessage: RemoteMessage) {
val notifTitle = remoteMessage.notification?.title
val notifBody = remoteMessage.notification?.body
val builder: NotificationCompat.Builder?
val notificationManager =
this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "101"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_DEFAULT
val notificationChannel = NotificationChannel(channelId, "notification", importance)
notificationManager.createNotificationChannel(notificationChannel)
builder = NotificationCompat.Builder(applicationContext, notificationChannel.id)
} else {
builder = NotificationCompat.Builder(applicationContext)
}
val intent = Intent(this, NotifikasiActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setSmallIcon(R.drawable.logo_bprmsa)
.setLargeIcon(
BitmapFactory.decodeResource(
this.resources,
R.drawable.logo_bprmsa
)
)
.setContentIntent(pendingIntent)
.setContentTitle(notifTitle)
.setContentText(notifBody)
.setDefaults(Notification.DEFAULT_VIBRATE)
var alarmSound: Uri? = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
if (alarmSound == null) {
alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
if (alarmSound == null) {
alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
}
}
builder.setSound(alarmSound)
builder.setAutoCancel(true)
builder.setWhen(System.currentTimeMillis())
builder.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
builder.priority = NotificationCompat.PRIORITY_HIGH
notificationManager.notify(Random().nextInt(), builder.build())
}
}
I need to open the NotificationActivity after click the notification received from Firebase, but the problem is the PendingIntent is not working while the app is in background state. Is there any different condition between foreground and background state code ?
And for the second, the layout of foreground and background is also different (background state without the icon shown)
https://firebase.google.com/docs/cloud-messaging/concept-options
Based on the official document from Google, it is intentional. The Icon and any other buttons or others you wish to display other than the title and the message won't display if your app is not running foreground.
When I swipe up after the local notification comes, the application notifications don't appear on the screen for a while. What could be the reason for this? I've read something that when heads up notifications are swiped up, it sends a warning to the system to prevent heads up notifications for a certain period of time, but how can I prevent this? I don't have any problems getting notifications in my app other than that.
fun getChatChannels(): MutableList<NotificationChannel> {
val chatChannels = mutableListOf<NotificationChannel>()
val chatChannel = NotificationChannel(
IM_CHANNEL_ID,
Application.getString(R.string.chat_channel_name),
NotificationManager.IMPORTANCE_HIGH
)
chatChannel.setShowBadge(false)
chatChannel.group = MESSAGE_GROUP_ID
chatChannels.add(chatChannel)
return chatChannels }
private fun getChannelList(): MutableList<NotificationChannel> {
val channelList = mutableListOf<NotificationChannel>()
channelList.addAll(getChatChannels())
return channelList
}
fun createGroupsAndChannels() {
// 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) {
val notificationManager =
Application.instance.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannelGroups(getGroupList())
notificationManager.createNotificationChannels(getChannelList())
}
Log.d(TAG, "Channels and groups created")
}
fun showChatNotification(destinationAddress: String, messageId: String, message: String) {
ThreadManager.createUITask {
val name = if (domainContact != null) {
"${domainContact.firstName} ${domainContact.lastName}"
} else {
destinationAddress
}
val notificationIntent = Intent(Application.instance, MainActivity::class.java)
notificationIntent.putExtra(
Application.getString(R.string.key_conversation_participant),
destinationAddress
)
notificationIntent.flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
val pendingIntent = PendingIntent.getActivity(
Application.instance,
destinationAddress.hashCode(),
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val notificationId = UUID.randomUUID().hashCode()
val builder = NotificationCompat.Builder(Application.instance, IM_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification_message)
.setColor(ContextCompat.getColor(Application.instance, R.color.colorPrimary))
.setContentTitle(name)
.setContentText(message)
.setStyle(
NotificationCompat.BigTextStyle() // Expandable-Collapsible notification
.bigText(message)
)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent)
.setVisibility(VISIBILITY_PUBLIC)
.setAutoCancel(true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.addAction(getChatNotificationReplyAction(destinationAddress, notificationId, messageId))
}
chatNotifications.add(mapOf(destinationAddress to notificationId))
createNotifications(builder, notificationId)
Log.d(TAG, "Chat notification created")
}
private fun createNotifications(builder: NotificationCompat.Builder, notificationId: Int) {
with(NotificationManagerCompat.from(Application.instance)) {
notify(notificationId, builder.build())
}
}
i have a problem with chronometer in Notification. I want to get current tick if notification clicked and parsing value to MainActivity using Intent. i have no idea about this case, i was try and result is always 0.
here my notification code with RemoteView
fun showNotification(context: Context, value: Long, state: Int) {
val isPaused = state == Constant.MusicState.PAUSED
val intentTimer = Intent(context, MainActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val bundle = Bundle()
bundle.putLong(Constant.Key.CURRENT_TIME, value)
val pendingIntentButtonPause = PendingIntent.getActivity(context, 100, intentTimer, PendingIntent.FLAG_UPDATE_CURRENT, bundle)
val remoteViews = RemoteViews(context.packageName, R.layout.item_notification)
remoteViews.setChronometer(R.id.chronometer, value, null, !isPaused)
remoteViews.setOnClickPendingIntent(R.id.buttonPause, pendingIntentButtonPause)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val builder = NotificationCompat.Builder(context, "199102")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentText("Test")
.setAutoCancel(false)
.setOngoing(true)
.setOnlyAlertOnce(true)
.setUsesChronometer(true)
.setContentIntent(PendingIntent.getActivity(context, 10, intentTimer, PendingIntent.FLAG_UPDATE_CURRENT))
remoteViews
builder.setCustomContentView(remoteViews)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
checkNotificationChannel(context, "199102")
}
notificationManager.notify(199102, builder.build())
}
And this when i call function showNotification()
this.binding.apply {
this#MainActivity.musicState = Constant.MusicState.IDLE
this.chronometer.setOnChronometerTickListener {
try {
if (it.text == "00.10" || it.text == "00:10") {
Chronotification.showNotification(this#MainActivity, it.base, this#MainActivity.musicState)
this#MainActivity.musicState = Constant.MusicState.IDLE
this#MainActivity.binding.buttonStart.text = "Start"
it.text = "00.00"
it.stop()
}
}catch (e : Exception) {
e.printStackTrace()
}
}
GeneralHelper.makeClickable(this#MainActivity, this.buttonStart)
}
Thanks, any help or suggestion will be appreciate.
An application receives push notifications. They can be different (payment, order, chat), so I have to show them all, not replacing old with new. A problem is that in old emulators (API 19) all push notifications are shown separately.
In newer emulators they are groupped into one, but (if I'm not mistaken) after 3 received notifications.
Data sent from FCM:
{
"to": "<push token>",
"data": {
"title": "Application name",
"message": "See a message",
"screen": "Main screen",
...
}
}
MyFirebaseMessagingService:
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val textStyle = NotificationCompat.BigTextStyle()
val title: String
val body: String
if (remoteMessage.data.isNullOrEmpty()) {
title = remoteMessage.notification?.title ?: ""
body = remoteMessage.notification?.body ?: ""
} else {
title = remoteMessage.data["title"] ?: ""
body = remoteMessage.data["message"] ?: ""
}
val notificationBuilder = NotificationCompat.Builder(this,
getString(R.string.default_notification_channel_id))
.setContentTitle(title)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setStyle(textStyle)
.setSound(soundUri)
.setSmallIcon(R.drawable.ic_notification_icon)
.setAutoCancel(true) // Dismiss the notification on click.
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Since android Oreo notification channel is needed.
setupChannels(notificationManager, notificationBuilder)
// Create pending intent, mention the Activity which needs to be triggered
// when user clicks on notification.
val notificationId = Random.nextInt()
navigateToScreen(notificationBuilder, notificationId, remoteMessage)
val notification = notificationBuilder.build()
notificationManager.notify(notificationId, notification)
}
private fun setupChannels(notificationManager: NotificationManager,
notificationBuilder: NotificationCompat.Builder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = getString(R.string.default_notification_channel_id)
val channel = NotificationChannel(channelId, "title",
NotificationManager.IMPORTANCE_DEFAULT).apply {
description = "body"
enableLights(true)
enableVibration(true)
lightColor = Color.CYAN
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
canShowBadge()
setShowBadge(true)
}
notificationManager.createNotificationChannel(channel)
notificationBuilder.setChannelId(channelId)
}
}
private fun navigateToScreen(notificationBuilder: NotificationCompat.Builder,
notificationId: Int,
remoteMessage: RemoteMessage) {
val intent = getNavigationIntent(remoteMessage)
val pendingIntent = PendingIntent.getActivity(this, notificationId, intent,
PendingIntent.FLAG_UPDATE_CURRENT)
notificationBuilder.setContentIntent(pendingIntent)
}
private fun getNavigationIntent(remoteMessage: RemoteMessage): Intent {
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("screen", remoteMessage.data["screen"])
return intent
}
I have tried using "0" notification id and as well as unique notification id.
Also used setGroup() like below. It still generates a new notification every time. I want to merge the notification body and set the title as common.
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
remoteMessage?.let {
sendNotification(it.data["alert"])
}
}
private fun sendNotification(messageBody: String?) {
val channelId = "${this.packageName}-${this.getString(R.string.app_name)}"
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val builder = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
setGroupSummary(true)
}
val manager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, getString(R.string.default_channel_name), NotificationManager.IMPORTANCE_HIGH)
manager?.createNotificationChannel(channel)
}
val intent = Intent(this, DashboardFlowActivity::class.java)
intent.putExtra(DashboardFlowActivity.ISFROMNOTIFICATION, true)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
builder.setContentIntent(pendingIntent)
//manager?.cancelAll()
manager?.notify(this.getString(R.string.app_name), getID(), builder.build())
}
}
private val c = AtomicInteger(0)
private fun getID(): Int {
return c.incrementAndGet()
}
Anything I am doing wrong here? Also, I have gone through this answer. setgroup() in notification not working
Finally I got solution for this question using https://stackoverflow.com/a/41114135/6021469, https://www.developer.com/ws/android/creating-bundled-notifications-with-android.html
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
remoteMessage?.let {
sendNotification(it.data["alert"])
}
}
private fun sendNotification(messageBody: String?) {
val channelId = "${this.packageName}-${this.getString(R.string.app_name)}"
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val builder = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setShowWhen(true)
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setShowWhen(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
}
val builderSummary = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setShowWhen(true)
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setShowWhen(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
setGroupSummary(true)
}
val manager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, getString(R.string.default_channel_name), NotificationManager.IMPORTANCE_HIGH)
manager?.createNotificationChannel(channel)
}
val intent = Intent(this, DashboardFlowActivity::class.java)
intent.putExtra(DashboardFlowActivity.ISFROMNOTIFICATION, true)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
builder.setContentIntent(pendingIntent)
manager?.notify(this.getString(R.string.app_name), getID(), builder.build())
manager?.notify(this.getString(R.string.app_name), 0, builderSummary.build())
}
}
private val c = AtomicInteger(0)
private fun getID(): Int {
return c.incrementAndGet()
}