First of all, I am sorry if there is a topic on this but I didn't found the exact solution.
The problem is that, I am setting a notification but when I close the app, the notification is removed automatically by the system. You might think it is relevant to onGoing attribute but as far as I know it is required user interaction. In my case, notifications disappear by itself.
Here is the code:
class NotificationHelper {
private val CHANNEL_ID: String = "Default Channel ID"
private var context: Context
private var notificationManager: NotificationManager
private var notificationBuilder: NotificationCompat.Builder
constructor(context: Context) {
this.context = context
this.notificationManager =
this.context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// NotificationChannel is required on Oreo and newer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.notificationManager.createNotificationChannel(
NotificationChannel(
CHANNEL_ID,
this.context.getString(R.string.channel_name),
NotificationManager.IMPORTANCE_HIGH
)
)
}
notificationBuilder = NotificationCompat.Builder(this.context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_set_notification_black)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setNotificationSilent()
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(
PendingIntent.getActivity(
this.context, 0, Intent(
this.context,
MainActivity::class.java
), 0
)
)
}
fun setNotification(notification: Notification) {
val deleteIntent = Intent(context, BootOrUpdateBroadcastReceiver::class.java)
deleteIntent.action = GlobalInfo.ACTION_NOTIFICATION_DELETE
deleteIntent.putExtra(GlobalInfo.NotificationEntry.COLUMN_ID, notification.id)
val notificationToBeShown: android.app.Notification = this.notificationBuilder
.setContentTitle(notification.title)
.setContentText(notification.content)
.setStyle(NotificationCompat.BigTextStyle().bigText(notification.content))
.setAutoCancel(notification.removeByClick)
.setOngoing(!notification.removeBySwipeAway)
.setDeleteIntent(
PendingIntent.getBroadcast(
context,
0,
deleteIntent,
PendingIntent.FLAG_CANCEL_CURRENT
)
)
.build()
with(NotificationManagerCompat.from(this.context)) {
// notificationId is a unique int for each notification that you must define
notify(notification.id, notificationToBeShown)
}
}
fun clearNotification(notificationId: Int) {
this.notificationManager.cancel(notificationId)
}
fun clearAllNotifications() {
this.notificationManager.cancelAll()
}
}
Also, I thought to use a sticky service but it doesn't make sense to me. Services are also being destroyed as the application is closed. There should be another way.
Thanks in advance :)
Related
I want to show the app name on top and all the notifications of the app clubbed below it. I am receiving the notification from firebase and using this code:
val messagingStyle = Notification.MessagingStyle(person)
val remoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).also {
it.setLabel(context.getString(R.string.type_to_reply))
}.build()
val mChannel =
NotificationChannel(channelId, newMessage.text, NotificationManager.IMPORTANCE_HIGH)
mChannel.description = newMessage.text.toString()
mChannel.enableVibration(true)
val notifManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notifManager.createNotificationChannel(mChannel)
val statusBarNotification = notifManager.activeNotifications.firstOrNull {
it.id == channelId.toInt()
}
if (statusBarNotification == null) {
val builder: Notification.Builder = Notification.Builder(context, channelId)
val pendingIntent: PendingIntent =
PendingIntent.getActivity(
context,
channelId.toInt(),
navIntent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
builder.setContentTitle(newMessage.text)
.setSmallIcon(R.drawable.my_logo) // required
.setContentText(newMessage.text) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.addAction(
getNotificationIntent(context, channelId.toInt(), remoteInput)
)
.setWhen(newMessage.timestamp)
.setStyle(messagingStyle.addMessage(newMessage))
.setContentIntent(pendingIntent)
.setGroup(MY_NOTIFICATIONS)
.setGroupSummary(true)
val notification = builder.build()
notifManager.notify(channelId.toInt(), notification)
} else {
var notificationBuilder = recoverBuilder(context, statusBarNotification.notification)
notificationBuilder.also {
val messageStyle = it.style as Notification.MessagingStyle
messageStyle.addMessage(newMessage.text, newMessage.timestamp, person)
it.style = messageStyle
}
notifManager.notify(channelId.toInt(), notificationBuilder.build())
}
This is what I want(like whatsapp)
[![whatsapp screenshot]]
[1]: https://i.stack.imgur.com/1j3Xf.jpg
But this is how it is appearing right now. all the notifications are seperate.
[![screenshot]]
[2]: https://i.stack.imgur.com/UdhrY.jpg
There are similar posts here about merging notifications. They offer different approaches so check them out to see which one is applicable to your use case:
Firebase merge similar notifications in Android
How to merge push notifications like whatsapp does in FirebaseMessagingService
Can't get grouped/bundled notifications with
FirebaseMessagingService
I have implemented a broadcast receiver to ask the user to restart the app if it is killed. I have confirmed that the broadcast receiver is being called fine, and it runs the below line but for some reason, I am not getting any notification.
Here is the code,
class ForegroundLocationServicesRestarter : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent != null) {
if (intent.action != ForegroundLocationService.ACTION_RESTART_LOCATION_UPDATES) {
return
}
}
val notificationChannelId = "restartDeliveryApp"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(notificationChannelId, "location_notif_chan", NotificationManager.IMPORTANCE_MAX)
val manager = context.getSystemService(LifecycleService.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(notificationChannel)
}
val fullScreenIntent = Intent(context, DeliveryManActivity::class.java)
fullScreenIntent.putExtra("RESTART_TRIGGERED", true)
val fullScreenPendingIntent = PendingIntent.getActivity(
context, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT
)
NotificationCompat.Builder(context, notificationChannelId)
.setSmallIcon(R.drawable.ic_truck_red)
.setContentTitle(context.getString(R.string.restarter_title))
.setContentText(context.getString(R.string.restarter_message))
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(fullScreenPendingIntent, true)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.build()
}
}
The notification channel is unique, the app has notification permission and also, full intent permission in the manifest. Any help is highly appreciated.
Plus there is already one service notification, does that impact this in any way?
was not pushing notifications into the system to display! Just need to do this!
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(notificationChannelId, "location_notif_chan", NotificationManager.IMPORTANCE_MAX)
val manager = context.getSystemService(LifecycleService.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(notificationChannel)
}
val dmIntent = Intent(context, DeliveryManActivity::class.java)
dmIntent.putExtra("RESTART_TRIGGERED", true)
val dmPendingIntent = PendingIntent.getActivity(
context, 0, dmIntent, PendingIntent.FLAG_UPDATE_CURRENT
)
// Prepare a notification with vibration, sound and lights
val builder = NotificationCompat.Builder(context, notificationChannelId)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_truck_red)
.setContentTitle(context.getString(R.string.restarter_title))
.setContentText(context.getString(R.string.restarter_message))
.setLights(Color.RED, 1000, 1000)
.setVibrate(longArrayOf(0, 400, 250, 400))
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(dmPendingIntent)
Pushy.setNotificationChannel(builder, context)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(7, builder.build()) // same notification id to override
Hi custom FCM notifications have stopped showing up on Android. they used to work before but after I updated all the gradle libraries notifications have stopped showing up on the deivce.
The code is executed with breakpoints and no errors are shown but notifications are not shown.
I am clueless on how to investigate this.
any pointers would be very very useful.
This is the code that should show custom notifications with a two layouts for small and large notifications sizes.
private fun showCustomPushNotification(message: RemoteMessage, chargerId: String) {
val notificationLayout = RemoteViews(
packageName,
R.layout.pgin_requires_approval_notification_small
)
val notificationLayoutExpanded = RemoteViews(
packageName,
R.layout.pgin_requires_approval_notification_large
)
val title = message.data[MSG_TITLE]
val subTitle = message.data[MSG_SUB_TITLE]
notificationLayout.setTextViewText(R.id.tvTitle, title)
notificationLayout.setTextViewText(R.id.tvSubTitle, subTitle)
notificationLayoutExpanded.setTextViewText(R.id.tvTitle, title)
notificationLayoutExpanded.setTextViewText(R.id.tvSubTitle, subTitle)
val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val customNotification = NotificationCompat.Builder(
this,
CarInfoProcessingService.APPROVE_EACH_PGIN_NOTIFICATION_CHANNEL_ID
)
.setSmallIcon(R.mipmap.ic_launcher)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutExpanded)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.build()
val approveIntent = Intent(this, CustomNotificationListener::class.java)
approveIntent.putExtra("onClickListener", "approve")
approveIntent.putExtra("chargerId", chargerId)
val pendingApproveIntent = PendingIntent.getBroadcast(
this,
0,
approveIntent,
PendingIntent.FLAG_IMMUTABLE
)
notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnApprove, pendingApproveIntent)
val denyIntent = Intent(this, CustomNotificationListener::class.java)
denyIntent.putExtra("onClickListener", "deny")
denyIntent.putExtra("chargerId", chargerId)
val pendingDenyIntent = PendingIntent.getBroadcast(
this,
1,
denyIntent,
PendingIntent.FLAG_IMMUTABLE
)
notificationLayoutExpanded.setOnClickPendingIntent(R.id.btnDeny, pendingDenyIntent)
val notificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(CustomNotificationListener.WHAT_NOTIFICATION_ID, customNotification)
}
Only change that I can think of is updating libraries in gradle but as it does not show any error I am clueless.
Thanks for your help in advance.
R
You say before update it was working. So after update i think you need to check versions for your code :
Define your pending intent like below :
val pendingIntent: PendingIntent? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getActivity(applicationContext, 0, intent, PendingIntent.FLAG_ONE_SHOT)
}
You might wanna set priority for your notification, Build.VERSION_CODES.O and above will ignore that but older devices uses this:
customNotification.priority = NotificationCompat.PRIORITY_MAX
And for Build.VERSION_CODES.O and above notification channel is needed:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
customNotification.setChannelId(Constants.NOTIFICATION_CHANNEL)
val channel =
NotificationChannel(
Constants.NOTIFICATION_CHANNEL,
Constants.NOTIFICATION_NAME,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(channel)
}
For the constans i used they are just strings:
const val NOTIFICATION_NAME = "YourApp"
const val NOTIFICATION_CHANNEL = "YourApp_channel_01"
Just change your code regarding to this and it will work. If you can not manage to do that please let me know.
I am trying to integrate Firebase Cloud Messages into my app. The code I used in the showNotification function is from the Android User Interface Samples. I tried it in the Activity and it worked but am not sure why it's not working in the service. The println is showing the function is getting called and values are coming as expected. Is there anything am missing from the function?
class MessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.data.isNotEmpty()) {
val message = Gson().fromJson(remoteMessage.data.toString(), Message.Res::class.java).payload!!
showNotification(message.title, message.body, message.count)
}
}
private fun showNotification(title: String?, body: String?, count: Int = 0) {
println("_print::showNotification(title:$title, body:$body, count:$count)")
val mainPendingIntent = PendingIntent.getActivity(
applicationContext, BuildConfig.REQUEST_CODE,
Intent(applicationContext, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
val builder = NotificationCompat.Builder(applicationContext, "channel_email_1")
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher_round))
.setContentIntent(mainPendingIntent)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setColor(ContextCompat.getColor(applicationContext, R.color.primary))
.setSubText(if (count > 1) "You have $count pending notifications" else title)
.setCategory(Notification.CATEGORY_EMAIL)
.setPriority(1)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
NotificationManagerCompat.from(applicationContext)
.notify(BuildConfig.NOTIFICATION_ID, builder.build())
}
}
Instead of
val mainPendingIntent = PendingIntent.getActivity(
applicationContext, BuildConfig.REQUEST_CODE,
Intent(applicationContext, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
NotificationManagerCompat.from(applicationContext)
.notify(BuildConfig.NOTIFICATION_ID, builder.build())
I use:
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Since android Oreo notification channel is needed.
setupChannels(notificationManager, builder)
// Create pending intent, mention the Activity which needs to be triggered
// when user clicks on notification.
val notificationId = Random.nextInt()
navigateToScreen(builder, notificationId)
val notification = builder.build()
notificationManager.notify(notificationId, notification)
}
private fun setupChannels(notificationManager: NotificationManager,
builder: NotificationCompat.Builder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = "channel_email_1"
val channel = NotificationChannel(channelId, "title",
NotificationManager.IMPORTANCE_DEFAULT).apply {
description = "body"
// Add other settings.
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
canShowBadge()
setShowBadge(true)
}
notificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}
}
private fun navigateToScreen(builder: NotificationCompat.Builder,
notificationId: Int) {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, notificationId, intent,
PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(pendingIntent)
}
I'm trying to create a foreground service that check devices location every minute and I've managed to make it work. But I have some problems regarding the obligatory notification about the service being active.
I can't get the notification badge to stop showing and I can't make the notification minimized programatically.
Here are the relevant parts:
class LocationPollingService : Service() {
companion object {
const val NOTIF_ID = 2
const val NOTIF_CHANNEL_ID = "background_service_notification"
const val NOTIF_CHANNEL_NAME = "Background service"
}
#Nullable
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
createBackgroundNotifChannel()
startForeground()
requestLocation()
return super.onStartCommand(intent, flags, startId)
}
private fun startForeground() {
val notificationIntent = Intent(this, SplashActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this, 0,
notificationIntent, 0
)
val notification = NotificationCompat.Builder(
this,
NOTIF_CHANNEL_ID
)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_app_icon)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.im_watching_you))
.setContentIntent(pendingIntent)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIF_ID, notification.build())
} else {
notification.priority = NotificationCompat.PRIORITY_MIN
startForeground(NOTIF_ID, notification.build())
}
}
private fun createBackgroundNotifChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelBackground = NotificationChannel(
NOTIF_CHANNEL_ID,
NOTIF_CHANNEL_NAME,
NotificationManager.IMPORTANCE_LOW
).apply {
description = getString(
R.string.notification_channel_background_description
)
enableLights(false)
enableVibration(false)
setShowBadge(false)
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channelBackground)
}
}
}
If I understand correctly, IMPORTANCE_LOW is supposed to be used for this kind of notification and it is supposed to make it minimized by default. The notification is never minimized nor can I minimize it by clicking. The only way I can make it minimized is by manually changing notification channel settings in device settings (setting Notification style to Silent and minimized, instead of just silent, which is the default). I tried setting the importance to IMPORTANCE_MIN and IMPORTANCE_NONE, but that didn't change anything.
As mentioned, the second problem is that the badge is shown (the notification counter displayed on app icon), despite of setShowBadge(false).
What am I missing?
You need to notify notification after build notification like below :
notificationManager.notify(NOTIF_ID , notification.build());
for hiding notification badge from statusbar
you should change notification channel priority:
val channelBackground = NotificationChannel(
NOTIF_CHANNEL_ID,
NOTIF_CHANNEL_NAME,
NotificationManager.IMPORTANCE_MIN