I am trying to send cloud messages (push notifications) from the firebase console to my app. I have seen similar questions on here but nothing worked for me.
I followed the documentation, watched the tutorial, searched online, and StackOverflow and nothing seems to work for me. MainActivity, I am getting the token and trying to use it to send a test message.
FirebaseInstanceId.getInstance().instanceId
.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "getInstanceId failed", task.exception)
return#OnCompleteListener
}
// Get new Instance ID token
val token = task.result?.token
// Log and toast
val msg = getString(R.string.msg_token_fmt, token)
Log.d(TAG, msg)
})
MyFirebaseMessagingService similar to the code from the documenttaion
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
// [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]
Log.e(TAG, "From: ${remoteMessage.from}")
// Check if message contains a data payload.
if (remoteMessage.data.isNotEmpty()) {
Log.d(TAG, "Message data payload: ${remoteMessage.data}")
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use WorkManager.
scheduleJob()
} else {
// Handle message within 10 seconds
handleNow()
}
}
// Check if message contains a notification payload.
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
sendNotification(it.body.toString())
}
// 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.
}
// [END receive_message]
// [START on_new_token]
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
override fun onNewToken(token: String) {
Log.d(TAG, "Refreshed token: $token")
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token)
}
// [END on_new_token]
/**
* Schedule async work using WorkManager.
*/
private fun scheduleJob() {
// [START dispatch_job]
val work = OneTimeWorkRequest.Builder(MyWorkerActivity::class.java).build()
WorkManager.getInstance().beginWith(work).enqueue()
// [END dispatch_job]
}
/**
* Handle time allotted to BroadcastReceivers.
*/
private fun handleNow() {
Log.d(TAG, "Short lived task is done.")
}
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private fun sendRegistrationToServer(token: String?) {
// TODO: Implement this method to send token to your app server.
Log.d(TAG, "sendRegistrationTokenToServer($token)")
}
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private fun sendNotification(messageBody: String) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT)
val channelId = getString(R.string.default_notification_channel_id)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_stat_sample_notification)
.setContentTitle(getString(R.string.fcm_message))
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build())
}
companion object {
private const val TAG = "MyFirebaseMsgService"
}
}
And inside my AndroidManifest file I have this
<!-- [START firebase_service] -->
<service
android:name=".ui.services.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
I saw a similar question that had an answer to downgrading the firebase messaging dependency, I also tried that with no luck. I will post more If I have to. Any help will be much appreciated, thanks.
First just make sure that testing notification works,inside onNewToken place just log the token and try to send it manually, make sure that your software accept/receive notification while on background.( open up Settings and go to Apps & Notifications. Within that screen, tap on See all X apps (where X is the number of apps you have installed) then select yours and make sure that "background activity" is on.
Try this out also,It works for me.I hope it could help
dependency : implementation 'com.google.firebase:firebase-messaging:20.2.0'
class MyFirebaseMessagingService : FirebaseMessagingService() {
val TAG = "FirebaseMessagingService"
#SuppressLint("LongLogTag")
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "msg received: ${remoteMessage.from}")
if (remoteMessage.notification != null) {
showNotification(remoteMessage.notification?.title, remoteMessage.notification?.body)
}
}
override fun onNewToken(token: String) {
Log.d("TAG", "Refreshed token: $token")
}
private fun showNotification(title: String?, body: String?) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT)
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())
}
}
Turns out I had to retype my Service in order for it to work. I have to remember not to copy and paste any more. Going to leave it here for anybody who faces this problem in the future. Happy coding!
class FCMService : FirebaseMessagingService() {
val TAG = "FCMService"
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
Log.d(TAG,"From: ${remoteMessage.from}")
if (remoteMessage.data.isNotEmpty()) {
Log.d(TAG, "Message data payload: ${remoteMessage.data}")
if (true) {
scheduleJob()
}else {
handleNow()
}
}
remoteMessage.notification?.let {
Log.d(TAG, "Message notification body: ${it.body}")
sendNotification(it.body.toString())
}
}
private fun sendNotification(messageBody: String) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0,
intent,
PendingIntent.FLAG_ONE_SHOT)
val channelId = getString(R.string.default_notification_channel_id)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(
this, channelId
)
.setSmallIcon(R.drawable.ic_stat_sample_notification)
.setContentTitle(getString(R.string.fcm_message))
.setContentText(messageBody)
.setAutoCancel(false)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(0, notificationBuilder.build())
}
override fun onNewToken(token: String) {
//super.onNewToken(token)
Log.d(TAG, token)
}
private fun handleNow() {
Log.d(TAG, "Short lived task done")
}
private fun scheduleJob() {
TODO("Not yet implemented")
}
}
<service
android:name=".ui.services.FCMService"
android:enabled="false"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Related
Once I saw this error, I googled enough and realized it was a manifest meta data problem, so I asked the question after fixing it and doing a lot of work.
ex) manifest
default_notification_channel -> default_notification_channel_id
my log cat
2021-08-15 14:03:05.326 26315-27157/com.project W/FirebaseMessaging: Notification Channel requested (fcm_default_channel) has not been created by the app. Manifest configuration, or default, value will be used.
2021-08-15 14:03:05.327 26315-27157/com.project W/FirebaseMessaging: Notification Channel set in AndroidManifest.xml has not been created by the app. Default value will be used.
my manifest
<service
android:name=".ui.fcm.MyFirebaseMessagingService"
android:stopWithTask="false"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id"/>
and my fcm service class
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Timber.d("Refreshed token: $token")
//TODO : Token save
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Timber.d("MyFirebaseMessagingService onMessageReceived 성공!!!!")
if (remoteMessage.notification != null) {
Timber.d("MyFirebaseMessagingService noti.body = ${remoteMessage.notification?.body}")
sendNotification(remoteMessage)
}
if (remoteMessage.data.isEmpty()) {
return
}
super.onMessageReceived(remoteMessage)
}
private fun sendNotification(remoteMessage: RemoteMessage) {
val uniId: Int = (System.currentTimeMillis() / 7).toInt()
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent =
PendingIntent.getActivity(this, uniId, intent, PendingIntent.FLAG_ONE_SHOT)
val channelId = getString(R.string.default_notification_channel_id)
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(remoteMessage.data["body"].toString())
.setContentText(remoteMessage.data["title"].toString())
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(channelId, "Notice", NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(uniId, notificationBuilder.build())
}
}
I'm asking this question because fcm doesn't work properly while I'm working on saving data to room. The push message is coming, but the data is not logged and I am not sure if the correct data is coming because such an error is coming out.
I haven't been able to solve this problem, can you help me yet?
I am using FirebaseMessagingService to send push notifications to my Pocophone X3 NFC. However, I will send a notification token and erase the notification token from my Firestore database first when logging in and logging out happens. This is to ensure that the notification is sent to the correct user.
To do the above, I have the following code.
#AndroidEntryPoint
class MessagingService :
FirebaseMessagingService(),
FirebaseAuth.AuthStateListener {
#Inject
lateinit var notificationRepository: NotificationRepository
override fun onCreate() {
super.onCreate()
FirebaseAuth.getInstance().addAuthStateListener(this)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val title = remoteMessage.notification?.title
val message = remoteMessage.notification?.body
if (message != null && title != null) {
sendPushNotification(title, message)
}
}
override fun onNewToken(token: String) {
saveTokenToSharedPreferences(token)
authRepository.getUser()?.let {
val uid = it.uid
sendTokenToFirestore(uid, token)
}
}
override fun onAuthStateChanged(auth: FirebaseAuth) {
auth.currentUser?.let {
val uid = it.uid
val savedRegistrationToken =
PreferenceManager.getDefaultSharedPreferences(this)
.getString(getString(R.string.fcm_token_shared_pref_key), "")
savedRegistrationToken?.let { token -> sendTokenToFirestore(uid, token) }
}
}
private fun sendPushNotification(title: String, messageBody: String) {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT)
val channelId = getString(R.string.general_notification_channel_id)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.mlearn_logo)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
channelId,
getString(R.string.general_notification_channel_name),
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
}
private fun saveTokenToSharedPreferences(token: String) {
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
with (sharedPref.edit()) {
putString(getString(R.string.fcm_token_shared_pref_key), token)
apply()
}
}
private fun sendTokenToFirestore(uid: String, token: String) {
GlobalScope.launch(Dispatchers.IO) {
notificationRepository.sendNotificationToken(uid, token)
}
}
companion object {
const val REQUEST_CODE = 0
const val NOTIFICATION_ID = 0
}
}
I also registered the service to the manifest like so.
<service
android:name=".service.MessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
The code is working fine when I install the app for the first time and if I don't do any device restarts or app killing. However, when I either
turn off my phone and turn it back on; or
kill the app from my recent apps list
the FirebaseMessagingService code will no longer run. As a result, when I do log in using a new account, the new account does not have the notification token associated with it because the service isn't running.
How do I make FirebaseMessagingService keep running even on app kills and phone turning off and turning on (i.e. restarts)? Note that the app installed is not signed yet.
add this to your service
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
also, it takes some time to receive FCM messages after restart, that doesnt mean your service isnt running. If you start receiving messages after like 5 mins of restart that means your service is working fine, it just takes some time for new tokens to register
if all else fails, check out this project's implementation of FCM, its solid, restarts automatically and saves tokens to firebase
https://github.com/yahyakhan234/PharmaGO2-master
Let FCM handle notifications on device, if it's not a data message.
How can I force Android to show notification using FCM, even when app is in foreground? I don't want to build my own notification.
I am sending two types of messages to my app: data message and normal notification message. Data messages are handled in onMessageReceived(), no matter if the App is in background or foreground or killed which is OK. But now I am also sending normal notification messages through Firebase Console, and they are automatically displayed when app is in background but when app is in foreground, onMessageReceived() is called. Here, I would need to somehow tell FCM to show the contents without me having to build the notification.
I tried with:
#Override public void onMessageReceived(RemoteMessage remoteMessage) {
if(remoteMessage.getData() == null || !remoteMessage.getData().containsKey("specificKey")) {
// notification msg, let FCM handle it
super.onMessageReceived(remoteMessage); // this is not working - I want FCM to show notification the same as if the app was in background.
return;
} else {
// data message, I'm handling it on my own and showing a custom notification, working fine and well
}
}
But this is my own handling via code and I want FCM to do that somehow. How can I do that?
When the app is not in the foreground, notification messages are handled by the system. This is by definition and there is no way to change the behavior.
If you want to control what is displayed while the app is not in the foreground, you will have to send a data message.
In this, the else part needs to be handled by you to show a custom notification as follows:
class FCMMessagingService: FirebaseMessagingService() {
var dataMap: Map<String, String>? = null
var body: String = ""
var title: String = ""
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
dataMap = remoteMessage?.data
Log.d("Data Map", dataMap.toString())
try {
val jsonObject = JSONObject(dataMap?.get("data")!!)
val contentInfo = jsonObject.get("contentInfo") as JSONObject
val time = contentInfo.getString("time")
var message = jsonObject.getString("message")
message = message.replace("<time>", Utils.getTimeFromTimestamp(time.toLong(), true))
body = message
} catch (e:JSONException) {
e.printStackTrace()
}
title = dataMap?.get("title")!!
if(Foreground.get().foreground) {
sendBroadCast(title , body)
} else {
createNotification(title, body)
}
}
private fun createNotification(title: String, body: String) {
val intent = Intent(this, DashBoardActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, Calendar.getInstance().timeInMillis.toInt(), intent,
PendingIntent.FLAG_ONE_SHOT)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notification = NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.noti)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notification.color = resources.getColor(R.color.toolBarColor)
}
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(Calendar.getInstance().timeInMillis.toInt(), notification.build())
}
private fun sendBroadCast(title: String, body: String) {
val broadCastIntent = Intent(Constant.NOTIFICATION)
broadCastIntent.putExtra("title", title)
broadCastIntent.putExtra("body", body)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadCastIntent)
// val intent = Intent(this, DashBoardActivity::class.java)
// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
}
I believe you will have to do it this way only as FCM won't handle it anyhow for you. I hope, this helps you.
Edit : I forgot to tell, i already try to make a breakpoint on the onRefreshToken and make a Log in that function, but when i start the apps, none of them is running (the breakpoint doesn't start, and the Log doesnt showing in AS's console log). So IMO its pure that the service itself doesn't start.
I make a code where my apps gonna show a notification if there is a data incoming in onMessageReceived. Its can run well, no problem at all, until i try it in Android Jelly Bean.
The notification doesn't showing (i am sure the notification is sent, because the other non JellyBean device is show the notification at the same time.) and then i trying it in KitKat Device, the result is same.
I then try to debug it and no error showing in Android Studio ( I bet because the device got Chinese rom and doesn't have Google play service built in).
Later i change my method and try it in Emulator, and the E/FirebaseInstanceId: Token retrieval failed: PHONE_REGISTRATION_ERROR is showing. I already try it in emulator that have KitKat and JellyBean image installed, the result is same, the same message appear.
This is my code:
AndroidManifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.appname">
///Some activity and meta data here
<service
android:name=".fcm.MyFirebaseInstanceIdService"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service
android:name=".fcm.MyFirebaseMessagingService"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</manifest>
MyFirebaseInstanceIdService
class MyFirebaseInstanceIdService : FirebaseInstanceIdService() {
val TAG = "PushNotifService"
lateinit var name: String
override fun onTokenRefresh() {
val token = FirebaseInstanceId.getInstance().token
}
}
MyFirebaseMessagingService
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val session = SessionManagement(this)
#SuppressLint("LongLogTag")
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.data != null){
val data = remoteMessage.data
val title = data["title"]
val body = data["body"]
showNotification(title, body)
}
}
#SuppressLint("LongLogTag")
override fun onNewToken(token: String?) {
session.updateFCMToken(token)
}
fun subscribeTopic(topic: String?){
//the topic in here is a param send by other activity when the apps lunch
FirebaseMessaging.getInstance().subscribeToTopic(topic).addOnCompleteListener { task ->
if (!task.isSuccessful) {
} else {
}
}
}
//This sendMessageTrainer() is called and run from other activity
fun sendMessageTrainer(){
val contentType = "application/json"
val authorizationKey = ServerHelper.FCMServerKey
val data = "{\"to\": \"/topics/sometopic\",\"data\": {\"title\":\"Request Update\",\"body\":\"New Request.\"}}"
Fuel.post(ServerHelper.FCMServer).header("Content-Type" to contentType, "Authorization" to "key=$authorizationKey").body(data).responseJson{
_, _, result ->
result.failure {
sendMessageTrainer()
}
result.success {
}
}
}
//showNotification() is run if there is a new data/notification from onMessageReceived
private fun showNotification(title: String?, body: String?) {
val intent = Intent(this, LauncherActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
val channelName = getString(R.string.app_name)
val channelID = "default"
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notifyID = 1
val notification = NotificationCompat.Builder(this, channelID)
.setSmallIcon(R.drawable.ic_logo)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(alarmSound)
.setContentIntent(pendingIntent)
.build()
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
val importance = NotificationManager.IMPORTANCE_HIGH
val mChannel = NotificationChannel(channelID, channelName, importance)
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.createNotificationChannel(mChannel)
mNotificationManager.notify(notifyID , notification)
}
Build.VERSION.SDK_INT <= Build.VERSION_CODES.N -> {
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify(notifyID, notification)
}
}
}
}
Thanks and regards,
vl14b
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())
}
}