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

Expo Notifications中NotificationResponse功能异常求助

Expo/React Native 跨平台全状态通知点击跳转解决方案

问题核心

原方案依赖useLastNotificationResponse存在平台兼容性问题,且未覆盖应用冷启动场景,导致跳转失效或崩溃。需通过冷启动数据获取+实时监听结合的方式,覆盖所有应用状态(关闭、后台、前台),同时处理Android前台跳转的崩溃问题。

分步实现

1. 基础配置检查

  • 确保expo-notifications版本≥0.17.0,与expo-firebase-messaging版本兼容
  • iOS:在app.json中添加后台通知权限:
    "ios": {
      "infoPlist": {
        "UIBackgroundModes": ["remote-notification"]
      }
    }
    

2. 冷启动状态处理

应用完全关闭时,useLastNotificationResponse无法获取数据,需在App初始化时调用getLastNotificationResponseAsync,且需等待导航容器初始化完成后执行跳转。

3. 后台/前台状态监听

使用addNotificationResponseReceivedListener监听实时通知点击,该API可覆盖后台、前台状态,双平台均有效。

4. 崩溃修复(Android前台)

Android前台点击崩溃多因导航未完全初始化,需用InteractionManager.runAfterInteractions确保UI渲染完成后再执行跳转。

完整代码示例

import React, { useEffect, useState, useRef } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import * as Notifications from 'expo-notifications';
import { InteractionManager } from 'react-native';

const Stack = createStackNavigator();

// 示例页面组件(替换为你的实际页面)
const HomeScreen = () => <></>;
const TargetScreen = () => <></>;

// 配置通知展示规则
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

export default function App() {
  const [navigationReady, setNavigationReady] = useState(false);
  const navigationRef = useRef();

  // 通用跳转处理函数
  const navigateFromNotification = (screen) => {
    if (!navigationReady || !screen) return;
    // 确保UI渲染完成后执行跳转,避免Android前台崩溃
    InteractionManager.runAfterInteractions(() => {
      navigationRef.current?.navigate(screen);
    });
  };

  useEffect(() => {
    // 处理冷启动时的通知响应
    const fetchInitialNotification = async () => {
      const response = await Notifications.getLastNotificationResponseAsync();
      if (response?.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER) {
        const targetScreen = response.notification.request.content.data.screen;
        navigateFromNotification(targetScreen);
      }
    };

    // 监听实时通知点击(后台/前台状态)
    const notificationListener = Notifications.addNotificationResponseReceivedListener((response) => {
      if (response.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER) {
        const targetScreen = response.notification.request.content.data.screen;
        navigateFromNotification(targetScreen);
      }
    });

    // 初始化时获取冷启动通知
    fetchInitialNotification();

    // 清理监听
    return () => {
      notificationListener.remove();
    };
  }, [navigationReady]);

  return (
    <NavigationContainer
      ref={navigationRef}
      onReady={() => setNavigationReady(true)} // 标记导航已初始化完成
    >
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Target" component={TargetScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

注意事项

  • 推送Payload必须包含data.screen字段,值需与导航栈中页面名称完全匹配
  • 测试冷启动场景时,需完全关闭应用(划掉后台进程)后再发送推送
  • 避免在通知监听回调中执行耗时操作,防止阻塞UI线程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:09:51