为何FCM的messaging().sendToDevice有时无法正常工作?
FCM设备推送未触发问题排查方案
问题重现
使用Firebase Admin SDK调用admin.messaging().sendToDevice()前流程正常,能打印接收方Token,但调用后通知未触发,无法完成推送,相关代码如下:
var firebase = require("firebase-admin"); var serviceAccount = require("./julla-tutorial.json"); console.log("enter in then Firebase Api"); const firebaseToken = [ 'e0T6j1AiRjaa7IXweJniJq:APA91bHNznSHSIey08s-C-c3gchci6wepvhP1QxQyYbmZ8LySI3wnu64iW7Q23GhA6VCdc4yodZoCFOgynfAb5C8O8VE81OcSv_LL-K3ET1IKGZ_6h35n-_q5EKFtfJWlzOqZr4IvpiB', 'dNWnSqyCQbufzv1JutNEWr:APA91bFcI9FDyRxHRBEcdw4791X0e-V0k1FjXcSstUA67l94hSojMRCd6LWr2b57azNEt3z_XLwLljMX4u2mc9cZDrAVm55Mw9CHGyue-09KofWnnHNR9XWBibc4T76xOV_DWX7T2RvW', 'cq65rtuaTCKGk5lHk7UabN:APA91bFR3kAArg6lhuBq7ktNuBk7Z9MXXk3PskqhYa8CgNaEl6MX4TQ5lo35d6XhnCQ4fEkCkyZ_j08evxE9Y4oVCRTEdqsrkccCVTE8Di47lfmDR3i1NdoL3re9oLw6F_uNsnvRoQcq' ] firebase.initializeApp({ credential: firebase.credential.cert(serviceAccount) }) const payload = { notification: { title: 'Demo 2345', body: 'dfghj', sound: 'default', color: 'yellow', android_channel_id: 'default', channel_id: 'default' }, data: { id: 'broadcast', channelId: 'default' } } const options = { priority: 'high', timeToLive: 60 * 60 * 24, // 1 day }; console.log('------payload---',payload); console.log('-----TOKEN_Array----',firebaseToken); console.log('-------options-----',options); firebase.messaging().sendToDevice(firebaseToken, payload, options).then(function (response) { console.log('--------response',response); }) .catch(function (error) { console.log('-------rejet',reject); });
排查步骤及修复建议
1. 修正错误捕获逻辑,查看真实错误信息
代码的catch块中错误变量写错:将reject改为error,否则无法打印真实的错误详情,无法定位问题。修改后:
.catch(function (error) { console.log('-------error', error); });
2. 分析sendToDevice返回的响应结果
打印的response对象包含results数组,每个元素对应传入的Token的推送状态:
- 若存在
error字段,根据错误码判断问题:InvalidRegistration:Token格式错误或无效,需重新获取设备TokenNotRegistered:设备已卸载APP或Token已失效,需移除该TokenMismatchSenderId:服务账号的Sender ID与客户端配置的Sender ID不匹配,检查双方配置
- 若
results中无错误但设备仍未收到通知,说明消息已发送成功,但设备端存在问题。
3. 避免Firebase重复初始化
每次执行代码都会调用firebase.initializeApp(),多次运行会抛出"App already initialized"错误。添加判断逻辑,仅在未初始化时执行:
if (!firebase.apps.length) { firebase.initializeApp({ credential: firebase.credential.cert(serviceAccount) }); }
4. 检查Android通知通道配置
Android 8.0+要求必须创建通知通道才能显示通知,确保客户端已创建ID为default的通道,示例客户端代码(Kotlin):
val channel = NotificationChannel( "default", "Default Channel", NotificationManager.IMPORTANCE_HIGH ).apply { description = "Default notification channel" enableVibration(true) setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), AudioAttributes.DEFAULT_NOTIFICATION) } val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(channel)
5. 检查设备端状态
- 设备是否联网:离线设备会在TTL有效期内等待上线后接收通知
- APP通知权限是否开启:进入设备设置确认APP已允许通知
- 厂商系统限制:部分国产安卓系统会限制后台APP推送,需开启APP的"自启动"权限,或将APP加入白名单
内容的提问来源于stack exchange,提问作者Deep Patel
相关产品推荐
相关产品推荐

