Expo 推送通知与后台任务实战

Created on

前言

推送与后台任务是移动端的重要能力,用于消息提醒、数据同步与业务触达。Expo 提供了 expo-notificationsexpo-task-manager,可以在不写原生代码的情况下完成核心流程。

本文介绍推送接入、权限管理、消息处理与后台任务的基础方案。

安装依赖

expo install expo-notifications expo-device expo-task-manager expo-background-fetch

推送权限与 Token 获取

import * as Notifications from "expo-notifications";
import * as Device from "expo-device";

export async function registerForPushToken() {
  if (!Device.isDevice) return null;

  const { status: existing } = await Notifications.getPermissionsAsync();
  let finalStatus = existing;

  if (existing !== "granted") {
    const { status } = await Notifications.requestPermissionsAsync();
    finalStatus = status;
  }

  if (finalStatus !== "granted") return null;

  const token = await Notifications.getExpoPushTokenAsync();
  return token.data;
}

Token 需要上传到你的服务端,由服务端触发推送。

前台与点击事件处理

import { useEffect } from "react";
import * as Notifications from "expo-notifications";

export function useNotificationsHandlers() {
  useEffect(() => {
    const receive = Notifications.addNotificationReceivedListener((notif) => {
      console.log("前台收到消息", notif.request.content);
    });

    const response = Notifications.addNotificationResponseReceivedListener(
      (res) => {
        console.log("点击通知", res.notification.request.content.data);
      }
    );

    return () => {
      receive.remove();
      response.remove();
    };
  }, []);
}

本地通知与定时提醒

import * as Notifications from "expo-notifications";

export async function scheduleLocalNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "任务提醒",
      body: "你有一条待处理任务",
    },
    trigger: { seconds: 5 },
  });
}

后台任务与数据同步

后台任务适用于轻量级同步,例如刷新缓存或上报统计。

import * as TaskManager from "expo-task-manager";
import * as BackgroundFetch from "expo-background-fetch";

const TASK_NAME = "background-sync";

TaskManager.defineTask(TASK_NAME, async () => {
  try {
    // 执行轻量同步
    return BackgroundFetch.BackgroundFetchResult.NewData;
  } catch {
    return BackgroundFetch.BackgroundFetchResult.Failed;
  }
});

export async function registerBackgroundTask() {
  await BackgroundFetch.registerTaskAsync(TASK_NAME, {
    minimumInterval: 15 * 60,
    stopOnTerminate: false,
    startOnBoot: true,
  });
}

注意后台任务有平台限制,不要依赖它执行重任务。

常见问题与建议

小结

Expo 提供的推送与后台任务能力,已经足以覆盖绝大多数业务场景。建议先用 Expo 提供的完整流程打通“权限 → Token → 服务端推送 → 客户端处理”的链路,再根据实际需求做更深度的原生优化。