[英]FCM working in emulator, but not on real device
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 Firebase 服务 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 PushNotification 数据 Class
data class PushNotification(
val data: NotificationData,
val to: String
)
NotificationAPI interface通知API接口
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通知数据 Class
data class NotificationData(
val title: String,
val message: String
)
RetroFitIntance class 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.
我能够从真实设备向模拟器发送消息,但不能从模拟器向真实设备接收消息。
Update更新
When I try to send message to real device itself, this error happens当我尝试向真实设备本身发送消息时,会发生此错误
2022-09-18 00:54:34.087 8325-8423/com.example.pone E/AndroidRuntime: FATAL EXCEPTION: Firebase-Messaging-Intent-Handle
Process: com.example.pone, PID: 8325
java.lang.IllegalArgumentException: com.example.pone: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:458)
at android.app.PendingIntent.getActivity(PendingIntent.java:444)
at android.app.PendingIntent.getActivity(PendingIntent.java:408)
at com.example.pone.FirebaseService.onMessageReceived(FirebaseService.kt:52)
at com.google.firebase.messaging.FirebaseMessagingService.dispatchMessage(FirebaseMessagingService.java:235)
at com.google.firebase.messaging.FirebaseMessagingService.passMessageIntentToSdk(FirebaseMessagingService.java:185)
at com.google.firebase.messaging.FirebaseMessagingService.handleMessageIntent(FirebaseMessagingService.java:172)
at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(FirebaseMessagingService.java:161)
at com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$EnhancedIntentService(EnhancedIntentService.java:78)
at com.google.firebase.messaging.EnhancedIntentService$$ExternalSyntheticLambda1.run(Unknown Source:6)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.1.0:2)
at java.lang.Thread.run(Thread.java:920)
This is kind of a bug of firebase.这是 firebase 的一种错误。 try after sometime, you will receive the fcm message on real device too.
尝试一段时间后,您也会在真实设备上收到 fcm 消息。
Update更新
Fixed固定的
i replaced FLAG_ONE_SHOT with FLAG_MUTABLE我用 FLAG_MUTABLE 替换了 FLAG_ONE_SHOT
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.