使用Firebase Cloud Messaging发送通知消息

在本节中, 我们将讨论当应用程序处于设备后台时, 如何从Notification Composer向开发设备发送测试通知消息。为此, 我们必须:
1)创建一个Firebase项目。
2)从助手或控制台将我们的应用程序连接到Firebase, 然后将google-services.json文件下载到我们的应用程序目录中。
3)在我们的项目级别build.gradle文件中, 确保在我们的buildscript和所有项目部分中都包含Google的Maven存储库。

使用Firebase Cloud Messaging发送通知消息

文章图片
4)对于应用程序build.gradle文件, 我们有两个实现库”
  1. 将Cloud Messaging Android库和firebase核心库添加到我们的app / build.gradle文件中:’ com.google.firebase:firebase-core:17.0.0’ 的实现’ com.google.firebase:firebase-messaging:19.0的实现.1′
  2. 另外, 添加Google Play依赖项(并应用classpath):apply plugin:’ com.google.gms.google-services’ classpath’ com.google.gms:google-services:4.2.0′
使用Firebase Cloud Messaging发送通知消息

文章图片
5)编辑我们的应用清单
推荐并支持通知渠道。 FCM提供具有基本设置的默认通知渠道。如果要创建和使用默认通道, 则必须将default_notification_channel_id设置为通知通道对象的ID。当传入消息未明确设置通知通道时, FCM将使用此值:
< meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="http://www.srcmini.com/fcm_default_channel"/>

6)现在, 我们将移至主要活动, 以确保创建了通知渠道。
7)访问设备注册令牌
在我们的应用程序首次启动时, FCM SDK会为客户端应用程序实例生成一个注册令牌。如果要定位到单个设备, 则需要通过扩展FirebaseMessagingService并覆盖onNewToken来访问此令牌。首次启动后可以旋转令牌, 因此强烈建议检索最新的更新注册令牌。
注册令牌可能会更改:
  1. 应用删除实例ID的时间。
  2. 在新设备上还原应用程序时。
  3. 用户重新安装/卸载应用程序时。
  4. 用户清除应用程序数据时。
  5. 检索当前注册令牌
【使用Firebase Cloud Messaging发送通知消息】当我们需要检索当前令牌时, 调用FirebaseIntanceId.getInstance()。getInstanceId()。4
FirebaseInstanceId.getInstance().instanceId .addOnCompleteListener{task-?if(!task.isSuccessful){Log.w(TAG, "getInstanceId failed", task.exception)return@OnCompleteListener}//Getting new instance id token val token=task.result?.token//toast and log val msg1=getString(R.string.msg_token_fmt, token)Log.d(TAG, msg1)Toast.makeText(baseContext, msg1, Toast.Length_Short).show())}

9)监控令牌生成
生成新令牌时将触发oneNewToken回调。获取令牌后, 我们可以将其发送到我们的应用服务器并使用首选方法进行存储:
/*** It is called if InstanceID token is modified(update). This may happen if the security of the previous token had been compromised. Essentially this is called when the InstanceID token is generated. */override fun onNewToken(token: String) {Log.d(TAG, "Refreshed token: $token")// If we want to send messages to this application instance or// manage the app's subscription on the server-side, send the// Instance ID token to your app server.sendRegistrationToServer(token)}

activity_main.xml
使用Firebase Cloud Messaging发送通知消息

文章图片
Main_activity.kt
package com.example.firebasecloudmessagingimport android.app.NotificationChannelimport android.app.NotificationManagerimport android.os.Buildimport android.os.Bundleimport android.util.Logimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityimport com.google.android.gms.tasks.OnCompleteListenerimport com.google.firebase.iid.FirebaseInstanceIdimport com.google.firebase.messaging.FirebaseMessagingimport kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.O) {// Creating channel to show notifications.val channelId = getString(R.string.default_notification_channel_id)val channelName = getString(R.string.default_notification_channel_name)val notificationManager = getSystemService(NotificationManager::class.java)notificationManager?.createNotificationChannel(NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW))}// Any data accompanying the notification, if a notification message is tapped.// message is available in the intent extras. // The launcher intent is triggered when the notification is tapped, so any accompanying data can// be handled here. If we want a different intent fired, click_action// set the field of the notification message to the desired intent. The launcher intent// is used when no click_action is specified.//// Handle possible data accompanying notification message.intent.extras?.let {for (key in it.keySet()) {val value = http://www.srcmini.com/intent.extras!!.get(key)Log.d(TAG,"Key: $key Value: $value")}}subscribeButton.setOnClickListener {Log.d(TAG, "Subscribing to my topic")FirebaseMessaging.getInstance().subscribeToTopic("myTopic").addOnCompleteListener { task -> var msg1 = getString(R.string.msg_subscribed)if (!task.isSuccessful) {msg1 = getString(R.string.msg_subscribe_failed)}Log.d(TAG, msg1)Toast.makeText(baseContext, msg1, Toast.LENGTH_SHORT).show()}}logTokenButton.setOnClickListener {// Getting tokenFirebaseInstanceId.getInstance().instanceId.addOnCompleteListener(OnCompleteListener { task -> if (!task.isSuccessful) {Log.w(TAG, "getInstanceId failed", task.exception)return@OnCompleteListener}// Getting new Instance ID tokenval token = task.result?.token// toast and Logval msg1 = getString(R.string.msg_token_fmt, token)Log.d(TAG, msg1)Toast.makeText(baseContext, msg1, Toast.LENGTH_SHORT).show()})}}companion object {private const val TAG = "MainActivity"}}

MyFirebaseMessagingService.kt
package com.example.firebasecloudmessagingimport android.app.NotificationChannelimport android.app.NotificationManagerimport android.app.PendingIntentimport android.content.Contextimport android.content.Intentimport android.os.Buildimport android.util.Logimport androidx.annotation.NonNullimport androidx.core.app.NotificationCompatimport com.example.firebasecloudmessaging.MainActivityimport com.example.firebasecloudmessaging.Rimport com.google.firebase.messaging.FirebaseMessagingServiceimport com.google.firebase.messaging.RemoteMessageclass MyFirebaseMessagingService : FirebaseMessagingService() {/*** It is called when message is received.* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.*/override fun onMessageReceived(remoteMessage: RemoteMessage) {//There are two types of messages, i.e., data messages and notification messages. //The data messages are handled here in onMessageReceived, either the app is in the foreground or background. //The data messages are traditionally used with GCM. //The notification messages are only received here in onMessageReceived when the app is in the foreground, and if the app is in the background, the automatically generated notification is displayed. //If the user taps on the notification, they are returned to the app. //Messages containing both notifications and data payloads are treated as notification messages. //The Firebase console always sends a notification message. //For more see: https://firebase.google.com/docs/cloud-messaging/concept-options// TODO(developer): Handle FCM messages here.Log.d(TAG, "From: ${remoteMessage?.from}")// Check if message contains a data payload.remoteMessage?.data?.isNotEmpty()?.let {Log.d(TAG, "Message data payload: " + remoteMessage.data)}// Check if message contains a notification payload.remoteMessage?.notification?.let {Log.d(TAG, "Message Notification Body: ${it.body}")sendNotification(it.body.toString())}// Also, if we intend on generating our own notifications as a result of a received FCM message, here is where that should be initiated. See the send notification method below.}/*** It called if InstanceID token is modified(update). This may happen if the security of* the previous token had been compromised. This is essentially called when the InstanceID token* is generated, so this is where we would retrieve the token.*/override fun onNewToken(token: String) {Log.d(TAG, "Refreshed token: $token")// If we want to send messages to this application instance or// manage this apps subscription on the server-side, send the// Instance ID token to our app server.sendRegistrationToServer(token)}/*** Preserve token to third-party servers.* Modify this method relate to 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 a token to your app server.}/*** Creating and showing 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 penIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT)val channelId = getString(R.string.default_notification_channel_id)val notificationBuilder = NotificationCompat.Builder(this, channelId).setSmallIcon(R.drawable.ic_stat_ic_notification).setContentTitle(getString(R.string.fcm_message)).setContentText(messageBody).setAutoCancel(true).setContentIntent(penIntent)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(channelId, 1, notificationBuilder.build())}companion object {private const val TAG = "MyFirebaseMsgService"}}


当我们单击“日志令牌”按钮时, 它为我们提供了一个InstanceID令牌, 我们在FCM控制台中使用它来发送消息。

现在, 我们将移至FCM控制台并单击“新建通知”。

单击Nee Notification后, 它将要求我们填写一些字段, 例如通知标题, 文本和图像等, 然后单击Select test message。

我们将粘贴复制的InstanceId令牌以添加FCM注册令牌字段, 然后单击“测试”。

最后一步在我们应用的通知栏中创建一条通知消息。仅当我们的应用程序将在后台运行时, 才会显示通知。

    推荐阅读