Ionic 4集成FCM插件时iOS端如何无需刷新应用自动更新推送角标
问题根因
你遇到的iOS角标无法自动更新、必须打开APP才变化的问题,完全是推送Payload配置错误+逻辑缺陷导致的,和Cordova FCM插件本身无关。
当前代码的明确错误
- 语法错误:PHP代码中
Authorization请求头的字符串未闭合,'Authorization:key=AAAAF.....,行末尾缺少单引号,会导致cURL请求头格式非法,极端情况下会直接造成推送请求失败。 - Payload结构错误:你将
sound、badge字段放在了请求体根层级,FCM不会将根层级的这两个字段透传给iOS系统的APNs解析模块——只有当APP在前台活跃时,JS层才能读取到这两个字段;APP在后台、杀进程状态下,iOS系统根本拿不到角标、声音配置,自然不会自动更新角标。 - 逻辑错误:
badge值固定写死为1,哪怕字段位置正确,无论用户收到多少条推送,角标最多显示数字1,完全无法实现计数递增。iOS系统本身不会自动累加角标数值,未读数逻辑要么由服务端维护,要么由客户端扩展实现。 - 前端配置缺失:未开启iOS远程通知后台模式,APP在后台时无法正常响应推送的系统级事件。
修复方案
1. 服务端PHP代码修正
优先采用服务端维护未读数的方案(兼容性最好,支持APP杀进程场景):
- 给每个用户在数据库增加
unread_count字段,默认值为0 - 每次给用户发推送时,先将对应
unread_count +1,再把这个动态值传入badge字段 - 用户打开APP、清空未读消息时,前端调用接口把对应用户的
unread_count重置为0
修正后的核心推送代码如下:
<?php function send_notification ($token, $message, $title, $badge = 1) { $path_to_firebase_cm = 'https://fcm.googleapis.com/fcm/send'; // 注意:sound、badge必须放在notification节点内,才能被iOS系统识别 $fields = array( 'registration_ids' => $token, 'notification' => array( 'title' => $title, 'body' => $message, 'sound' => 'default', 'badge' => $badge // 传入动态计算的未读数值,不要写死1 ), 'data' => array( 'message' => $message, 'title' => $title ), 'priority' => 'high', // iOS推送必须设高优先级,保证后台能及时收到 'content_available' => true // 开启后台唤醒权限 ); $headers = array( // 补全缺失的闭合单引号 'Authorization:key=AAAAF替换为你的实际FCM服务端KEY', 'Content-Type:application/json' ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $path_to_firebase_cm); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields)); $result = curl_exec($ch); curl_close($ch); return $result; } // 业务逻辑部分:发推送前先给对应用户累加未读数,查用户token时同步取出当前unread_count,累加后传入send_notification即可
2. 前端Ionic 4配置补全
- 首先在
config.xml中开启iOS远程通知后台模式,添加如下配置:
<config-file parent="UIBackgroundModes" target="*-Info.plist"> <array> <string>remote-notification</string> </array> </config-file>
- 请求推送权限时必须明确申请角标权限:
// 在app.component.ts等初始化逻辑中调用 this.fcm.requestPermission({ badge: true, sound: true, alert: true }).then(() => { // 权限申请成功逻辑 }).catch(err => { // 权限申请失败逻辑 });
- 业务场景下重置角标:比如用户进入APP首页、清空所有未读消息时,调用插件方法清零角标,同时通知服务端重置未读计数:
// 角标清零 this.fcm.setBadge(0);
可选替代方案(无需服务端维护计数)
如果不想在服务端存未读数,可以配置iOS Notification Service Extension,在推送到达客户端时自动读取当前角标值+1再展示,但该方案需要做原生iOS扩展配置,打包流程更复杂,且在部分iOS低版本上存在兼容问题,优先推荐服务端维护计数的方案。
内容的提问来源于stack exchange,提问作者Eleen009
相关产品推荐
相关产品推荐

