0

I'm trying to send a notification whenever I send a message, but the notification is not displaying even though the message is sent successfully. I have added the necessary dependency and I am also able to send notifications through Firebase.

Here are my getToken() and sendNotification() functions. In the sendNotification() function, the log value for
Response.Listener { response: JSONObject -> Log.d("TAG", "onResponse: $response") } is
D/TAG: onResponse: {"multicast_id":2648883838169160595,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}.

My receiverUid is correct and I'm also able to retrieve the token for the receiver user, and my server key is correct as well.
What is wrong with my code?
Why isn't it working?

 private fun getToken(message: String) {

    receiverUid = intent.getStringExtra("uid")
    val databaseReference = FirebaseDatabase.getInstance().getReference("user").child(receiverUid!!)
    databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val user = dataSnapshot.getValue(User::class.java)
            if (dataSnapshot.exists()) {
                val token = user?.token

                val to = JSONObject()
                to.put("to", token)
                val data = JSONObject()

                val uid = FirebaseAuth.getInstance().currentUser?.uid
                val firebaseRef = FirebaseDatabase.getInstance().getReference("user").child(uid!!)

                firebaseRef.addListenerForSingleValueEvent(object : ValueEventListener {
                    override fun onDataChange(dataSnapshot: DataSnapshot) {
                        val user = dataSnapshot.getValue(User::class.java)

                        val myName = user?.name
                        val myId = user?.uid
                        val myImage = user?.profileImageUrl
                        val chatId = "${receiverUid}${uid}"

                        data.put("hisId", myId)
                        data.put("hisImage", myImage)
                        data.put("title", myName)
                        data.put("message", message)
                        data.put("chatId", chatId)

                        Log.d("hisToken",token.toString())

                        to.put("data", data)
                        sendNotification(to)
                    }
                    override fun onCancelled(error: DatabaseError) {
                        TODO("Not yet implemented")
                    }
                })
            }
        }
        override fun onCancelled(error: DatabaseError) {
            TODO("Not yet implemented")
        }
    })
}

private fun sendNotification(to: JSONObject) {
    val request: JsonObjectRequest = object : JsonObjectRequest(
        Method.POST,
        Constants.NOTIFICATION_URL,
        to,
        Response.Listener { response: JSONObject ->
            Log.d("TAG", "onResponse: $response")
        },
        Response.ErrorListener {
            Log.d("TAG", "onError: $it")
        }) {
        override fun getHeaders(): MutableMap<String, String> {
            val map: MutableMap<String, String> = HashMap()

            map["Authorization"] = "key=" + Constants.SERVER_KEY
            map["Content-type"] = "application/json"
            return map
        }

        override fun getBodyContentType(): String {
            return "application/json"
        }
    }

    val requestQueue = Volley.newRequestQueue(this@ChatActivity)
    request.retryPolicy = DefaultRetryPolicy(
        30000,
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
    )
    requestQueue.add(request)
}

In my SplashActivity I'm retrieving the token as follow and it is saving the value in firebase database

                  val intent = Intent(this@SplashActivity, HomeMain::class.java)
                    FirebaseInstallations.getInstance().getToken(/* forceRefresh= */ true)
                        .addOnCompleteListener { task ->
                            if (task.isSuccessful) {
                                val token = task.result?.token
                                val databaseReference =
                                    FirebaseDatabase.getInstance().getReference("user")
                                        .child(appUtil.getUID()!!)

                                val map: MutableMap<String, Any> = HashMap()
                                map["token"] = token!!
                                databaseReference.updateChildren(map)
                            }
                            startActivity(intent)
                            finish()

And my Firebase Messaging service Class is below

package com.example.chat
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.media.RingtoneManager
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.res.ResourcesCompat
import com.example.chat.bnNavigation.AppUtil
import com.example.chat.bnNavigation.Constants
import com.example.chat.bnNavigation.message.ChatActivity
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import java.util.*
import kotlin.collections.HashMap

class MyFirebaseMessagingService : FirebaseMessagingService() {

    private val appUtil = AppUtil()

    override fun onNewToken(token: String) {
        super.onNewToken(token)
        updateToken(token)
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)

        if (remoteMessage.data.isNotEmpty()) {

            val map: Map<String, String> = remoteMessage.data
            val hisId = map["hisId"]
            val hisImage = map["hisImage"]
            val title = map["title"]
            val message = map["message"]
            val chatId = map["chatId"]

            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
                createOreoNotification(title!!, message!!, hisId!!, hisImage!!, chatId!!)
            else createNormalNotification(title!!, message!!, hisId!!, hisImage!!, chatId!!)

        }
    }

    private fun updateToken(token: String) {

        if(appUtil.getUID() != null) {
            val databaseReference =
                FirebaseDatabase.getInstance().getReference("user").child(appUtil.getUID()!!)
            val map: MutableMap<String, Any> = HashMap()
            map["token"] = token
            databaseReference.updateChildren(map)
        }
    }

    private fun createNormalNotification(
        title: String,
        message: String,
        hisId: String,
        hisImage: String,
        chatId: String
    ) {

        val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)

        val builder = NotificationCompat.Builder(this, Constants.CHANNEL_ID)
        builder.setContentTitle(title)
            .setContentText(message)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setAutoCancel(true)
            .setColor(ResourcesCompat.getColor(resources, R.color.black, null))
            .setSound(uri)

        val intent = Intent(this, ChatActivity::class.java)

        intent.putExtra("hisId", hisId)
        intent.putExtra("hisImage", hisImage)
        intent.putExtra("chatId", chatId)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
        builder.setContentIntent(pendingIntent)
        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        manager.notify(Random().nextInt(85 - 65), builder.build())

    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createOreoNotification(
        title: String,
        message: String,
        hisId: String,
        hisImage: String,
        chatId: String
    ) {

        val channel = NotificationChannel(
            Constants.CHANNEL_ID,
            "Message",
            NotificationManager.IMPORTANCE_HIGH
        )

        channel.setShowBadge(true)
        channel.enableLights(true)
        channel.enableVibration(true)
        channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE

        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannel(channel)

        val intent = Intent(this, ChatActivity::class.java)

        intent.putExtra("hisId", hisId)
        intent.putExtra("hisImage", hisImage)
        intent.putExtra("chatId", chatId)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)

        val notification = Notification.Builder(this, Constants.CHANNEL_ID)
            .setContentTitle(title)
            .setContentText(message)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setAutoCancel(true)
            .setColor(ResourcesCompat.getColor(resources, R.color.gradEnd, null))
            .setContentIntent(pendingIntent)
            .build()

        manager.notify(100, notification)
    }
}
greybeard
  • 2,249
  • 8
  • 30
  • 66
  • *firebaser here* Calls to the FCM REST API require that you specify the FCM *server** key in your code (`map["Authorization"] = "key=" + Constants.SERVER_KEY`). As its name implies, this key should only be used in server-side code, or in an otherwise trusted environment. The reason for this is that anyone who has the FCM server key can send whatever message they want to all of your users. By including this key in your Android app, a malicious user can find it and you're putting your users at risk. See https://stackoverflow.com/a/37993724 for a better solution. – Frank van Puffelen Mar 31 '23 at 15:09

0 Answers0