📅  最后修改于: 2021-01-02 03:58:29             🧑  作者: Mango
在本节中,我们将讨论当应用程序处于设备后台时,如何从Notification Composer向开发设备发送测试通知消息。为此,我们必须:
1)创建一个Firebase项目。
2)从助手或控制台将我们的应用程序连接到Firebase,然后将google-services.json文件下载到我们的应用程序目录中。
3)在我们的项目级别build.gradle文件中,确保在我们的buildscript和所有项目部分中都包含Google的Maven存储库。
4)对于应用程序build.gradle文件,我们有两个实现库”
5)编辑我们的应用清单
建议和支持通知渠道。 FCM提供具有基本设置的默认通知渠道。如果要创建和使用默认通道,则必须将default_notification_channel_id设置为通知通道对象的ID。当传入消息未明确设置通知通道时,FCM将使用此值:
6)现在,我们将转到主要活动,以确保创建了通知通道。
7)访问设备注册令牌
在我们的应用程序首次启动时,FCM SDK会为客户端应用程序实例生成注册令牌。如果要定位到单个设备,则需要通过扩展FirebaseMessagingService并覆盖onNewToken来访问此令牌。首次启动后可以旋转令牌,因此强烈建议检索最新的更新注册令牌。
注册令牌可能会更改:
当我们需要检索当前令牌时,调用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"
}
}
当我们单击“日志令牌”按钮时,它为我们提供了一个InstanceID令牌,我们在FCM控制台中使用它来发送消息。
现在,我们将移至FCM控制台并点击新建通知。
单击Nee Notification后,它将要求我们填写一些字段,例如通知标题,文本和图像等,然后单击Select test message 。
我们将粘贴复制的InstanceId令牌以添加FCM注册令牌字段,然后单击Test 。
最后一步在我们应用的通知栏中创建一条通知消息。仅当我们的应用程序将在后台运行时,才会显示通知。