You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS通过FCM接入APNs仅发data字段推送无通知弹窗问题排查

问题根因

这个是iOS平台APNs与FCM的交互机制差异导致的,不属于前后端代码bug:

  • FCM给安卓发送仅带data字段的消息时,安卓应用可以自行接收消息后弹出通知
  • 但iOS的系统通知必须依赖APNs载荷中aps字段的alert配置,仅带data的FCM消息属于静默推送,系统不会主动弹出通知,只会触发didReceiveRemoteNotification回调交给应用自行处理。

你可以根据团队情况选择以下任意一种方案解决:


方案1:后端修改(推荐,成本最低,双端兼容)

不需要改动现有安卓逻辑,只需要在构造FCM消息时新增notification字段即可,FCM会自动将该字段内容转换为iOS APNs要求的aps.alert配置,触发系统自动弹通知。

  1. 首先修改FcmMessageReq类,新增Notification结构:
@AllArgsConstructor
@Builder
@Getter
public class FcmMessageReq {
    private boolean validate_only;
    private Message message;

    @Builder
    @AllArgsConstructor
    @Getter
    public static class Message {
        private String token;
        private Data data;
        // 新增Notification字段
        private Notification notification;
    }

    @Builder
    @AllArgsConstructor
    @Getter
    public static class Data {
        private String movingPage;
        private String title;
        private String body;
    }
    
    // 新增Notification静态类
    @Builder
    @AllArgsConstructor
    @Getter
    public static class Notification {
        private String title;
        private String body;
    }
}
  1. 然后修改makeMessage方法,构造消息时传入notification参数:
private String makeMessage(String deviceToken, String title, String body, String movingPage) {
    FcmMessageReq fcmMessage = FcmMessageReq.builder()
            .validate_only(false)
            .message(
                    FcmMessageReq.Message.builder()
                            .token(deviceToken)
                            .data(
                                    FcmMessageReq.Data.builder()
                                            .movingPage(movingPage)
                                            .title(title)
                                            .body(body)
                                            .build()
                            )
                            // 新增notification配置,不影响安卓原有逻辑
                            .notification(
                                    FcmMessageReq.Notification.builder()
                                            .title(title)
                                            .body(body)
                                            .build()
                            )
                            .build()
            )
            .build();
    try {
        return objectMapper.writeValueAsString(fcmMessage);
    } catch (Exception exception) {
        log.error("{}", exception.getStackTrace());
        return null;
    }
}

方案2:iOS端修改(适用于后端无法调整的场景)

如果后端暂时没法改动代码,你可以在收到静默推送的回调里,手动触发本地通知弹出,操作如下:

  1. 首先确保App启动时已经申请了通知权限,在didFinishLaunchingWithOptions中添加如下代码:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
    if granted {
        application.registerForRemoteNotifications()
    }
}
  1. 修改didReceiveRemoteNotification方法,收到数据后手动构造本地通知弹出:
func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
{
    print ("didreceiveremotenoti")
    print ("UIStart",userInfo,"UIFIN")
    
    // 取出data字段中的title和body
    if let title = userInfo["title"] as? String, 
       let body = userInfo["body"] as? String,
       let movingPage = userInfo["movingPage"] as? String {
        // 构造本地通知内容
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = body
        content.sound = .default
        // 存储自定义参数,供用户点击通知后跳转逻辑使用
        content.userInfo = ["movingPage": movingPage]
        
        // 触发本地通知
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
        UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
                print("本地通知弹出失败:\(error)")
                completionHandler(.failed)
                return
            }
            completionHandler(.newData)
        }
        return
    }

    guard let aps = userInfo["aps"] as? [String: AnyObject] else {
        completionHandler(.failed)
        return
    }
    print ("APS START",aps,"APSFIN")
    completionHandler(.newData)
}

注意:该方案受iOS静默推送配额限制,系统每日对静默推送的接收次数有上限,超出后消息会被丢弃,不适合高频推送或者营销类推送场景。


内容的提问来源于stack exchange,提问作者Kyongkun Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:24:04