android firebase通知在一段时间后停止工作(一天或几天)

but5z9lq  于 2023-02-14  发布在  Android
关注(0)|答案(1)|浏览(113)

我对这个问题感到非常沮丧:(
我正在为Android和iOS开发一个应用程序(使用电容器3),我正在通过Firebase通知向应用程序发送通知。(电容器包:@电容器社区/fcm和@电容器/推送通知)。
它工作了一段时间,一天或几天后,应用程序在后台或前台运行(而不是杀死)它停止工作,应用程序没有得到通知(这发生在我的Android设备。
我正在使用主题发送通知,我也尝试通过firebase控制台发送通知,但没有成功。
我不确定这是否意味着注册令牌已经过期,因为我会认为电容器封装应该处理它,因为他们没有谈论这个问题。
我做了一切从电容器推送通知的文件。
当我查看日志时,我可以看到下一个错误:同步主题失败。不会重试同步。INVALID_PARAMETERS。
我的JavaScript代码:

import '@capacitor/core';
import { ActionPerformed, PushNotificationSchema, PushNotifications } from '@capacitor/push-notifications'
import { FCM } from '@capacitor-community/fcm';
import { getMessaging, getToken as firebaseGetToken, onMessage, deleteToken, isSupported } from "firebase/messaging";
import { myAxios } from './generic-functions/my-axios';
const platform = window.Capacitor && window.Capacitor.platform;
const topicIos = `${process.env.REACT_APP_TOPIC}_ios`;
const topicAnd = `${process.env.REACT_APP_TOPIC}_and`;

function isCapacitor(): boolean {
    //check if we are in a capacitor platform
    return window.Capacitor && (window.Capacitor.platform === "android" || window.Capacitor.platform === "ios")
}

export async function InitFCM(destination: string) {
    if (!isCapacitor()) {
        const isNtfSupported = await isSupported()
        if (!isNtfSupported) return

        // web notifications
        Notification.requestPermission().then(function (permission) {
            if (permission === 'granted') {
                subscribeTo(destination);
            } else {
                // Show some error
            }
        });

        const messaging = getMessaging();

        onMessage(messaging, (payload) => {
            let notification = payload.data;

            const notificationOptions: NotificationOptions = {
                badge: notification?.largeIco,
                body: notification?.body,
                icon: notification?.largeIcon
            };

            const title = notification?.title || "";

            // show notification
            navigator.serviceWorker
                .getRegistrations()
                .then((registration) => {
                    if (notification?.sound) {
                        const audio = new Audio(`/notifications/${notification?.sound}`)
                        audio.play()
                    }
                    registration[0].showNotification(title, notificationOptions);
                });
        })
        return
    }
    try {
        console.log('Initializing Push Notifications');

        // Request permission to use push notifications
        // iOS will prompt user and return if they granted permission or not
        // Android will just grant without prompting
        PushNotifications.requestPermissions().then(result => {
            if (result.receive === 'granted') {
                // Register with Apple / Google to receive push via APNS/FCM
                // PushNotifications.register();
                subscribeTo(destination);
            } else {
                // Show some error
            }
        });

        // Some issue with our setup and push will not work
        PushNotifications.addListener('registrationError',
            (error: any) => {
                console.log('Error on registration: ' + JSON.stringify(error));
            }
        );

        // Show us the notification payload if the app is open on our device
        PushNotifications.addListener('pushNotificationReceived',
            (notification: PushNotificationSchema) => {
                console.log('Push received: ' + JSON.stringify(notification));
            }
        );

        // Method called when tapping on a notification
        PushNotifications.addListener('pushNotificationActionPerformed',
            (notification: ActionPerformed) => {
                console.log('Push action performed: ' + JSON.stringify(notification));
            }
        );
    } catch (e) {
        console.log('err in push notifications: ', e);
    }
}

async function subscribeTo(destination: string) {
    if (!isCapacitor()) {
        //subscribe to web topic
        const messaging = getMessaging();
        firebaseGetToken(messaging, { vapidKey: process.env.REACT_APP_FIREBASE_VAPID_KEY }).then(
            async (token) => {
                if (token) {
                    await myAxios.post("/api/notifications/subscribe-to-topic", { token, destination });
                }
            }).catch((err) => {
                console.log('An error occurred while retrieving token. ', err);
            });
        return
    }
    try {
        await PushNotifications.register();
        if (platform === "ios") {
            //subscribe to ios topic
            const resIos = await FCM.subscribeTo({ topic: `${topicIos}_${destination}` });
            console.log(`subscribed to ios Topic ${JSON.stringify(resIos)}`);
        }
        if (platform === "android") {
            //subscribe to android topic
            const resAnd = await FCM.subscribeTo({ topic: `${topicAnd}_${destination}` });
            console.log(`subscribed to android Topic ${JSON.stringify(resAnd)}`);
        }
    } catch (error) {
        console.log(JSON.stringify(error));
    }
}

export async function getToken() {
    try {
        /* const result = */ await FCM.getToken();
        // console.log("TOKEN", result.token);
    } catch (error) {
        console.log(error);
    }
}

export async function unsubscribeFrom(destination?: string) {
    if (!isCapacitor()) {
        const isNtfSupported = await isSupported()
        if (!isNtfSupported || !destination) return
        const messaging = getMessaging();

        //unsubscribe from web topic
        firebaseGetToken(messaging, { vapidKey: process.env.REACT_APP_FIREBASE_VAPID_KEY }).then(
            async (token) => {
                if (token) {
                    await myAxios.post("/api/notifications/unsubscribe-from-topic", { token, destination });
                }
            }).catch((err) => {
                console.log('An error occurred while retrieving token. ', err);
            });

        return
    }
    try {
        await PushNotifications.removeAllListeners();
        if (destination) {
            if (platform === "ios") {
                //unsubscribe from ios topic
                const resIos = await FCM.unsubscribeFrom({ topic: `${topicIos}_${destination}` });
                console.log(`unsubscribed from ios topic ${resIos}`);
            }
            if (platform === "android") {
                //unsubscribe from android topic
                const resAndroid = await FCM.unsubscribeFrom({ topic: `${topicAnd}_${destination}` });
                console.log(`unsubscribed from android topic ${topicAnd}_${destination}: ${resAndroid.message}`);
            }
        }
    } catch (error) {
        console.log(error)
    }
    if (platform === 'android') {
        await FCM.deleteInstance();
    }
}

先谢谢大家!

a11xaf1n

a11xaf1n1#

这是自Android 7.0以来的常见问题。出现该问题的原因是您使用了数据消息。您的代码onMessage(messaging, (payload) => {的这一部分告诉我您依赖于此。这意味着当收到消息时,您的应用代码将处理消息传递,即使在后台也是如此。它将创建一个通知,在设备上显示该消息并播放声音,例如。

电源管理功能过度

有几家设备制造商对电源管理改进得太多了,这导致了以下问题:在几天不活动之后,一个应用程序会被Android操作系统完全杀死。这意味着该应用程序无法再在后台处理收到的消息。供应商做得太过分了。但你对此无能为力。

该怎么办?

要解决这个问题,你应该依靠通知消息。这些消息直接发送到Android操作系统,而不是你的应用。这意味着消息不需要你的应用后台处理。在服务器(发送)端,这意味着你必须修改你的当前消息,并在发送的消息中添加通知信息。

缺点

通知消息的缺点是你无法获取通知中的数据。如果你之前在应用中填充了每个通知的数据,那么只有当你的应用在前台或点击通知时,你才能获取数据。要获取应用中的所有数据,你需要一个服务器API解决方案或其他东西。
为了克服这个问题,你可以在你的应用中添加一个NotificationListener。我不知道如何在Capacitor中实现这一点。https://github.com/Chagall/notification-listener-service-exampleNotificationListener也可以在后台监听发送到Android设备的通知。使用此解决方案,您可以确保通知始终在后台发送,数据也在后台发送。但可能,我不知道,此监听器也被电源管理杀死了。当您使用NotificationListener时,您需要一个特殊权限,必须通过设备设置进行设置(参见上述示例)。

结论

从数据消息改为通知消息。提供一种不同的方式来获取应用中的消息数据。你可以使用NotificationListener,但我不知道它是否可靠。最明显的解决方案是引入一个服务器端API,为应用提供数据。在新的情况下,通知可以可靠地发送到应用。

相关问题