📌  相关文章
📜  使用Firebase Cloud Messaging发送通知消息

📅  最后修改于: 2021-01-02 03:58:29             🧑  作者: Mango

使用Firebase Cloud Messaging发送通知消息

在本节中,我们将讨论当应用程序处于设备后台时,如何从Notification Composer向开发设备发送测试通知消息。为此,我们必须:

1)创建一个Firebase项目。

2)从助手或控制台将我们的应用程序连接到Firebase,然后将google-services.json文件下载到我们的应用程序目录中。

3)在我们的项目级别build.gradle文件中,确保在我们的buildscript和所有项目部分中都包含Google的Maven存储库。

4)对于应用程序build.gradle文件,我们有两个实现库”

  • 将Cloud Messaging Android库和firebase核心库添加到我们的app / build.gradle文件中:
    1. 实现“ com.google.firebase:firebase-core:17.0.0”
    2. 实现“ com.google.firebase:firebase-messaging:19.0.1”
  • 另外,添加谷歌播放依赖(类路径和应用):
    1. 套用外挂程式:'com.google.gms.google-services'
    2. classpath'com.google.gms:google-services:4.2.0'

5)编辑我们的应用清单

建议和支持通知渠道。 FCM提供具有基本设置的默认通知渠道。如果要创建和使用默认通道,则必须将default_notification_channel_id设置为通知通道对象的ID。当传入消息未明确设置通知通道时,FCM将使用此值:


6)现在,我们将转到主要活动,以确保创建了通知通道。

7)访问设备注册令牌

在我们的应用程序首次启动时,FCM SDK会为客户端应用程序实例生成注册令牌。如果要定位到单个设备,则需要通过扩展FirebaseMessagingService并覆盖onNewToken来访问此令牌。首次启动后可以旋转令牌,因此强烈建议检索最新的更新注册令牌。

注册令牌可能会更改:

  • 应用删除实例ID的时间。
  • 在新设备上还原应用程序时。
  • 用户重新安装/卸载应用程序时。
  • 用户清除应用程序数据时。
  • 检索当前注册令牌

当我们需要检索当前令牌时,调用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

Main_activity.kt

package com.example.firebasecloudmessaging

import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import 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 = 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 token
            FirebaseInstanceId.getInstance().instanceId
                .addOnCompleteListener(OnCompleteListener { 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()
                })
        }
    }

    companion object {
        private const val TAG = "MainActivity"
    }
}

MyFirebaseMessagingService.kt

package com.example.firebasecloudmessaging

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.annotation.NonNull
import androidx.core.app.NotificationCompat
import com.example.firebasecloudmessaging.MainActivity
import com.example.firebasecloudmessaging.R
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class 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"
    }
}

”使用Firebase”使用Firebase

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

”使用Firebase

现在,我们将移至FCM控制台并点击新建通知

”使用Firebase

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

”使用Firebase

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

”使用Firebase

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

”使用Firebase