Files
digital-pilates/docs/background-task-testing-guide.md
richarjiang ea22901553 feat(background-task): 完善iOS后台任务系统并优化断食通知和UI体验
- 修复iOS后台任务注册时机问题,确保任务能正常触发
- 添加后台任务调试辅助工具和完整测试指南
- 优化断食通知系统,增加防抖机制避免频繁重调度
- 改进断食自动续订逻辑,使用固定时间而非相对时间计算
- 优化统计页面布局,添加身体指标section标题
- 增强饮水详情页面视觉效果,改进卡片样式和配色
- 添加用户反馈入口到个人设置页面
- 完善锻炼摘要卡片条件渲染逻辑
- 增强日志记录和错误处理机制

这些改进显著提升了应用的稳定性、性能和用户体验,特别是在iOS后台任务执行和断食功能方面。
2025-11-05 11:23:33 +08:00

8.1 KiB
Raw Permalink Blame History

iOS 后台任务测试指南

问题诊断与修复

已识别的问题

  1. AppDelegate 注册时机错误 已修复

    • 问题:后台任务处理器在 super.application() 之后注册
    • 修复:移至 super.application() 之前注册
    • 影响:这是导致任务从未执行的主要原因
  2. 缺少详细日志 已修复

    • 添加了全面的日志记录
    • 改进了错误处理和报告
  3. 测试机制不完善 已修复

    • 添加了调试辅助工具
    • 提供了诊断命令

在真机上测试后台任务

前置条件

  1. 设备要求

    • iOS 13.0 或更高版本
    • 真机(模拟器不支持 BGTaskScheduler
  2. 系统设置

    设置 > Out Live > 后台App刷新 > 开启
    
  3. 开发者设置

    设置 > 开发者 > Background Fetch > 频繁
    

方法 1: 使用 Xcode 模拟后台任务(推荐)

  1. 在 Xcode 中打开项目

    open ios/OutLive.xcworkspace
    
  2. 运行应用到真机

    • 选择真机设备
    • 点击 Run (⌘R)
  3. 暂停应用执行

    • 点击 Pause 按钮(或 ⌘⌃Y
  4. 在 LLDB 控制台中执行命令

    e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.anonymous.digitalpilates.task"]
    
  5. 恢复应用执行

    • 点击 Continue 按钮(或 ⌘⌃Y
  6. 查看日志

    • 在 Xcode Console 中查看后台任务执行日志
    • 应该看到 [AppDelegate] ====== 后台任务被触发 ======

方法 2: 使用应用内调试功能

  1. 在应用中调用诊断工具

    import { BackgroundTaskDebugHelper } from "@/services/backgroundTaskDebugHelper";
    
    // 运行完整诊断
    const helper = BackgroundTaskDebugHelper.getInstance();
    const report = await helper.runFullDiagnostics();
    console.log(helper.generateReadableReport(report));
    
    // 手动触发测试任务
    await helper.triggerTestTask();
    
  2. 在开发者页面添加测试按钮

    // 在 app/developer.tsx 中
    import { BackgroundTaskManager } from "@/services/backgroundTaskManagerV2";
    import { BackgroundTaskDebugHelper } from "@/services/backgroundTaskDebugHelper";
    
    const handleRunDiagnostics = async () => {
      const helper = BackgroundTaskDebugHelper.getInstance();
      const report = await helper.runFullDiagnostics();
      Alert.alert("诊断报告", helper.generateReadableReport(report));
    };
    
    const handleTriggerTask = async () => {
      try {
        await BackgroundTaskManager.getInstance().triggerTaskForTesting();
        Alert.alert("成功", "测试任务已触发");
      } catch (error) {
        Alert.alert("错误", error.message);
      }
    };
    

方法 3: 自然触发(等待系统调度)

  1. 启动应用并确保后台任务已初始化

    • 查看启动日志确认初始化成功
    • 确认有待处理的任务请求
  2. 将应用切换到后台

    • 按 Home 键或使用手势切换
  3. 等待系统触发

    • iOS 系统会在合适的时机触发后台任务
    • 通常在以下情况下:
      • 设备空闲
      • 网络连接良好
      • 电量充足
      • 距离上次执行已过最小间隔
  4. 查看执行记录

    const manager = BackgroundTaskManager.getInstance();
    const lastExecution = await manager.getLastBackgroundCheckTime();
    console.log(
      "上次执行:",
      lastExecution ? new Date(lastExecution) : "从未执行"
    );
    

验证后台任务执行

检查点 1: 应用启动日志

期望看到:

[BackgroundTaskManagerV2] ====== 开始初始化后台任务管理器 ======
[BackgroundTaskManagerV2] 原生模块可用,开始注册事件监听器
[BackgroundTaskManagerV2] 事件监听器注册完成
[BackgroundTaskManagerV2] 后台刷新状态: available
[BackgroundTaskManagerV2] ✅ 后台任务配置成功
[BackgroundTaskManagerV2] 当前待处理的任务请求数量: 1
[BackgroundTaskManagerV2] ====== 初始化完成 ======

检查点 2: 后台任务触发日志

期望看到:

[AppDelegate] ====== 后台任务被触发 ======
[AppDelegate] 任务标识符: com.anonymous.digitalpilates.task
[BackgroundTaskBridge] ====== 开始处理后台任务 ======
[BackgroundTaskBridge] ✅ 有JS监听器发送执行事件
[BackgroundTaskManagerV2] ✅ 收到后台任务执行事件
[BackgroundTaskManagerV2] 开始执行后台任务

检查点 3: 任务执行完成日志

期望看到:

[BackgroundTaskManagerV2] 后台任务执行成功
[BackgroundTaskManagerV2] ✅ 后台任务调度成功

常见问题排查

问题 1: 任务从不执行

可能原因:

  • 后台刷新权限未启用
  • 应用在 Info.plist 中的配置不正确
  • 任务标识符不匹配

解决方案:

  1. 检查系统设置中的后台刷新权限
  2. 验证 Info.plist 配置:
    <key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>com.anonymous.digitalpilates.task</string>
    </array>
    <key>UIBackgroundModes</key>
    <array>
        <string>fetch</string>
        <string>processing</string>
    </array>
    
  3. 运行诊断工具检查配置

问题 2: 模拟器上不工作

原因: iOS 模拟器不完全支持 BGTaskScheduler

解决方案: 必须在真机上测试

问题 3: 执行频率低于预期

原因: iOS 系统根据多个因素决定后台任务执行时机:

  • 设备使用模式
  • 电量状态
  • 网络状况
  • 应用使用频率

解决方案:

  • 使用 Xcode 模拟触发进行测试
  • 在生产环境中接受系统的调度策略
  • 不要期望后台任务精确按时执行

问题 4: 任务执行时间过短

原因: iOS 通常只给后台任务 30 秒执行时间

解决方案:

  • 优化后台任务逻辑,确保快速完成
  • 使用异步操作和超时机制
  • 在任务过期前完成关键操作

生产环境监控

添加远程日志记录

import { BackgroundTaskManager } from "@/services/backgroundTaskManagerV2";
import AsyncStorage from "@/utils/kvStore";

// 记录后台任务执行历史
async function logBackgroundExecution(success: boolean, duration: number) {
  const history = JSON.parse(
    (await AsyncStorage.getItem("@bg_task_history")) || "[]"
  );
  history.push({
    timestamp: Date.now(),
    success,
    duration,
  });

  // 只保留最近 50 条记录
  if (history.length > 50) {
    history.shift();
  }

  await AsyncStorage.setItem("@bg_task_history", JSON.stringify(history));
}

添加性能监控

// 在 backgroundTaskManagerV2.ts 中
private async handleBackgroundExecution(): Promise<void> {
  const startTime = Date.now();

  try {
    await executeBackgroundTasks();
    const duration = Date.now() - startTime;
    logger.info(`后台任务执行成功,耗时: ${duration}ms`);

    // 记录到本地存储或远程服务
    await logBackgroundExecution(true, duration);
  } catch (error) {
    const duration = Date.now() - startTime;
    logger.error(`后台任务执行失败,耗时: ${duration}ms`, error);
    await logBackgroundExecution(false, duration);
  }
}

最佳实践

  1. 快速执行

    • 后台任务应在 30 秒内完成
    • 优先处理关键逻辑
    • 使用异步操作避免阻塞
  2. 错误处理

    • 捕获所有可能的错误
    • 确保任务始终标记为完成
    • 在错误情况下也要重新调度
  3. 电池友好

    • 避免密集计算
    • 限制网络请求数量
    • 使用批处理减少唤醒次数
  4. 用户体验

    • 不要过度依赖后台任务
    • 在应用前台时优先更新数据
    • 提供手动刷新选项
  5. 测试覆盖

    • 在真机上充分测试
    • 模拟各种系统状态(低电量、无网络等)
    • 验证长时间运行的稳定性

参考资源