Issue
This Content is from Stack Overflow. Question asked by kamran
Main Activity
package com.example.pone
import android.content.ContentValues.TAG
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import com.google.firebase.messaging.FirebaseMessaging
import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
const val TOPIC = "/topics/myTopic2"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
FirebaseService.sharedPref = getSharedPreferences("sharedPref", Context.MODE_PRIVATE)
FirebaseMessaging.getInstance().token
.addOnCompleteListener { task ->
if (task.isSuccessful) {
if (task.result != null && !TextUtils.isEmpty(task.result)) {
val token: String = task.result!!
etToken.setText(token.toString())
}
}
}
FirebaseMessaging.getInstance().subscribeToTopic(TOPIC)
btnSend.setOnClickListener {
val title = etTitle.text.toString()
val message = etMessage.text.toString()
val recipientToken = etToken.text.toString()
if(title.isNotEmpty() && message.isNotEmpty() && recipientToken.isNotEmpty()) {
PushNotification(
NotificationData(title, message),
recipientToken
).also {
sendNotification(it)
}
}
}
}
private fun sendNotification(notification: PushNotification) = CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitInstance.api.postNotification(notification)
if(response.isSuccessful) {
Log.d(TAG, "Response: ${Gson().toJson(response)}")
} else {
Log.e(TAG, response.errorBody().toString())
}
} catch(e: Exception) {
Log.e(TAG, e.toString())
}
}
}
Firebase Service Class
package com.example.pone
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_ONE_SHOT
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import kotlin.random.Random
private const val CHANNEL_ID = "my_channel"
class FirebaseService : FirebaseMessagingService() {
companion object {
var sharedPref: SharedPreferences? = null
var token: String?
get() {
return sharedPref?.getString("token", "")
}
set(value) {
sharedPref?.edit()?.putString("token", value)?.apply()
}
}
override fun onNewToken(newToken: String) {
super.onNewToken(newToken)
token = newToken
}
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val intent = Intent(this, MainActivity::class.java)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationID = Random.nextInt()
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(notificationManager)
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, FLAG_ONE_SHOT)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(message.data["title"])
.setContentText(message.data["message"])
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(notificationID, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(notificationManager: NotificationManager) {
val channelName = "channelName"
val channel = NotificationChannel(CHANNEL_ID, channelName, IMPORTANCE_HIGH).apply {
description = "My channel description"
enableLights(true)
lightColor = Color.GREEN
}
notificationManager.createNotificationChannel(channel)
}
}
PushNotification Data Class
data class PushNotification(
val data: NotificationData,
val to: String
)
NotificationAPI interface
import com.example.pone.Constants.Companion.CONTENT_TYPE
import com.example.pone.Constants.Companion.SERVER_KEY
import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface NotificationAPI {
@Headers("Authorization: key=$SERVER_KEY", "Content-Type:$CONTENT_TYPE")
@POST("fcm/send")
suspend fun postNotification(
@Body notification: PushNotification
): Response<ResponseBody>
}
Notification Data Class
data class NotificationData(
val title: String,
val message: String
)
RetroFitIntance class
import com.example.pone.Constants.Companion.BASE_URL
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class RetrofitInstance {
companion object {
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val api by lazy {
retrofit.create(NotificationAPI::class.java)
}
}
}
Constants
class Constants {
companion object {
const val BASE_URL = "https://fcm.googleapis.com"
const val SERVER_KEY = "*****"
const val CONTENT_TYPE = "application/json"
}
}
i am receiving messages on emulator but not real device i am able to send messages to emulator from real device but not receiving messages from emulator to real device
Solution
This is kind of a bug of firebase. try after sometime, you will receive the fcm message on real device too.
This Question was asked in StackOverflow by kamran and Answered by Amartya It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.