离线后并非所有通知都显示
Not All Notifications Show after being Offline
我正在测试将物理 (android) 设备调至飞行模式(无 wifi)的情况。当我将设备重新连接到在线时,我想接收所有通知。
目前我只收到了多个通知中的一个。
我搜索了有关此案例的文档 Setting the lifespan of a message,找到了 time_to_live 参数。通过这个参数,我可以编辑通知的生命周期,但我没有使用它,因为默认情况下它被设置为 4 周。就我而言,我在 seconds/minutes.
之后将设备转为在线
以下函数是在可调用的 Cloud Funtion 中实现的,该函数会在设备在线时触发并正常工作。
以下是我发送消息的方式:
async function notifyParticipantForRegistrationStatus(
data: any,
participantDeleted: boolean
) {
const uid = data.uid;
const courseId = data.courseId;
const courseEventSnapshot = await firestore
.collection("CourseEvents")
.doc(courseId)
.get();
const courseEvent = courseEventSnapshot.data() as CourseEvent;
// get tokens for this participant
const registrationTokens: string[] = [];
await firestore
.collection("Users")
.doc(uid)
.collection("Tokens")
.get()
.then((querySnapshot) => {
querySnapshot.forEach(function (doc) {
const tokenObj = doc.data() as Token;
registrationTokens.push(tokenObj.token);
});
})
.catch((error) => {
console.error(`registrationTokens: ${registrationTokens}`);
console.error(error);
});
// transform date from utc to german
const d = utcSecondsToGermanDate(courseEvent.start.seconds);
// send notification to the deletedParticipant
if (registrationTokens.length > 0) {
const message = {
notification: {
title: `Kurs ${courseEvent.courseEventTitle}`,
body: participantDeleted
? `Du wurdest vom Kurs ${courseEvent.courseEventTitle} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} entfernt. Deine Einheit wurde storniert.`
: `Du wurdest zum Kurs ${courseEvent.courseEventTitle} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} registriert.`,
},
tokens: registrationTokens,
} as admin.messaging.MulticastMessage;
fcm
.sendMulticast(message)
.then((response) => {
if (response.failureCount > 0) {
const failedTokens: string | string[] = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(registrationTokens[idx]);
}
});
console.log("List of tokens that caused failures: " + failedTokens);
}
})
.catch((error) => {
console.error(error);
});
}
}
我几乎可以肯定您已经阅读了第一份文档,但我引用它只是为了记录。
FCM usually delivers messages immediately after they are sent. However, this might not always be possible. For example, if the platform is Android, the device could be turned off, offline, or otherwise unavailable. Or FCM might intentionally delay messages to prevent an app from consuming excessive resources and negatively affecting battery life.
When this happens, FCM stores the message and delivers it as soon as it's feasible. While this is fine in most cases, there are some apps for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it is meaningful only for a short period of time before the call is terminated. Or if the message is an invitation to an event, it is useless if received after the event has ended.
我相信您可以将通知消息设置为 non-collapsible,这意味着它们是重要消息,将单独发送,因为每条消息都有不同的内容。
我还认为您可能希望使用 high-priority FCM messages,因为即使设备处于打瞌睡状态,它也能可靠地唤醒应用程序。
另见:
我确实找到了解决办法。感谢@sllopis,我发现 notifications 默认情况下是可折叠的,但 data messages 不是。因此,我确实将消息更改为:
const message = {
data: {
title: `Kurs ${courseEvent.courseEventTitle}`,
body: participantDeleted
? `Du wurdest vom Kurs ${
courseEvent.courseEventTitle
} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} entfernt. Deine Einheit wurde storniert.`
: `Du wurdest zum Kurs ${
courseEvent.courseEventTitle
} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} registriert.`,
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
tokens: registrationTokens,
} as admin.messaging.MulticastMessage;
现在我可以在设备上线后收到多个“通知”了。
注意!!
要在您的应用程序处于后台时捕获并显示此类消息(数据),您必须使用 onBackgroundMessage 而不是 onLaunch 和 onResume 函数。这是一篇对我有帮助的文章:https://medium.com/@sylvainduch/firebase-messaging-catch-them-all-3f9c594734d7
要使 onBackgroundMessage 完全正常工作,您必须按照文档中的步骤操作:https://pub.dev/packages/firebase_messaging
并将此处提供的解决方案添加到新创建的应用程序 class:https://github.com/MaikuB/flutter_local_notifications/issues/238 by @varadkulk
至少 android.
我正在测试将物理 (android) 设备调至飞行模式(无 wifi)的情况。当我将设备重新连接到在线时,我想接收所有通知。
目前我只收到了多个通知中的一个。
我搜索了有关此案例的文档 Setting the lifespan of a message,找到了 time_to_live 参数。通过这个参数,我可以编辑通知的生命周期,但我没有使用它,因为默认情况下它被设置为 4 周。就我而言,我在 seconds/minutes.
之后将设备转为在线以下函数是在可调用的 Cloud Funtion 中实现的,该函数会在设备在线时触发并正常工作。
以下是我发送消息的方式:
async function notifyParticipantForRegistrationStatus(
data: any,
participantDeleted: boolean
) {
const uid = data.uid;
const courseId = data.courseId;
const courseEventSnapshot = await firestore
.collection("CourseEvents")
.doc(courseId)
.get();
const courseEvent = courseEventSnapshot.data() as CourseEvent;
// get tokens for this participant
const registrationTokens: string[] = [];
await firestore
.collection("Users")
.doc(uid)
.collection("Tokens")
.get()
.then((querySnapshot) => {
querySnapshot.forEach(function (doc) {
const tokenObj = doc.data() as Token;
registrationTokens.push(tokenObj.token);
});
})
.catch((error) => {
console.error(`registrationTokens: ${registrationTokens}`);
console.error(error);
});
// transform date from utc to german
const d = utcSecondsToGermanDate(courseEvent.start.seconds);
// send notification to the deletedParticipant
if (registrationTokens.length > 0) {
const message = {
notification: {
title: `Kurs ${courseEvent.courseEventTitle}`,
body: participantDeleted
? `Du wurdest vom Kurs ${courseEvent.courseEventTitle} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} entfernt. Deine Einheit wurde storniert.`
: `Du wurdest zum Kurs ${courseEvent.courseEventTitle} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} registriert.`,
},
tokens: registrationTokens,
} as admin.messaging.MulticastMessage;
fcm
.sendMulticast(message)
.then((response) => {
if (response.failureCount > 0) {
const failedTokens: string | string[] = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(registrationTokens[idx]);
}
});
console.log("List of tokens that caused failures: " + failedTokens);
}
})
.catch((error) => {
console.error(error);
});
}
}
我几乎可以肯定您已经阅读了第一份文档,但我引用它只是为了记录。
FCM usually delivers messages immediately after they are sent. However, this might not always be possible. For example, if the platform is Android, the device could be turned off, offline, or otherwise unavailable. Or FCM might intentionally delay messages to prevent an app from consuming excessive resources and negatively affecting battery life.
When this happens, FCM stores the message and delivers it as soon as it's feasible. While this is fine in most cases, there are some apps for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it is meaningful only for a short period of time before the call is terminated. Or if the message is an invitation to an event, it is useless if received after the event has ended.
我相信您可以将通知消息设置为 non-collapsible,这意味着它们是重要消息,将单独发送,因为每条消息都有不同的内容。
我还认为您可能希望使用 high-priority FCM messages,因为即使设备处于打瞌睡状态,它也能可靠地唤醒应用程序。
另见:
我确实找到了解决办法。感谢@sllopis,我发现 notifications 默认情况下是可折叠的,但 data messages 不是。因此,我确实将消息更改为:
const message = {
data: {
title: `Kurs ${courseEvent.courseEventTitle}`,
body: participantDeleted
? `Du wurdest vom Kurs ${
courseEvent.courseEventTitle
} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} entfernt. Deine Einheit wurde storniert.`
: `Du wurdest zum Kurs ${
courseEvent.courseEventTitle
} an den ${d.getDate()}.${
d.getMonth() + 1 //getMonth() starts from 0
}.${d.getFullYear()} um ${d.getHours()}:${d.getMinutes()} registriert.`,
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
tokens: registrationTokens,
} as admin.messaging.MulticastMessage;
现在我可以在设备上线后收到多个“通知”了。
注意!!
要在您的应用程序处于后台时捕获并显示此类消息(数据),您必须使用 onBackgroundMessage 而不是 onLaunch 和 onResume 函数。这是一篇对我有帮助的文章:https://medium.com/@sylvainduch/firebase-messaging-catch-them-all-3f9c594734d7
要使 onBackgroundMessage 完全正常工作,您必须按照文档中的步骤操作:https://pub.dev/packages/firebase_messaging
并将此处提供的解决方案添加到新创建的应用程序 class:https://github.com/MaikuB/flutter_local_notifications/issues/238 by @varadkulk
至少 android.