# 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 中打开项目** ```bash open ios/OutLive.xcworkspace ``` 2. **运行应用到真机** - 选择真机设备 - 点击 Run (⌘R) 3. **暂停应用执行** - 点击 Pause 按钮(或 ⌘⌃Y) 4. **在 LLDB 控制台中执行命令** ```lldb e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.anonymous.digitalpilates.task"] ``` 5. **恢复应用执行** - 点击 Continue 按钮(或 ⌘⌃Y) 6. **查看日志** - 在 Xcode Console 中查看后台任务执行日志 - 应该看到 `[AppDelegate] ====== 后台任务被触发 ======` ### 方法 2: 使用应用内调试功能 1. **在应用中调用诊断工具** ```typescript import { BackgroundTaskDebugHelper } from "@/services/backgroundTaskDebugHelper"; // 运行完整诊断 const helper = BackgroundTaskDebugHelper.getInstance(); const report = await helper.runFullDiagnostics(); console.log(helper.generateReadableReport(report)); // 手动触发测试任务 await helper.triggerTestTask(); ``` 2. **在开发者页面添加测试按钮** ```typescript // 在 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. **查看执行记录** ```typescript 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 配置: ```xml BGTaskSchedulerPermittedIdentifiers com.anonymous.digitalpilates.task UIBackgroundModes fetch processing ``` 3. 运行诊断工具检查配置 ### 问题 2: 模拟器上不工作 **原因:** iOS 模拟器不完全支持 BGTaskScheduler **解决方案:** 必须在真机上测试 ### 问题 3: 执行频率低于预期 **原因:** iOS 系统根据多个因素决定后台任务执行时机: - 设备使用模式 - 电量状态 - 网络状况 - 应用使用频率 **解决方案:** - 使用 Xcode 模拟触发进行测试 - 在生产环境中接受系统的调度策略 - 不要期望后台任务精确按时执行 ### 问题 4: 任务执行时间过短 **原因:** iOS 通常只给后台任务 30 秒执行时间 **解决方案:** - 优化后台任务逻辑,确保快速完成 - 使用异步操作和超时机制 - 在任务过期前完成关键操作 ## 生产环境监控 ### 添加远程日志记录 ```typescript 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)); } ``` ### 添加性能监控 ```typescript // 在 backgroundTaskManagerV2.ts 中 private async handleBackgroundExecution(): Promise { 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. **测试覆盖** - 在真机上充分测试 - 模拟各种系统状态(低电量、无网络等) - 验证长时间运行的稳定性 ## 参考资源 - [Apple BGTaskScheduler 文档](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler) - [WWDC 2019: Advances in App Background Execution](https://developer.apple.com/videos/play/wwdc2019/707/) - [iOS 后台执行最佳实践](https://developer.apple.com/documentation/backgroundtasks/starting_and_terminating_tasks_during_development)