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

Firebase主题推送无法接收问题排查求助(附Go实现代码)

问题:Firebase主题推送返回message_id但设备无法接收

已将设备Token订阅至Firebase主题,向该主题发送消息时虽返回message_id,但Android和iOS设备均无法接收。
补充说明:Android和iOS设备测试结果一致。

已验证的有效场景:

  • 直接向设备Token发送消息,设备可正常接收;
  • 将同一Token订阅至主题,响应显示绑定成功(成功数为1);
  • Firebase Cloud Messaging控制台中可看到刚订阅的主题;
    以上信息说明Token、主题及订阅操作均有效。

请问有哪些排查步骤或解决方法?

排查步骤与解决方法

1. 完善跨平台推送配置

  • Android端:当前代码已设置Priority: "high",需确认设备厂商系统是否拦截低优先级通知,同时检查AndroidNotification的图标路径是否正确,部分系统会因图标缺失隐藏通知;
  • iOS端:在主题推送的message中添加APNSConfig配置,设置APNSPriority: 10(高优先级),并补充Sound参数,iOS默认可能不会展示无声音的静默通知。

2. 校验主题名称一致性

确认发送主题消息时使用的fm.Topic与订阅时的主题名称完全匹配,包括大小写、特殊字符(如下划线、斜杠),Firebase主题名称区分大小写。

3. 等待主题订阅同步延迟

Firebase主题订阅操作存在异步同步延迟,可能需要几分钟才能在系统中生效。若刚完成订阅就测试推送,可等待10-15分钟后重试。

4. 查看设备端日志排查

  • Android:通过Logcat过滤FirebaseMessaging标签,查看是否有主题消息接收日志,排查是否被系统拦截或解析失败;
  • iOS:通过Xcode控制台查看APNs相关日志,确认设备是否收到推送,排查证书权限或系统设置问题。

5. 对比控制台推送参数

直接在Firebase控制台向该主题发送测试消息,若控制台推送成功,说明代码中的消息构造存在问题,对比控制台生成的Payload与代码中message的差异,重点检查Notification、Data字段的完整性。

6. 验证Firebase实例一致性

确认主题推送使用的Firebase App实例,与Token推送、订阅操作使用的是同一个实例,避免多实例导致的订阅与推送数据不互通。

相关Go代码

初始化Firebase App(正常工作)

func NewFirebaseNotifier() (IExternal, error) {

    var app *firebase.App
    var err error

    if config.GetSystemENV().RunMode == config.RunModeLocal {

        projectID := config.GetFirebaseEnv().ProjectID

        opt := option.WithCredentialsFile(projectID)

        app, err = firebase.NewApp(context.Background(), nil, opt)
        if err != nil {
            return nil, errors.New("error initializing app: " + err.Error())
        }

    } else {

        projectConfig := &firebase.Config{ProjectID: config.GetFirebaseEnv().ProjectID}
        if config.GetFirebaseEnv().ProjectID == "" {
            projectConfig = nil
        }

        app, err = firebase.NewApp(context.Background(), projectConfig)
        if err != nil {
            return nil, errors.New("error initializing app: " + err.Error())
        }
    }

    if config.GetSystemENV().RunMode != config.RunModeProduction {
        fmt.Println("Firebase app initialized", app)
    }

    return &FirebaseNotifier{app: app}, nil
}

向Token推送消息(正常工作)

func (e *FirebaseNotifier) SendMessageToTokens(fm dto.PushMessageTokens) *dto.APIError {

    if err := checkMessage(fm.Message); err != nil {
        return &dto.APIError{
            Err:        err,
            StatusCode: apiprotocol.RequestErr,
        }
    }

    ctx := context.Background()

    fmt.Println("tokens app:", e.app)
    client, err := e.app.Messaging(ctx)
    if err != nil {
        return &dto.APIError{
            Err:        errors.New("error getting Messaging client: " + err.Error()),
            StatusCode: apiprotocol.FirebaseClientErr,
        }
    }

    // See documentation on defining a message payload.
    message := &messaging.MulticastMessage{
        Notification: &messaging.Notification{
            Title:    fm.Message.Title,
            Body:     fm.Message.Body,
            ImageURL: fm.Message.ImageURL,
        },
        Android: &messaging.AndroidConfig{
            Priority: "high",
            Notification: &messaging.AndroidNotification{
                Icon:  "stock_ticker_update",
                Color: "#0000FF",
            },
        },
        Tokens: fm.Tokens,
        Data:   fm.Data,
    }

    // Send a message to the devices subscribed to the provided topic.
    response, err := client.SendEachForMulticast(ctx, message)
    if err != nil {
        return &dto.APIError{
            Err:        errors.New("error sending Messaging: " + err.Error()),
            StatusCode: apiprotocol.FirebaseSendMessageErr,
        }
    }

    if config.GetSystemENV().RunMode != config.RunModeProduction {
        // Response is a message ID string.
        fmt.Println("message tokens:", fm)
        fmt.Println("Successfully sent message:", response)
    }

    return nil
}

订阅主题(正常工作)

func (e *FirebaseNotifier) SubscribeTopic(fs dto.Subscription) *dto.APIError {

    ctx := context.Background()

    client, err := e.app.Messaging(ctx)
    if err != nil {
        return &dto.APIError{
            Err:        errors.New("error getting Messaging client: " + err.Error()),
            StatusCode: apiprotocol.FirebaseClientErr,
        }
    }

    response, err := client.SubscribeToTopic(ctx, fs.DeviceIDs, fs.Topic)
    if err != nil {
        log.Fatalln(err)
    }

    if config.GetSystemENV().RunMode != config.RunModeProduction {
        fmt.Println("subscribe success:", fs)
        if response.FailureCount > 0 {
            // List of errors in the same order as the registration tokens.
            for idx, err := range response.Errors {
                fmt.Println("Failed to subscribe to token:", fs.DeviceIDs[idx], "error:", err)
            }
        }
        fmt.Println(response.SuccessCount, "tokens were subscribed successfully, tokens: ", fs.DeviceIDs)
    }

    return nil

}

向主题推送消息(无法正常工作)

func (e *FirebaseNotifier) SendMessageToTopic(fm dto.PushMessageTopic) *dto.APIError {

    if err := checkMessage(fm.Message); err != nil {
        return &dto.APIError{
            Err:        err,
            StatusCode: apiprotocol.RequestErr,
        }
    }

    ctx := context.Background()

    fmt.Println("topic app:", e.app)
    client, err := e.app.Messaging(ctx)
    if err != nil {
        return &dto.APIError{
            Err:        errors.New("error getting Messaging client: " + err.Error()),
            StatusCode: apiprotocol.FirebaseClientErr,
        }
    }

    // See documentation on defining a message payload.
    message := &messaging.Message{
        Notification: &messaging.Notification{
            Title:    fm.Message.Title,
            Body:     fm.Message.Body,
            ImageURL: fm.Message.ImageURL,
        },
        Android: &messaging.AndroidConfig{
            Priority: "high",
            Notification: &messaging.AndroidNotification{
                Icon:  "stock_ticker_update",
                Color: "#f45342",
            },
        },
        Topic: fm.Topic,
        Data:  fm.Data,
    }

    // Send a message to the devices subscribed to the provided topic.
    response, err := client.Send(ctx, message)
    if err != nil {
        return &dto.APIError{
            Err:        errors.New("error sending Messaging: " + err.Error()),
            StatusCode: apiprotocol.FirebaseSendMessageErr,
        }
    }

    if config.GetSystemENV().RunMode != config.RunModeProduction {
        // Response is a message ID string.
        fmt.Println("message topic:", message)
        fmt.Println("Successfully sent message:", response)
    }

    return nil
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:00:55