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

Ionic/Cordova iOS应用关闭时onNotificationOpen回调不触发问题排查

解决iOS Ionic/Cordova应用终止状态下推送点击无响应的问题

我之前也踩过这个坑!问题核心在于cordova-plugin-firebase的事件机制差异:当应用处于前台或后台未被杀死时,onNotificationOpen能正常捕获点击事件,但如果应用是从完全终止/关闭状态被推送唤醒的,推送数据不会通过onNotificationOpen返回,而是需要通过getInitialNotification()方法在应用启动时主动获取。

问题根源

iOS系统在应用终止状态下收到推送并被点击时,会直接启动应用,此时推送的初始数据会被存在启动上下文里,而不是触发实时的onNotificationOpen事件——这个方法只负责监听应用运行中的推送交互。

具体解决方案

我们需要修改你的代码,添加对初始推送的处理,同时优化监听逻辑避免重复订阅:

1. 更新push.provider.ts代码

import { Injectable } from '@angular/core';
import { Firebase } from '@ionic-native/firebase';
import { Platform } from 'ionic-angular';

@Injectable()
export class PushNotificationsProvider {
  // 标记是否已初始化监听,避免重复订阅导致多次触发
  private listenersInitialized = false;

  constructor (private firebase: Firebase, private platform: Platform) { }

  init () {
    if (!this.platform.is('cordova')) {
      return;
    }

    // 统一处理权限验证后的推送初始化逻辑
    const setupPush = async () => {
      // 第一步:检查是否是从推送点击启动应用(终止状态)
      const initialNotification = await this.firebase.getInitialNotification();
      if (initialNotification) {
        // 标记为后台点击,复用现有处理逻辑
        this.handleNotification({ ...initialNotification, tap: true });
      }
      // 第二步:初始化运行时的推送监听
      this.initListeners();
    };

    if (this.platform.is('ios')) {
      this.firebase.grantPermission()
        .then(setupPush)
        .catch(err => console.error('iOS权限申请失败:', err));
    } else if (this.platform.is('android')) {
      this.firebase.hasPermission()
        .then(data => {
          if (data && data.isEnabled) {
            setupPush();
          } else {
            // 可选:Android无权限时引导用户开启
            this.firebase.grantPermission().then(setupPush);
          }
        })
        .catch(err => console.error('Android权限检查失败:', err));
    }
  }

  initListeners () {
    if (this.listenersInitialized) return;
    this.listenersInitialized = true;

    this.firebase.onNotificationOpen().subscribe((notification: any) => {
      this.handleNotification(notification);
    });
  }

  handleNotification (notification) {
    if (!notification) {
      return;
    }
    const message = (notification.aps || {}).alert || '无推送内容';
    if (notification.tap) {
      console.log('*** FMC: 从后台/终止状态打开推送:', notification);
      alert('*** FMC: opened in background/terminated: ' + message);
      // 这里添加页面导航逻辑,比如根据自定义字段跳转
      // this.navCtrl.push('TargetPage', { id: notification.customData.id });
    } else {
      console.log('*** FMC: 前台收到推送:', notification);
      alert('*** FMC: opened in foreground: ' + message);
    }
  }
}

2. 优化app.component.ts的初始化逻辑

你之前在platform.resume里重复调用init(),现在因为加了listenersInitialized标记,不会重复订阅,但可以保留调用确保权限变化后能重新初始化:

this.platform.ready().then(() => {
  if (this.platform.is('cordova')) {
    this.pushProvider.init();
    this.platform.resume.subscribe(() => {
      this.pushProvider.init();
    });
  }
});

3. 确保推送Payload格式正确

iOS下的推送Payload必须包含aps字段,自定义导航数据要放在根节点(不要嵌套在aps里),示例Payload:

{
  "aps": {
    "alert": "您有新的消息",
    "sound": "default",
    "badge": 1
  },
  "customData": {
    "targetPage": "OrderDetailPage",
    "orderId": "123456"
  }
}

4. 可选:升级插件版本

你当前使用的cordova-plugin-firebase@1.0.2版本较旧,可能存在iOS推送兼容性问题。建议升级到^2.0.5版本,同时对应升级@ionic-native/firebase到^5.x.x(Ionic 3推荐@ionic-native/firebase@5.36.0)。

验证步骤

  1. 完全关闭应用(从后台划掉)
  2. 发送符合格式的推送通知
  3. 点击通知启动应用,此时应该能触发handleNotification并执行后台/终止状态的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:37:05