简体   繁体   English

FCM 在模拟器中工作,但不在真实设备上

[英]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.

相关问题 Flutter Firebase 适用于真实设备 不适用于 Android 仿真器 - Flutter Firebase Works On Real Device Not On Android Emulator 为什么 FCM 无法在 flutter 应用程序中的 android 设备上工作? - Why FCM not working on android device in flutter application? Google 登录在真实设备中不起作用 - Google Sign In not working in Real Device android 模拟器和所有 ios 设备收到的 Fcm 通知,但不是真正的 android 设备 - Fcm notifications received by android emulator and all ios devices but not on real android devices 后台 FCM 消息适用于模拟器,但不适用于设备。 Flutter - “Dart_LookupLibrary:找不到库‘package:my_fcm.dart’。” - Background FCM messages work on emulator but not on device. Flutter - "Dart_LookupLibrary: library 'package:my_fcm.dart' not found." 谷歌登录在模拟器上工作但不在 Android 设备 flutter - Google sign in working on emulator but not on Android device flutter Firebase 手机认证在 Android 真实设备上不起作用 - Firebase phone authentication is not working on Android real device Android Studio 模拟器 Firebase(登录/注册)不工作,但在设备上工作 - Android Studio emulator Firebase (login/register) not working but works on device Firebase 从真实设备接收数据,但不从仿真器接收数据....为什么? - Firebase receives data from real device but doesn't from an emulator....why? firebase仿真器带真机 - firebase emulator with real devices
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM