插件
消息传递
@nativescript/firebase-messaging
内容
- 消息传递类
- android
- ios
- app
- isAutoInitEnabled
- showNotificationsWhenInForeground
- isDeviceRegisteredForRemoteMessages
- deleteToken()
- getToken()
- getAPNSToken()
- deleteToken()
- hasPermission()
- onMessage()
- onNotificationTap()
- onToken()
- registerDeviceForRemoteMessages()
- requestPermission()
- subscribeToTopic()
- unregisterDeviceForRemoteMessages()
- unsubscribeFromTopic()
- 消息传递类
简介
此插件允许您在 NativeScript 应用中使用 Firebase Cloud Messaging。
使用 FCM,您可以通知客户端应用有新的电子邮件或其他数据可供同步。您可以发送通知消息以推动用户重新参与和保留。对于即时消息等用例,消息可以将最大 4 KB
的有效负载传输到客户端应用。
FCM 消息可以发送到真实的 Android/iOS 设备和 Android 模拟器。但是,iOS 模拟器不处理云消息。
处理消息的常见用例可能是
- 显示通知(参见 在前景中监听通知消息)。
- 在设备上静默同步消息数据(例如,通过 ApplicationSettings 类)。
- 更新应用程序的 UI。
为 Firebase 设置您的应用
您需要为 Firebase 设置您的应用,然后才能启用 Firebase 消息传递。要为您的 NativeScript 应用设置和初始化 Firebase,请遵循 @nativescript/firebase-core 插件文档中的说明。
将 Firebase Cloud Messaging SDK 添加到您的应用
要将 Firebase Cloud Messaging SDK 添加到您的应用,请执行以下步骤
- 通过在项目的根目录中运行以下命令,安装
@nativescript/firebase-messaging
插件。
npm install @nativescript/firebase-messaging
- 通过导入
@nativescript/firebase-messaging
模块来添加 SDK。您应该在您的应用中导入此模块一次,理想情况下是在主文件(例如app.ts
或main.ts
)中。
import '@nativescript/firebase-messaging'
iOS:请求权限
iOS 阻止包含通知(或“警报”)有效负载的消息显示,除非您已从用户那里获得明确的权限。
要请求权限,请在 firebase().messaging()
返回的 消息传递类 实例上调用 requestPermission 方法。此方法会触发一个本机权限对话框,请求用户的权限。用户可以选择允许或拒绝请求。
import { firebase } from '@nativescript/firebase-core'
import { AuthorizationStatus } from '@nativescript/firebase-messaging-core'
async function requestUserPermission() {
const authStatus = await firebase()
.messaging()
.requestPermission({
ios: {
alert: true,
},
})
const enabled =
authStatus === AuthorizationStatus.AUTHORIZED ||
authStatus === AuthorizationStatus.PROVISIONAL
if (enabled) {
console.log('Authorization status:', authStatus)
const didRegister = await firebase()
.messaging()
.registerDeviceForRemoteMessages()
}
}
Android:请求权限
在 Android 上,您不需要请求用户权限。此方法仍然可以在 Android 设备上调用;但是,并且将始终成功解析。
Firebase Cloud 消息类型以及用户应用如何影响传递
FCM 允许您发送以下两种类型的消息
这些消息的传递方式取决于应用是在前景还是后台。
通知消息传递和应用状态
下表显示了根据应用状态,通知消息如何传递到用户应用。
通知消息类型 | 应用状态 | |
---|---|---|
前景 | 背景 | |
仅通知 | 由 FCM SDK 显示给用户 | 传递给 onMessage 处理程序,供应用代码处理 |
通知 + 可选数据 | 应用收到一个包含两个有效负载的消息对象。 | 应用在通知托盘中收到通知有效负载,当用户点击通知时,数据有效负载将传递给 onMessage 处理程序 |
始终在前景中显示通知
如果您希望在应用程序位于前景时始终显示通知,而无需在发送推送通知时发送其他参数/数据,请将 Messaging
实例的 showNotificationsWhenInForeground 属性设置为 true
import { firebase } from '@nativescript/firebase-core'
firebase().messaging().showNotificationsWhenInForeground = true
在前景中监听通知消息
由于通知消息在应用程序位于后台时会自动显示(参见 通知消息传递和应用状态),因此有时您可能希望手动处理消息的显示。要监听应用程序位于前景时收到消息或在应用程序位于后台时手动处理消息的显示,请将回调函数传递给 消息传递类 实例的 onMessage 方法。回调将。通过此处理程序执行的代码可以与您的应用程序交互(例如,更新状态或 UI)。
例如,您可以在每次传递消息时显示一个新的 Alert
import { alert } from '@nativescript/core'
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.onMessage(async (remoteMessage) => {
alert('A new FCM message arrived!', JSON.stringify(remoteMessage))
})
仅数据消息传递和应用状态
下表显示了根据应用状态,数据消息如何传递到用户应用。
前景 | 背景 |
---|---|
应用在传递给 onMessage 方法的回调函数中收到数据有效负载。 | 应用在传递给 onMessage 方法的回调函数中收到数据有效负载。 |
- 当客户端应用不在前景时,Android 和 iOS 都会将消息视为低优先级并忽略它(即不会发送任何事件)。要允许仅数据消息触发,请将有效负载
priority
属性设置为 Android 的high
,并将contentAvailable
属性设置为 iOS 的true
。
例如,如果使用 Node.js firebase-admin 包发送消息,您将按如下方式设置有效负载
admin.messaging().sendToDevice(
[], // device fcm tokens...
{
data: {
owner: JSON.stringify(owner),
user: JSON.stringify(user),
picture: JSON.stringify(picture),
},
},
{
// Required for background/quit data-only messages on iOS
contentAvailable: true,
// Required for background/quit data-only messages on Android
priority: 'high',
}
)
- 对于 iOS,除了将
contentAvailable
属性设置为true
之外,有效负载还必须包含适当的 APNs 标头。有关 APN 标头的更多信息,请参见 向 APNs 发送通知请求。例如,如果使用 Node.js firebase-admin 包发送消息,有效负载将如下所示
admin.messaging().send({
data: {
//some data
},
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
'apns-push-type': 'background',
'apns-priority': '5',
'apns-topic': '', // your app bundle identifier
},
},
//must include token, topic, or condition
//token: //device token
//topic: //notification topic
//condition: //notification condition
})
从您的服务器发送消息
Cloud Messaging 模块提供必要的工具,使您可以直接从您的服务器发送自定义消息。例如,您可以在将新的聊天消息保存到数据库时向特定设备发送 FCM 消息,并显示通知,或更新本地设备存储,以便立即可以使用该消息。
Firebase 为此目的提供了多种语言的 SDK,例如 Node.JS、Java、Python、C# 和 Go。它还支持通过 HTTP 发送消息。这些方法允许您通过 FCM 服务器直接向用户的设备发送消息。
使用用户设备令牌发送消息
要向设备发送消息,您必须访问其唯一的令牌。令牌由设备自动生成,可以使用 Cloud Messaging 模块访问。令牌应保存在您的服务器上,并在需要时易于访问。
以下示例使用 Cloud Firestore 数据库存储和管理令牌,以及 Firebase Authentication 管理用户的身份。但是,您可以使用您选择的任何数据存储或身份验证方法。
保存令牌
应用程序启动后,您可以调用 getToken 方法在 Messaging 实例上获取唯一的设备令牌。如果您使用不同的推送通知提供商,例如 Amazon SNS,则需要在 iOS 上调用 getAPNSToken
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-messaging';
import { FieldValue } from '@nativescript/firebase-auth';
import '@nativescript/firebase-firestore';
async function saveTokenToDatabase(token) {
// Assume user is already signed in
const userId = firebase().auth().currentUser.uid;
// Add the token to the users datastore
await firebase().firestore()
.collection('users')
.doc(userId)
.update({
tokens: FieldValue.arrayUnion(token),
});
}
// Get the device token
firebase().messaging()
.getToken()
.then(token => {
return saveTokenToDatabase(token);
});
// If using other push notification providers (ie Amazon SNS, etc)
// you may need to get the APNs token instead for iOS:
// if (global.isIOS) {
// saveTokenToDatabase(firebase().messaging().getAPNSToken());
// }
// Listen to whether the token changes
firebase().messaging().onToken(token => {
saveTokenToDatabase(token);
}
上面的代码片段将设备 FCM 令牌存储在远程数据库中。
在 saveTokenToDatabase
方法中,我们将令牌存储在当前用户的文档中。请注意,令牌是通过 FieldValue.arrayUnion 方法添加的。用户可以拥有多个令牌(例如使用 2 台设备),因此确保将所有令牌存储在数据库中非常重要,而 FieldValue.arrayUnion
允许我们做到这一点。
使用存储的令牌
将令牌存储在安全数据存储中后,我们现在可以通过 FCM 向这些设备发送消息。
注意
以下示例使用 Node.JS firebase-admin 包向我们的设备发送消息。但是,您可以使用上面列出的任何 SDK。
在您的服务器环境中设置 firebase-tools
库。设置完成后,我们的脚本需要执行两个操作
- 获取发送消息所需的令牌。
- 向令牌注册的设备发送数据有效负载。假设我们的应用程序类似于 Instagram。用户可以上传图片,其他用户可以“点赞”这些图片。每次帖子被点赞时,我们都希望向上传图片的用户发送一条消息。以下代码模拟了在图片被点赞时使用所有必需信息调用的函数
// Node.js
var admin = require('firebase-admin')
// ownerId - who owns the picture someone liked
// userId - id of the user who liked the picture
// picture - metadata about the picture
async function onUserPictureLiked(ownerId, userId, picture) {
// Get the owners details
const owner = admin.firestore().collection('users').doc(ownerId).get()
// Get the users details
const user = admin.firestore().collection('users').doc(userId).get()
await admin.messaging().sendToDevice(
owner.tokens, // ['token_1', 'token_2', ...]
{
data: {
owner: JSON.stringify(owner),
user: JSON.stringify(user),
picture: JSON.stringify(picture),
},
},
{
// Required for background/quit data-only messages on iOS
contentAvailable: true,
// Required for background/quit data-only messages on Android
priority: 'high',
}
)
}
在验证用户时处理令牌
Firebase Cloud Messaging 令牌与已安装应用程序的实例相关联。默认情况下,只有令牌过期或卸载/重新安装应用程序才会生成新的令牌。
这意味着默认情况下,如果两个用户从同一台设备登录您的应用程序,则相同的 FCM 令牌将用于两个用户。通常,这不是您想要的,因此您必须注意在处理用户注销/登录的同时循环 FCM 令牌。
您何时以及如何使令牌失效并生成新令牌将特定于您的项目,但常见模式是在注销时删除 FCM 令牌并更新您的后端以将其删除。然后,您在登录时获取 FCM 令牌并更新您的后端系统以将新令牌与已登录的用户关联。
请注意,当通过调用 deleteToken 方法删除令牌时,它会立即永久失效。
通过主题发送消息
主题是允许设备订阅和取消订阅命名 PubSub 频道 的机制,所有这些都通过 FCM 管理。您可以通过 FCM 令牌向特定设备发送消息,也可以向主题发送消息,订阅该主题的任何设备都将收到该消息。
主题允许您简化 FCM 服务器集成,因为您不需要保留设备令牌的存储。但是,关于主题有一些需要注意的地方
- 发送到主题的消息不应包含敏感或私人信息。
- 不要为特定用户创建主题以订阅。
- 主题消息支持每个主题的无限订阅。
- 一个应用程序实例最多可以订阅 2000 个主题。
- 每个项目的新的订阅频率受到速率限制。如果您在短时间内发送太多订阅请求,FCM 服务器将返回
429 RESOURCE_EXHAUSTED
(“配额已用尽”)响应。请使用指数退避重试。 - 服务器集成可以一次向多个主题发送单条消息。但是,这限制为
5
个主题。
要了解有关如何向订阅主题的设备发送消息的更多信息,请参阅 Android 上的主题消息 或 向 Apple 平台上的主题发送消息。
订阅主题
要将设备订阅到主题,请在 Messsaging 实例上调用 subscribeToTopic 方法,并使用主题名称(不得包含 ´/´)
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.subscribeToTopic('weather')
.then(() => console.log('Subscribed to topic!'))
取消订阅主题
要取消订阅主题,请使用主题名称调用 unsubscribeFromTopic 方法
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.unsubscribeFromTopic('weather')
.then(() => console.log('Unsubscribed fom the topic!'))
通过主题向用户设备发送消息
主题是允许设备订阅和取消订阅命名 PubSub 频道 的机制,所有这些都通过 FCM 管理。您可以通过 FCM 令牌向特定设备发送消息,也可以向主题发送消息,订阅该主题的任何设备都将收到该消息。
主题允许您简化 FCM 服务器集成,因为您不需要保留设备令牌的存储。但是,关于主题有一些需要注意的地方
- 发送到主题的消息不应包含敏感或私人信息。
- 不要为特定用户创建主题以订阅。
- 主题消息支持每个主题的无限订阅。
- 一个应用程序实例最多可以订阅 2000 个主题。
- 每个项目的新的订阅频率受到速率限制。如果您在短时间内发送太多订阅请求,FCM 服务器将返回
429 RESOURCE_EXHAUSTED
(“配额已用尽”)响应。 - 服务器集成可以一次向多个主题发送单条消息。但是,这限制为
5
个主题。
要了解有关如何向订阅主题的设备发送消息的更多信息,请参阅 Android 上的主题消息 或 向 Apple 平台上的主题发送消息。
订阅主题
要将设备订阅到主题,请在 Messaging 实例上调用 subscribeToTopic 方法,并使用主题名称(不得包含 /
)
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.subscribeToTopic('weather')
.then(() => console.log('Subscribed to topic!'))
取消订阅主题
要取消订阅主题,请使用主题名称调用 unsubscribeFromTopic 方法
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.unsubscribeFromTopic('weather')
.then(() => console.log('Unsubscribed fom the topic!'))
通过主题向用户设备发送消息
以 firebase-admin Admin SDK 为例,我们可以向订阅主题 (weather
) 的设备发送消息
const admin = require('firebase-admin')
const message = {
data: {
type: 'warning',
content: 'A new weather warning has been created!',
},
topic: 'weather', // topic name
}
admin
.messaging()
.send(message)
.then((response) => {
console.log('Successfully sent message:', response)
})
.catch((error) => {
console.log('Error sending message:', error)
})
使用条件向多个主题发送消息
要向主题组合发送消息,请指定一个条件,该条件是一个布尔表达式,指定目标主题。例如,以下条件将向订阅 weather
以及 news
或 traffic
主题的设备发送消息
condition: "'weather' in topics && ('news' in topics || 'traffic' in topics)"
要向此条件发送消息,请将主题键替换为条件
const admin = require('firebase-admin')
const message = {
data: {
content: 'New updates are available!',
},
condition: "'weather' in topics && ('news' in topics || 'traffic' in topics)",
}
admin
.messaging()
.send(message)
.then((response) => {
console.log('Successfully sent message:', response)
})
.catch((error) => {
console.log('Error sending message:', error)
})
在通知有效负载中发送图像
通知撰写器和 FCM API 都支持消息有效负载中的图像链接。
iOS 特定选项
要使用 Admin SDK 成功发送图像,请使用 iOS 的 apns
属性设置 ApnsConfig
选项
const payload = {
notification: {
body: 'This is an FCM notification that displays an image!',
title: 'FCM Notification',
},
apns: {
payload: {
aps: {
'mutable-content': 1,
},
},
fcmOptions: {
imageUrl: 'image-url',
},
},
}
注意
要查看 iOS 可用的配置列表,请查看 官方 Firebase 文档。
Android 特定选项
与 iOS 类似,也需要一些特定于 Android 的配置
const payload = {
notification: {
body: 'This is an FCM notification that displays an image!',
title: 'FCM Notification',
},
android: {
notification: {
image: 'image-url',
},
},
}
注意
有关在 Android 上发送图像的更多信息,请参阅 在通知有效负载中发送图像。
为 iOS 和 Android 发送一个图像通知
可以使用 Admin SDK 发送一个将同时传递到两个平台的通知
const admin = require('firebase-admin')
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
'YOUR_REGISTRATION_TOKEN_2',
]
const message = {
tokens: registrationTokens,
notification: {
body: 'This is an FCM notification that displays an image!',
title: 'FCM Notification',
},
apns: {
payload: {
aps: {
'mutable-content': 1,
},
},
fcmOptions: {
imageUrl: 'image-url',
},
},
android: {
notification: {
imageUrl: 'image-url',
},
},
}
admin
.messaging()
.send(message)
.then((response) => {
console.log('Successfully sent message:', response)
})
.catch((error) => {
console.log('Error sending message:', error)
})
Android:配置推送通知图标和颜色
如果要使用推送通知的特定图标和颜色,请在 App_Resources/Android/src/main/AndroidManifest.xml
文件中对其进行配置
<meta-data android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/your_drawable_name" />
<meta-data android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/ns_primary" />
iOS:在 Xcode 中启用对后台推送通知传递的支持
打开 /platforms/ios/yourproject.xcworkspace (!) 并转到您项目的 target,然后转到“Capabilities”以将其打开(如果尚未打开):
注意
如果未启用此功能,您将在前台收到推送消息,但 **不会在后台** 收到。
复制权利文件
上一步创建了文件 platforms/ios/YourAppName/Resources/YourAppName.entitlements
。要防止文件在运行 ns clean
时被删除,请将其移动并重命名为 app/App_Resources/iOS/app.entitlements
(如果该文件不存在,则创建该文件,否则合并其内容)。该文件中与后台推送相关的相关内容是
<key>aps-environment</key>
<string>development</string>
允许处理收到的后台推送通知
打开 app/App_Resources/iOS/Info.plist
并将以下代码添加到底部
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
API
Messaging 类
android
import { firebase } from '@nativescript/firebase-core'
messagingAndroid: com.google.firebase.messaging.FirebaseMessaging =
firebase().messaging().android
一个 只读
属性,返回 Android 的 Messaging 类实例。
ios
import { firebase } from '@nativescript/firebase-core'
messagingIos: MessagingCore = firebase().messaging().ios
一个 只读
属性,返回 iOS 的 Messaging 类实例。
app
import { firebase } from '@nativescript/firebase-core'
messageApp: FirebaseApp = firebase().messaging().app
一个 只读
属性,返回与该 Cloud Messaging 实例关联的 FirebaseApp 类实例。
isAutoInitEnabled
import { firebase } from '@nativescript/firebase-core'
isAutoInitEnabled: boolean = firebase().messaging().isAutoInitEnabled
// or
firebase().messaging().isAutoInitEnabled = true
确定是否启用或禁用 Firebase Cloud Messaging 的自动初始化。有关 iOS 的此属性的更多信息,请参阅 autoInitEnabled。
showNotificationsWhenInForeground
import { firebase } from '@nativescript/firebase-core'
showNotificationsWhenInForeground: boolean =
firebase().messaging().showNotificationsWhenInForeground
// or
firebase().messaging().showNotificationsWhenInForeground = true
允许您在应用程序处于前台时始终显示通知,而无需在发送推送通知时发送其他参数/数据。
isDeviceRegisteredForRemoteMessages
import { firebase } from '@nativescript/firebase-core'
isDeviceRegisteredForRemoteMessages: boolean =
firebase().messaging().isDeviceRegisteredForRemoteMessages
一个属性,返回一个布尔值,指示应用程序是否已注册以接收远程通知。
getToken()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.getToken()
.then((token: string) => {
console.log('Token: ', token)
})
.catch((error: Error) => {
console.log('Error: ', error)
})
获取用户的设备令牌。有关更多信息,请参阅 getToken()
getAPNSToken()
import { firebase } from '@nativescript/firebase-core';
aPNSToken: string | null = firebase().messaging().getAPNSToken()
返回应用程序当前设备的 Apple 推送通知服务 (APNs) 令牌。有关更多信息,请参阅 apnsToken.
hasPermission()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.hasPermission()
.then((status: AuthorizationStatus) => {
console.log('Authorization status: ', status)
})
.catch((error: Error) => {
console.log('Error: ', error)
})
检查应用程序在 iOS 上是否已获得向用户发送通知的权限。
onMessage()
import { firebase } from '@nativescript/firebase-core'
firebase().messaging().onMessage(listener)
注册一个回调函数,该函数在收到新消息时被调用。
参数 | 类型 | 描述 |
---|---|---|
listener | (message: RemoteMessage) => any | 在收到新消息时调用的回调函数 |
onNotificationTap()
import { firebase } from '@nativescript/firebase-core'
firebase().messaging().onNotificationTap(listener)
注册一个回调函数,该函数在用户点击通知时被调用。
参数 | 类型 | 描述 |
---|---|---|
listener | (message: RemoteMessage) => any | 在收到新消息时调用的回调函数 |
onToken()
import { firebase } from '@nativescript/firebase-core'
firebase().messaging().onToken(listener)
注册一个回调函数,该函数在用户的设备更改其注册令牌时被调用。
参数 | 类型 | 描述 |
---|---|---|
listener | (token: string) => any | 在 |
registerDeviceForRemoteMessages()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.registerDeviceForRemoteMessages()
.then(() => {
console.log('Device registered for remote messages')
})
.catch((error: Error) => {
console.log('Error: ', error)
})
requestPermission()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.requestPermission(permissions)
.then((status: AuthorizationStatus) => {
console.log('Authorization status: ', status)
})
.catch((error: Error) => {
console.log('Error: ', error)
})
参数 | 类型 | 描述 |
---|---|---|
permissions | 权限 | 包含要请求的权限的对象。 |
subscribeToTopic()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.subscribeToTopic(topic)
.then(() => {
console.log('Subscribed to topic')
})
.catch((error: Error) => {
console.log('Error: ', error)
})
有关此方法的描述,请访问 Firebase 网站上的 subscribeToTopic()。
参数 | 类型 | 描述 |
---|---|---|
topic | string | 要订阅的主题名称。 |
unsubscribeFromTopic()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.unsubscribeFromTopic(topic)
.then(() => {
console.log('Unsubscribed from topic')
})
.catch((error: Error) => {
console.log('Error: ', error)
})
有关此方法的描述,请访问 Firebase 网站上的 unsubscribeToTopic()。
参数 | 类型 | 描述 |
---|---|---|
topic | string | 要取消订阅的主题名称。 |
unregisterDeviceForRemoteMessages()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.unregisterDeviceForRemoteMessages()
.then(() => {
console.log('Device unregistered for remote messages')
})
.catch((error: Error) => {
console.log('Error: ', error)
})
deleteToken()
import { firebase } from '@nativescript/firebase-core'
firebase()
.messaging()
.deleteToken()
.then(() => {
console.log('Token deleted')
})
.catch((error: Error) => {
console.log('Error: ', error)
})
有关 deleteToken 方法的描述,请访问 Firebase 网站上的 deleteToken()。
许可证
Apache 许可证 2.0 版