Android设备接收重复FCM通知,桌面端正常的问题求助
Android设备接收重复FCM通知,桌面端正常的问题求助
我现在遇到一个很头疼的问题:我做了一个Flask web应用,用Google Sheets API扫描校车位置表格,判断校车所在区域,然后给用户发送包含校车编号、所在象限/区域以及相邻校车的通知。这个应用在桌面设备上完全正常,但在Android上会收到重复的通知——其中一条带网站图标,另一条没有。
一开始我以为是ngrok隧道的问题(我用它把手机连到本地HTTPS的Flask服务),但桌面端用ngrok访问完全没问题,不会发重复通知,所以应该不是ngrok的锅。
我把代码精简到最核心的版本了,保留了问题复现的关键部分,现在这个简化版也会出现同样的重复通知问题:
Flask App代码
from flask import Flask, request, jsonify, render_template, send_from_directory import firebase_admin from firebase_admin import credentials, messaging from flask_cors import CORS import os from dotenv import load_dotenv # Load environment variables load_dotenv() app = Flask(__name__, template_folder='templates', static_folder='static', static_url_path='' ) CORS(app) # Initialize Firebase Admin SDK cred = credentials.Certificate('Core/firetoken.json') # Your Firebase credentials file firebase_admin.initialize_app(cred) @app.route('/firebase-messaging-sw.js') def sw(): response = send_from_directory(app.static_folder, 'firebase-messaging-sw.js') response.headers['Content-Type'] = 'application/javascript' response.headers['Service-Worker-Allowed'] = '/' return response @app.route('/') def home(): return render_template('index.html', firebase_config=dict( api_key=os.getenv('FIREBASE_API_KEY'), auth_domain=os.getenv('FIREBASE_AUTH_DOMAIN'), project_id=os.getenv('FIREBASE_PROJECT_ID'), storage_bucket=os.getenv('FIREBASE_STORAGE_BUCKET'), messaging_sender_id=os.getenv('FIREBASE_MESSAGING_SENDER_ID'), app_id=os.getenv('FIREBASE_APP_ID'), measurement_id=os.getenv('FIREBASE_MEASUREMENT_ID') ), vapid_key=os.getenv('VAPID_KEY') ) @app.route('/store_token', methods=['POST']) def store_token(): data = request.json token = data.get('token') if not token: return jsonify({'error': 'Token is required'}), 400 try: # Send a test notification message = messaging.Message( notification=messaging.Notification( title="Test Notification", body="This is a test notification!" ), token=token ) messaging.send(message) return jsonify({'status': 'Notification sent successfully'}) except Exception as e: return jsonify({'error': str(e)}), 500 if __name__ == '__main__': app.run(debug=True)
HTML Template代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Simple Notification Test</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .container { background-color: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } button { background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 10px 0; } #status { margin: 20px 0; padding: 10px; border-radius: 4px; } .success { background-color: #dff0d8; color: #3c763d; } .error { background-color: #f2dede; color: #a94442; } </style> </head> <body> <div class="container"> <h1>Notification Test</h1> <button id="send-notification">Send Test Notification</button> <p id="status"></p> </div> <script type="module"> import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-app.js"; import { getMessaging, getToken, onMessage } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-messaging.js"; const firebaseConfig = { apiKey: "{{ firebase_config.api_key }}", authDomain: "{{ firebase_config.auth_domain }}", projectId: "{{ firebase_config.project_id }}", storageBucket: "{{ firebase_config.storage_bucket }}", messagingSenderId: "{{ firebase_config.messaging_sender_id }}", appId: "{{ firebase_config.app_id }}", measurementId: "{{ firebase_config.measurement_id }}" }; const vapidKey = "{{ vapid_key }}"; try { const app = initializeApp(firebaseConfig); const messaging = getMessaging(app); // Register service worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/firebase-messaging-sw.js') .then(registration => console.log('Service Worker registered')) .catch(err => console.error('Service Worker registration failed:', err)); } document.getElementById('send-notification').addEventListener('click', async () => { try { const permission = await Notification.requestPermission(); if (permission === 'granted') { const currentRegistration = await navigator.serviceWorker.getRegistration(); const token = await getToken(messaging, { vapidKey: vapidKey, serviceWorkerRegistration: currentRegistration }); const response = await fetch('/store_token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: token }) }); const result = await response.json(); if (!response.ok) throw new Error(result.error); document.getElementById('status').innerText = 'Notification sent successfully!'; document.getElementById('status').className = 'success'; } else { throw new Error('Notification permission denied'); } } catch (error) { document.getElementById('status').innerText = `Error: ${error.message}`; document.getElementById('status').className = 'error'; } }); // Listen for messages onMessage(messaging, (payload) => { document.getElementById('status').innerText = `Received: ${payload.notification.title} - ${payload.notification.body}`; document.getElementById('status').className = 'success'; }); } catch (error) { console.error('Initialization error:', error); document.getElementById('status').innerText = `Error: ${error.message}`; document.getElementById('status').className = 'error'; } </script> </body> </html>
问题的具体表现:Android设备上会收到两条内容完全一致的测试通知,其中一条显示网站的favicon图标,另一条没有任何图标,而桌面端只会收到一条正常的通知。
备注:内容来源于stack exchange,提问作者DavidGordiienko
相关产品推荐
相关产品推荐

