feat: 添加后台任务调试工具并优化水提醒任务逻辑
This commit is contained in:
177
services/backgroundTaskDebugger.ts
Normal file
177
services/backgroundTaskDebugger.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { BackgroundTaskManager } from './backgroundTaskManager';
|
||||
|
||||
/**
|
||||
* 后台任务调试工具
|
||||
* 提供简单的调试和测试功能
|
||||
*/
|
||||
export class BackgroundTaskDebugger {
|
||||
private static instance: BackgroundTaskDebugger;
|
||||
|
||||
static getInstance(): BackgroundTaskDebugger {
|
||||
if (!BackgroundTaskDebugger.instance) {
|
||||
BackgroundTaskDebugger.instance = new BackgroundTaskDebugger();
|
||||
}
|
||||
return BackgroundTaskDebugger.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后台任务诊断信息
|
||||
*/
|
||||
async getDiagnosticInfo(): Promise<{
|
||||
taskManager: any;
|
||||
storage: any;
|
||||
}> {
|
||||
const taskManager = BackgroundTaskManager.getInstance();
|
||||
|
||||
return {
|
||||
taskManager: {
|
||||
isInitialized: await this.getTaskManagerInitStatus(),
|
||||
status: await taskManager.getStatus(),
|
||||
statusText: await taskManager.checkStatus(),
|
||||
},
|
||||
storage: await this.getRelevantStorageValues(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动测试后台任务
|
||||
*/
|
||||
async testBackgroundTask(): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
executionTime: number;
|
||||
}> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const taskManager = BackgroundTaskManager.getInstance();
|
||||
await taskManager.testBackgroundTask();
|
||||
|
||||
const executionTime = Date.now() - startTime;
|
||||
|
||||
return {
|
||||
success: true,
|
||||
executionTime
|
||||
};
|
||||
} catch (error) {
|
||||
const executionTime = Date.now() - startTime;
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
executionTime
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理后台任务相关数据
|
||||
*/
|
||||
async clearBackgroundTaskData(): Promise<void> {
|
||||
const keys = [
|
||||
'@last_background_water_check',
|
||||
'@last_background_test_notification',
|
||||
];
|
||||
|
||||
for (const key of keys) {
|
||||
try {
|
||||
await AsyncStorage.removeItem(key);
|
||||
console.log(`已清理存储键: ${key}`);
|
||||
} catch (error) {
|
||||
console.error(`清理存储键失败 ${key}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置后台任务管理器
|
||||
*/
|
||||
async resetBackgroundTaskManager(): Promise<void> {
|
||||
try {
|
||||
const taskManager = BackgroundTaskManager.getInstance();
|
||||
await taskManager.stop();
|
||||
await this.clearBackgroundTaskData();
|
||||
|
||||
// 重新初始化
|
||||
await taskManager.initialize();
|
||||
|
||||
console.log('后台任务管理器已重置');
|
||||
} catch (error) {
|
||||
console.error('重置后台任务管理器失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用测试通知
|
||||
*/
|
||||
async enableTestNotification(): Promise<void> {
|
||||
try {
|
||||
await AsyncStorage.setItem('@enable_test_notification', 'true');
|
||||
console.log('已启用测试通知');
|
||||
} catch (error) {
|
||||
console.error('启用测试通知失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用测试通知
|
||||
*/
|
||||
async disableTestNotification(): Promise<void> {
|
||||
try {
|
||||
await AsyncStorage.removeItem('@enable_test_notification');
|
||||
console.log('已禁用测试通知');
|
||||
} catch (error) {
|
||||
console.error('禁用测试通知失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否启用了测试通知
|
||||
*/
|
||||
async isTestNotificationEnabled(): Promise<boolean> {
|
||||
try {
|
||||
const enabled = await AsyncStorage.getItem('@enable_test_notification');
|
||||
return enabled === 'true';
|
||||
} catch (error) {
|
||||
console.error('检查测试通知状态失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async getTaskManagerInitStatus(): Promise<boolean> {
|
||||
try {
|
||||
const taskManager = BackgroundTaskManager.getInstance();
|
||||
const status = await taskManager.getStatus();
|
||||
const statusText = await taskManager.checkStatus();
|
||||
return statusText !== '受限制';
|
||||
} catch (error) {
|
||||
console.error('获取任务管理器状态失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async getRelevantStorageValues(): Promise<Record<string, any>> {
|
||||
const keys = [
|
||||
'@last_background_water_check',
|
||||
'@last_background_test_notification',
|
||||
'@enable_test_notification',
|
||||
];
|
||||
|
||||
const values: Record<string, any> = {};
|
||||
|
||||
for (const key of keys) {
|
||||
try {
|
||||
const value = await AsyncStorage.getItem(key);
|
||||
values[key] = value;
|
||||
} catch (error) {
|
||||
values[key] = `Error: ${error}`;
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
export const backgroundTaskDebugger = BackgroundTaskDebugger.getInstance();
|
||||
@@ -31,10 +31,25 @@ async function executeWaterReminderTask(): Promise<void> {
|
||||
try {
|
||||
console.log('执行喝水提醒后台任务...');
|
||||
|
||||
// 获取当前状态
|
||||
const state = store.getState();
|
||||
const waterStats = state.water.todayStats;
|
||||
const userProfile = state.user.profile;
|
||||
// 获取当前状态,添加错误处理
|
||||
let state;
|
||||
try {
|
||||
state = store.getState();
|
||||
} catch (error) {
|
||||
console.log('无法获取 Redux state,使用本地存储:', error);
|
||||
// 使用本地存储作为后备方案
|
||||
const dailyGoal = await getWaterGoalFromStorage();
|
||||
if (!dailyGoal || dailyGoal <= 0) {
|
||||
console.log('没有设置喝水目标,跳过喝水提醒');
|
||||
return;
|
||||
}
|
||||
// 简化的提醒逻辑
|
||||
await sendSimpleWaterReminder();
|
||||
return;
|
||||
}
|
||||
|
||||
const waterStats = state.water?.todayStats;
|
||||
const userProfile = state.user?.profile;
|
||||
|
||||
// 优先使用 Redux 中的目标,若无则读取本地存储
|
||||
let dailyGoal = waterStats?.dailyGoal ?? 0;
|
||||
@@ -111,9 +126,14 @@ async function executeChallengeReminderTask(): Promise<void> {
|
||||
try {
|
||||
console.log('执行挑战鼓励提醒后台任务...');
|
||||
|
||||
const state = store.getState();
|
||||
const normalizedUserName = state.user.profile?.name?.trim();
|
||||
const userName = normalizedUserName && normalizedUserName.length > 0 ? normalizedUserName : '朋友';
|
||||
let userName = '朋友';
|
||||
try {
|
||||
const state = store.getState();
|
||||
const normalizedUserName = state.user?.profile?.name?.trim();
|
||||
userName = normalizedUserName && normalizedUserName.length > 0 ? normalizedUserName : '朋友';
|
||||
} catch (error) {
|
||||
console.log('无法获取用户名,使用默认值:', error);
|
||||
}
|
||||
|
||||
const challenges = await listChallenges();
|
||||
const joinedChallenges = challenges.filter((challenge) => challenge.isJoined && challenge.progress);
|
||||
@@ -201,6 +221,33 @@ async function sendTestNotification(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送简单的喝水提醒(后备方案)
|
||||
*/
|
||||
async function sendSimpleWaterReminder(): Promise<void> {
|
||||
try {
|
||||
const userName = '朋友'; // 默认用户名
|
||||
const Notifications = await import('expo-notifications');
|
||||
|
||||
const notificationId = await Notifications.scheduleNotificationAsync({
|
||||
content: {
|
||||
title: '💧 该喝水啦!',
|
||||
body: `${userName},记得补充水分,保持身体健康~`,
|
||||
data: {
|
||||
type: 'water_reminder',
|
||||
url: '/statistics'
|
||||
},
|
||||
sound: 'default',
|
||||
},
|
||||
trigger: null, // 立即发送
|
||||
});
|
||||
|
||||
console.log('简单喝水提醒已发送,ID:', notificationId);
|
||||
} catch (error) {
|
||||
console.error('发送简单喝水提醒失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 后台任务执行函数
|
||||
async function executeBackgroundTasks(): Promise<void> {
|
||||
console.log('开始执行后台任务...');
|
||||
@@ -213,14 +260,30 @@ async function executeBackgroundTasks(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
// await sendTestNotification()
|
||||
// 确保 Redux store 已初始化
|
||||
try {
|
||||
const state = store.getState();
|
||||
if (!state) {
|
||||
console.log('Redux store 未初始化,跳过后台任务');
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('无法访问 Redux store,跳过后台任务:', error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行喝水提醒检查任务 - 已禁用,改为由用户手动在设置页面管理
|
||||
// await sendTestNotification() // 可选:启用测试通知
|
||||
|
||||
// 检查是否启用测试通知
|
||||
const testNotificationsEnabled = await AsyncStorage.getItem('@background_test_notifications_enabled') === 'true';
|
||||
if (testNotificationsEnabled) {
|
||||
await sendTestNotification();
|
||||
}
|
||||
|
||||
// 执行喝水提醒检查任务
|
||||
await executeWaterReminderTask();
|
||||
|
||||
// 执行站立提醒检查任务
|
||||
// await executeStandReminderTask();
|
||||
|
||||
// 执行挑战鼓励提醒任务
|
||||
await executeChallengeReminderTask();
|
||||
|
||||
console.log('后台任务执行完成');
|
||||
@@ -269,13 +332,15 @@ export class BackgroundTaskManager {
|
||||
|
||||
if (await TaskManager.isTaskRegisteredAsync(BACKGROUND_TASK_IDENTIFIER)) {
|
||||
log.info('[BackgroundTask] 任务已注册');
|
||||
return
|
||||
} else {
|
||||
log.info('[BackgroundTask] 任务未注册,开始注册...');
|
||||
await BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER);
|
||||
log.info('[BackgroundTask] 任务注册完成');
|
||||
}
|
||||
|
||||
log.info('[BackgroundTask] 任务未注册, 开始注册...');
|
||||
// 注册后台任务
|
||||
await BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER);
|
||||
|
||||
// 验证任务状态
|
||||
const status = await BackgroundTask.getStatusAsync();
|
||||
log.info(`[BackgroundTask] 任务状态: ${status}`);
|
||||
|
||||
this.isInitialized = true;
|
||||
log.info('后台任务管理器初始化完成');
|
||||
|
||||
Reference in New Issue
Block a user