使用 Kotlin 的 Firebase 云消息传递 Android
Posted
技术标签:
【中文标题】使用 Kotlin 的 Firebase 云消息传递 Android【英文标题】:Firebase Cloud Messaging Android using Kotlin 【发布时间】:2020-07-04 10:39:17 【问题描述】:我正在尝试从 Firebase 控制台向我的应用发送云消息(推送通知)。我在这里看到了类似的问题,但对我没有任何帮助。 我遵循了文档,观看了教程,在线搜索和 ***,似乎没有什么对我有用。 MainActivity,我正在获取令牌并尝试使用它来发送测试消息。
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 类似于文档中的代码
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"
在我的 AndroidManifest 文件中,我有这个
<!-- [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] -->
我看到了一个类似的问题,其中有一个关于降级 firebase 消息传递依赖项的答案,我也尝试过,但没有成功。如果有必要,我会发布更多。任何帮助将不胜感激,谢谢。
【问题讨论】:
【参考方案1】:首先只需确保测试通知有效,在 onNewToken 位置只需记录令牌并尝试手动发送,确保您的软件在后台接受/接收通知。(打开设置并转到应用程序和通知。在该屏幕中,点击查看所有 X 应用程序(其中 X 是您已安装的应用程序数量),然后选择您的应用程序并确保“后台活动”已打开。
也试试这个,它对我有用。我希望它可以帮助
依赖: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())
【讨论】:
如果您的设备是华为,请查看itechify.com/2016/02/01/… 感谢您的回答,将尝试您所说的,我会告诉您进展如何。 我已经尝试了您的所有建议,但没有成功,我找不到“后台活动”选项。如果有帮助,我正在使用 OnePlus 5t 手机。 三星设备中的后台活动,请查看itechify.com/2016/02/01/… 我找不到它,但在我的设置中一切正常。我想这可能是我缺少的东西。再次感谢您提供帮助。【参考方案2】:事实证明,我必须重新输入我的服务才能使其正常工作。我必须记住不要再复制和粘贴了。将把它留给将来遇到这个问题的任何人。编码愉快!
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>
【讨论】:
以上是关于使用 Kotlin 的 Firebase 云消息传递 Android的主要内容,如果未能解决你的问题,请参考以下文章
使用 Kotlin Coroutines 替换 LocalBroadcastManager 进行 Firebase 消息传递
Firebase 云函数 - 对象不能用 JSON 编码 - Kotlin 数据类
未能将价值纳入日志消息? Kotlin - Firebase