Handle Push Notification in Kotlin - android

i am using Kotlin Navigation component architecture for my chat app, and i am using Firebase Messaging service to integrate push notification, my requirement is to hide or disable the notifications when i am on User chat screen.Please let me know, how can i achieve this.
this is my code of displaying notification
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
Log.d(TAG, "From: ${remoteMessage?.from}")
remoteMessage?.data?.let {
Log.d(TAG, "data payload: " + remoteMessage.data.toString())
val params =remoteMessage.data.get("body")
val objects = JSONObject(params)
Log.e("JSON OBJECT", objects.toString())
val title = remoteMessage.data.get("title").toString()
sendNotification(messageBody,title, applicationContext)
} }
my notification class is:
fun NotificationManager.sendNotification(messageBody: String, title: String, applicationContext: Context) {
notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// TODO: Step 1.12 create PendingIntent
if(title.equals("Ride Request")) {
fragmentId = R.id.notificationFragment
}
else if(title.equals("Ride Accepted")) {
fragmentId = R.id.inboxFragment
}
else if(title.equals("New Message")) {
fragmentId = R.id.inboxFragment
}
// ---------- creating navgraph intent to open specific fragment ------------
var contentPendingIntent = NavDeepLinkBuilder(applicationContext)
.setComponentName(HomeActivity::class.java)
.setGraph(R.navigation.home_bottom_navigation)
.setDestination(fragmentId)
.setArguments(bundle)
.createPendingIntent()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationChannel = NotificationChannel(channel_id, description,
NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = R.color.colorPrimary
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
builder = NotificationCompat.Builder(applicationContext, channel_id)
.setSmallIcon(R.drawable.icon_car)
.setContentTitle(applicationContext.getString(R.string.app_name))
.setContentText(messageBody)
.setContentIntent(contentPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
}else {
builder = NotificationCompat.Builder(applicationContext,
applicationContext.getString(R.string.app_name))
.setSmallIcon(R.drawable.icon_car)
.setContentTitle(applicationContext.getString(R.string.app_name))
.setContentText(messageBody)
.setContentIntent(contentPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
}
notify(NOTIFICATION_ID, builder.build())
}

I don't if this is the perfect but you can try it as well
If the user is in chat screen you can create a sharedPref and set value of the variable to true (that the user is in chat screen)
So in the onMessageReceived() check it the value of the sharedPref is true (which mean the user is in chat screen)
If it's true then don't send notifications if false send notification
To set the sharedPref value
In the onResume of that chat activity set to true
In the onPause set to false

try this
class InboxFragment : Fragment() {
companion object {
var userId: String? = null
}
override fun onStart() {
userId = navArgs.userId
}
override fun onStop() {
userId = null
}
}
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
...
if (InboxFragment.userId != remoteMessage.data.get("userId"))
sendNotification(messageBody, title, applicationContext)
}
}

Related

How to create multiple notifications in Kotlin in foreground service

I am working on a parental control app which notify parent multiple times but when I try to create notification with a background service it generates only one 1.
Here is how I do it:
fun createNotification(parent_name: String, notificationText:String, id: Int){
val MchannelId = channelId+id.toString()
if (Build.VERSION.SDK_INT >= 26) {
val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel(
MchannelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT
)
} else {
TODO("VERSION.SDK_INT < O")
}
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
channel
)
}
val notificationIntent = Intent(this, TabbedActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
id, notificationIntent, 0
)
val notification: Notification = NotificationCompat.Builder(this, "$MchannelId")
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setSmallIcon(R.drawable.icon_child)
//.setContentIntent(pendingIntent)
.build()
startForeground(random_number, notification)
}
My Full-Service Class:
const val TAG2 = "Child Service"
class ParentService: Service() {
val db = FirebaseFirestore.getInstance()
private val channelId = "Notification from Service"
var parent_name = userName
override fun onBind(intent: Intent?): IBinder? = null
//OnBind Function Implementation
init {
Log.d(TAG2, "Started Service!")
}
//onCreate Method Implementation
override fun onCreate() {
super.onCreate()
}
//OnStartCommand Override
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Thread{
while (true){
checkStatus()
Thread.sleep(PARENT_CHECK_TIME)
}
}.start()
return START_STICKY
}
private fun checkStatus() {
var listOfNames = ""
var i = 1
val calendar: Calendar = Calendar.getInstance()
var list = ArrayList<String>()
db.collection(LINKED_CHILDS)
.whereEqualTo(USER_PHONE, userPhone)
.get()
.addOnSuccessListener { documents ->
for (document in documents){
val startTime: Long = calendar.getTimeInMillis()
val diff = startTime - (document.data[ACTIVE_STATUS] as Long)
Log.d("TAG", "Time Difference : $diff")
Log.d("TAG", "${document.data[USER_NAME].toString()}")
if (diff> MAX_GAP_TIME){
Log.d("TAG", "Entered IFF")
list.add(document.data[USER_NAME].toString())
}
}
for (name in list){
listOfNames = listOfNames + "$i. Your child $name is not active\n"
i++
createNotification(parent_name, listOfNames, i)
Log.d("TAG Notification ID:", "ID: $i")
}
Log.d("TAG: ", "$listOfNames")
}
}
fun createNotification(parent_name: String, notificationText:String, id: Int){
val MchannelId = channelId+id.toString()
if (Build.VERSION.SDK_INT >= 26) {
val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel(
MchannelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT
)
} else {
TODO("VERSION.SDK_INT < O")
}
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
channel
)
}
val notificationIntent = Intent(this, TabbedActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
id, notificationIntent, 0
)
val notification: Notification = NotificationCompat.Builder(this, "$MchannelId")
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setSmallIcon(R.drawable.icon_child)
//.setContentIntent(pendingIntent)
.build()
startForeground(id, notification)
}
}
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
If you create a non-persistent notification, it will show your notifications. The permanent notification will be used for your service to run in the background.
#RequiresApi(Build.VERSION_CODES.O)
private fun createNotification() {
val intent = Intent(this, TabbedActivity::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 notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.icon_child)
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
with(NotificationManagerCompat.from(this)) {
notify(notifManagerId, notification.build())
notifManagerId++
}
parmanentNotification()
}
this is a permanent notification will not be lost and destroyed will keep the service running permanently
private fun parmanentNotification() {
val notification=NotificationCompat.Builder(this,channelId)
.setSmallIcon(R.drawable.icon_child)
.setContentTitle("Hi $parent_name")
.setContentText("Application service running in the background")
.build()
startForeground(1,notification)
}
you aren't creating a common Notification in this scenario, you are running a Service, which must have a foreground representation on screen. So Activity visible or sticked, fixed Notification, and you are showing it
Now you can have much Notifications using similar code, but don't show them using startForeground, instead use NotificationManager, preferably compat version
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(uniqueId, notification);
or just like you are using it already when creating channel inside if: (getSystemService(NOTIFICATION_SERVICE) as NotificationManager).notify(...)
foreground-related Notification is sticky and lives as long as Service works in background, they are "tied". other Notifications may be configured to be sticky or swipeable, also should be posted on some own Channel (per child? per action?). Note that if you show yet another sticky Notification then you have to release it by own through code, just killing Service won't dismiss it as it does with foreground-related Notification
some DOC in here, read carefully, all answers are there

Notification sound isn't changing from default, even after changing in Android

I have been trying to change the sound of the notification but it isn't changing at all.
It is using the default notification in all cases, even when I have assigned the channel.
Please check the codes below and let me know, where I am going wrong.
Created Notification Channel in Application class
class App : Application() {
override fun onCreate() {
super.onCreate()
createNotificationChannel()
}
private fun createNotificationChannel() {
val ordersChannelId = "Orders"
val orderSoundUri =
Uri.parse("android.resource://" + applicationContext + "/raw/ordernotification")
val attributes = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build()
val VIBRATE_PATTERN = longArrayOf(0,400,800,600,800,800,800,1000)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val ordersChannel =
NotificationChannel(ordersChannelId, "Orders", NotificationManager.IMPORTANCE_HIGH)
ordersChannel.apply {
description = "This is Orders Channel"
setSound(orderSoundUri, attributes)
vibrationPattern = VIBRATE_PATTERN
importance = NotificationManager.IMPORTANCE_HIGH
}
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(ordersChannel)
}
}
Creating Notifications using FireBaseMessagingService
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d("NotificationFire", "From: ${remoteMessage?.data}")
val contentIntent = Intent(applicationContext, OrderInDetailActivity::class.java)
val orderSoundUri = Uri.parse("android.resource://"+applicationContext+"/raw/ordernotification")
val attributes = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build()
val VIBRATE_PATTERN = longArrayOf(0, 500)
val contentPendingIntent = PendingIntent.getActivity(
applicationContext,
0,
contentIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
remoteMessage?.data?.let {
Log.d("NotificationFire", "Message Notification Data: ${it}")
//Message Services handle notification
val notification = NotificationCompat.Builder(this, "Orders")
.setSmallIcon(R.drawable.biskit_logo)
.setContentTitle(remoteMessage.data.toString())
.setContentText(remoteMessage.data.toString())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSound(orderSoundUri)
.setVibrate(VIBRATE_PATTERN)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setContentIntent(contentPendingIntent)
.build()
val notificationManager = NotificationManagerCompat.from(this)
Log.d("NotificationFire","Notification")
notificationManager.notify(1,notification)
}
This code is able to display notifications with the default sound only.
In your sound path you appended applicationContext. It will add some random value in your path. Instead you need to add the package name like this below.
Uri.parse("android.resource://"+context.getPackageName()+"/"+R.raw.FILE_NAME);//Here is FILE_NAME is the name of file that you want to play

How to send fcm notification when app is not running

I have tried many solutions but none of them are worked. I am able receive FCM notification when app is active, but not getting notification when app is background or killed.
you need to create a service class extending FirebaseMessagingService and override onMessageReceived method in that class to send notification
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
try {
message.notification?.let {
showNotification(
it.title ?: "",
it.body ?: ""
)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
you are now getting the notification info from backend and showing it as a notification by using the function showNotification. of course, you must implement the function showNotification. it just a simple function for showing notifications in android
Edit: this the implementation of the function, add this to your class
class MyFirebaseMessagingService : FirebaseMessagingService() {
companion object {
const val channelId = "Channel"
const val channelName = "MyChannel"
const val smallIcon: Int = R.drawable.ic_logo
const val notificationId = 1
}
fun showNotification(myTitle: String, myBody: String) {
val notificationBuilder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder(applicationContext, channelId)
} else {
Notification.Builder(applicationContext)
}
val intent = Intent(applicationContext, HomeActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
applicationContext,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val notificationManager =
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
when {
Build.VERSION.SDK_INT >= 26 -> {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
notificationBuilder
.setContentIntent(pendingIntent)
.setContentText(myBody)
.setSmallIcon(smallIcon)
.setContentTitle(myTitle)
}
Build.VERSION.SDK_INT >= 24 -> notificationBuilder
.setContentText(myBody)
.setContentTitle(myTitle)
.setSmallIcon(smallIcon)
.setContentIntent(pendingIntent)
else -> notificationBuilder
.setContentText(myBody)
.setContentTitle(myTitle)
.setSmallIcon(smallIcon)
.setContentIntent(pendingIntent)
}
notificationManager.notify(notificationId, notificationBuilder.build())
}
}
If you want to get notification when app is background or killed your json object has to be this like:
{
"data":{
"title" : "your_title",
"body" : "your_body"
},
"to": "device_token",
"priority": "high"
}
You can catch notification onMessageReceived

why my Android notification can't be clicked to go inside my app? [duplicate]

This question already has answers here:
Open application after clicking on Notification
(12 answers)
Closed 3 years ago.
I can receive the notification sent from Firebase Cloud Messaging and show it to android device in here
when I click notification from my app, I expect it will go inside my app. but when I click the notification from my app it just doesn't do anything. it seems it can't be clicked.
so how to make it go to inside my app when I click the notification. here is the code I use
creating channel using this code
class App : Application() {
override fun onCreate() {
super.onCreate()
createNotificationChannels()
}
private fun createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val infoChannel = NotificationChannel(
NOTIFICATION_CHANNEL_INFO,
NOTIFICATION_CHANNEL_INFO,
NotificationManager.IMPORTANCE_DEFAULT
)
val importantNews = NotificationChannel(
NOTIFICATION_EVENT_UPDATES,
NOTIFICATION_EVENT_UPDATES,
NotificationManager.IMPORTANCE_HIGH
)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(infoChannel)
notificationManager.createNotificationChannel(importantNews)
}
}
}
and build notification using this code
private fun setUpNotification(title: String, message: String, type: String, imagePath: String) {
val channel = if (type == "Event Updates") NOTIFICATION_EVENT_UPDATES else NOTIFICATION_CHANNEL_INFO
var notification = NotificationCompat.Builder(this, channel)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
if (type == "Event Updates") {
notification = notification
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_EVENT)
} else {
notification = notification
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
}
if (imagePath.isNotEmpty()) {
Glide.with(this)
.asBitmap()
.load(imagePath)
.into(object: SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
notification = notification.setLargeIcon(resource)
val build = notification.build()
notificationManager.notify(1, build)
}
})
} else {
val build = notification.build()
notificationManager.notify(1, build)
}
}
}
you have to use pending intent to achive this
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, Intent(context, TimerService::class.java), 0)
notification.setContentIntent(pendingIntent)

How cast value from SharedPrefereces to FirebaseMessagingService?

I want to design the custom turn-off/on for push notification using SharedPreferences.
How I can get value (true or false) from SharedPreferences in FirebaseMessagingService?
Both my options don’t work:
To get value directly from SharedPrefences but getPreferences isnt work inside FMS.
To pass value from activity to FirebaseMessagingService. But how?
Maybe there is third option which will work. Please help me.
Below is my code file of FirebaseMessagingService
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val CURRENT_PUSH = "currentPush"
private var sPref: SharedPreferences? = null
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
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())
}
override fun onNewToken(s: String?) {
Log.i(C.T, "NEW_TOKEN" + s!!)
}
private fun loadCurrentPushNotification(): Boolean { //to read the status push notification from SharedPreferences
sPref = getPreferences(Context.MODE_PRIVATE) //this is not working
return sPref!!.getBoolean(CURRENT_PUSH, true)
}
}
sPref = getSharedPreferences(CONTEXT)
Unsure what Context.MODE_PRIVATE so you may have to replace with application context
then
return sPref!!.getBoolean(CURRENT_PUSH, true)

Categories

Resources