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

Expo-notifications:应用关闭/后台状态下通知响应异常问题

问题解答

是的,必须集成expo-task-manager才能解决应用后台/关闭状态下的通知响应问题。

原因说明

你当前使用的addNotificationResponseReceivedListener是前台专用监听器,它依赖应用的JS线程处于活跃状态才能触发。当应用退到后台或完全关闭时,JS线程会被挂起甚至终止,这个监听器自然无法工作。而expo-task-manager的作用是注册由原生系统触发的后台任务——即使JS线程未启动,原生层也能直接触发任务执行你的响应逻辑。

具体实现步骤

1. 安装依赖

确保已安装所需包:

npx expo install expo-task-manager expo-notifications

2. 定义后台任务

在你的notificationServices文件中添加后台任务定义,注意任务名称要全局唯一:

import * as TaskManager from 'expo-task-manager';
import * as Notifications from 'expo-notifications';

// 定义后台任务,任务名称要与后续配置一致
TaskManager.defineTask('NOTIFICATION_RESPONSE_TASK', async ({ data, error }) => {
  if (error) {
    console.error('后台任务执行出错:', error);
    return;
  }
  if (data?.response) {
    const { response } = data;
    // 复用你原来的通知响应逻辑
    if (response.actionIdentifier === "response1") {
      // 注意:friendToken和nickname需要从通知data中获取,或提前存在本地存储
      const message = {
        to: friendToken,
        sound: "default",
        title: `${nickname} sent you a message`,
        body: "Test",
        data: {},
        ios: { _displayInForeground: true },
      };
      try {
        await fetch("https://exp.host/--/api/v2/push/send", {
          method: "POST",
          headers: {
            Accept: "application/json",
            "Accept-encoding": "gzip, deflate",
            "Content-Type": "application/json",
          },
          body: JSON.stringify(message),
        });
      } catch (error) {
        console.log(error);
      }
    }
  }
});

3. 配置通知类别并关联后台任务

修改setNotificationCategoryPumping函数,在定义通知按钮时绑定后台任务:

export const setNotificationCategoryPumping = () => {
  Notifications.setNotificationCategoriesAsync([
    {
      identifier: 'pumping_category',
      actions: [
        {
          identifier: 'response1',
          title: '响应按钮',
          options: {
            ios: {
              foregroundPresentationOptions: { alert: true, sound: true },
              // iOS指定触发的后台任务
              runTask: 'NOTIFICATION_RESPONSE_TASK',
            },
            android: {
              channelId: 'your_custom_channel', // 需提前创建通知渠道
              autoCancel: true,
            },
          },
        },
      ],
    },
  ]);
};

4. 注册后台任务并保留前台监听器

在应用初始化的useEffect中注册后台任务,同时保留前台监听器处理活跃状态下的响应:

useEffect(() => {
  // 注册后台任务
  TaskManager.registerTaskAsync('NOTIFICATION_RESPONSE_TASK')
    .catch(error => console.error('后台任务注册失败:', error));

  // 保留前台监听器,处理应用活跃时的通知响应
  responseListener.current = notificationServices.addNotificationResponseReceivedListener(customUser!);

  // 你的原有注册推送、设置类别等代码...

  return () => {
    // 清理订阅和任务注册
    if (responseListener.current) {
      Notifications.removeNotificationSubscription(responseListener.current);
    }
    TaskManager.unregisterTaskAsync('NOTIFICATION_RESPONSE_TASK')
      .catch(error => console.error('后台任务注销失败:', error));
  };
}, []);

关键修复点

你原有代码中addNotificationResponseReceivedListener的回调未加async,导致await fetch无法正常执行,需修正:

export const addNotificationResponseReceivedListener = (customUser: CustomUser) => {
  return Notifications.addNotificationResponseReceivedListener(async (response) => { // 这里添加async
    if (response.actionIdentifier === "response1") {
      // 原有逻辑现在可以正常使用await
    }
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 08:53:12