From 3466799c94227c5ebba9fb201621e745058867ee Mon Sep 17 00:00:00 2001 From: cloudroam <cloudroam> Date: 星期二, 15 四月 2025 13:18:34 +0800 Subject: [PATCH] add: 消息提醒时间设定;会员到期时间调整; --- app/src/main/java/com/example/firstapp/service/ReminderWorker.kt | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 154 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/example/firstapp/service/ReminderWorker.kt b/app/src/main/java/com/example/firstapp/service/ReminderWorker.kt index 07b811a..ef0d07f 100644 --- a/app/src/main/java/com/example/firstapp/service/ReminderWorker.kt +++ b/app/src/main/java/com/example/firstapp/service/ReminderWorker.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.os.Build import androidx.core.app.NotificationCompat +import androidx.work.* import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import com.example.firstapp.MainActivity @@ -21,6 +22,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext +import java.util.Calendar import java.util.concurrent.TimeUnit /** @@ -38,23 +40,29 @@ override suspend fun doWork(): Result = withContext(Dispatchers.IO) { android.util.Log.d("ReminderWorker", "doWork 开始执行") try { + // 获取当前时间 + val currentTime = System.currentTimeMillis() + val scheduledTime = inputData.getLong("scheduled_time", 0) + + // 如果有设定的预定时间且当前时间与预定时间相差超过30分钟,则跳过执行 + if (scheduledTime > 0 && Math.abs(currentTime - scheduledTime) > 30 * 60 * 1000) { + android.util.Log.d("ReminderWorker", "当前时间与预定时间相差过大,跳过执行") + return@withContext Result.success() + } + // 获取所有提醒设置 val reminderList = reminderRepository.getAllReminders().first() android.util.Log.d("ReminderWorker", "获取到 ${reminderList.size} 条提醒设置") - if (reminderList.isEmpty()) { - // 测试用:如果没有数据,也发送一条测试通知 - sendTestNotification() - android.util.Log.d("ReminderWorker", "数据为空,发送了测试通知") - } - - for (reminder in reminderList) { - try { - android.util.Log.d("ReminderWorker", "处理提醒: ${reminder.categoryName}") - checkCategoryContent(reminder.categoryId, reminder.categoryName, reminder.notificationMethod) - } catch (e: Exception) { - e.printStackTrace() - android.util.Log.e("ReminderWorker", "处理提醒失败: ${e.message}") + if (reminderList.isNotEmpty()) { + for (reminder in reminderList) { + try { + android.util.Log.d("ReminderWorker", "处理提醒: ${reminder.categoryName}") + checkCategoryContent(reminder.categoryId, reminder.categoryName, reminder.notificationMethod) + } catch (e: Exception) { + e.printStackTrace() + android.util.Log.e("ReminderWorker", "处理提醒失败: ${e.message}") + } } } @@ -156,8 +164,12 @@ val channel = NotificationChannel( CHANNEL_ID, "提醒通知", - NotificationManager.IMPORTANCE_DEFAULT - ) + NotificationManager.IMPORTANCE_HIGH // 提高重要性级别 + ).apply { + enableLights(true) // 开启指示灯 + enableVibration(true) // 开启震动 + description = "重要提醒通知" // 设置描述 + } notificationManager.createNotificationChannel(channel) } @@ -166,7 +178,9 @@ .setSmallIcon(R.drawable.ic_reminder) // 使用自定义图标 .setContentTitle(title) .setContentText(content) - .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setPriority(NotificationCompat.PRIORITY_HIGH) // 提高通知优先级 + .setCategory(NotificationCompat.CATEGORY_REMINDER) // 设置为提醒类别 + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) // 在锁屏上显示完整通知 .setAutoCancel(true) .setContentIntent(pendingIntent) .build() @@ -231,13 +245,131 @@ companion object { private const val CHANNEL_ID = "reminder_channel" + private const val MISSED_PREF_KEY = "last_checked_reminder_time" - // 定时任务执行频率 - 设置为每天运行一次 - val REPEAT_INTERVAL = 24L // 每24小时运行一次 + // 定时任务执行频率(不再使用) + val REPEAT_INTERVAL = 24L // 设置为每24小时运行一次 val REPEAT_INTERVAL_TIME_UNIT = TimeUnit.HOURS - - // 测试用的频率配置,已注释掉 - // val REPEAT_INTERVAL = 2L - // val REPEAT_INTERVAL_TIME_UNIT = TimeUnit.MINUTES + + // 创建在指定时间运行的定时任务 + fun setupScheduledWorker(context: Context, hour: Int, minute: Int) { + val calendar = Calendar.getInstance() + val now = Calendar.getInstance() + + calendar.set(Calendar.HOUR_OF_DAY, hour) + calendar.set(Calendar.MINUTE, minute) + calendar.set(Calendar.SECOND, 0) + + // 如果设定时间已经过了,则设置为明天这个时间 + if (calendar.timeInMillis < now.timeInMillis) { + calendar.add(Calendar.DAY_OF_MONTH, 1) + } + + // 计算初始延迟 + val initialDelay = calendar.timeInMillis - now.timeInMillis + + // 先取消所有现有的提醒任务 + WorkManager.getInstance(context).cancelAllWorkByTag("reminder_worker") + + // 创建周期性工作请求(每天同一时间) + val dailyWorkRequest = PeriodicWorkRequestBuilder<ReminderWorker>( + 24, TimeUnit.HOURS + ) + .setInitialDelay(initialDelay, TimeUnit.MILLISECONDS) + .setConstraints( + Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + // 设置灵活时间窗口为0,确保尽量准时执行 + .setInputData(Data.Builder().putLong("scheduled_time", calendar.timeInMillis).build()) + .addTag("reminder_worker") + .build() + + // 使用 REPLACE 策略确保新配置生效 + WorkManager.getInstance(context).enqueueUniquePeriodicWork( + "daily_reminder_${hour}_${minute}", + ExistingPeriodicWorkPolicy.REPLACE, + dailyWorkRequest + ) + + android.util.Log.d("ReminderWorker", "设置定时提醒: ${hour}:${minute}, 初始延迟: ${initialDelay/1000/60}分钟") + + // 记录预定的下次执行时间 + val prefs = context.getSharedPreferences("reminder_prefs", Context.MODE_PRIVATE) + prefs.edit().putLong("next_reminder_time_${hour}_${minute}", calendar.timeInMillis).apply() + } + + // 应用启动时检查是否有错过的提醒 + fun checkMissedReminders(context: Context) { + val prefs = context.getSharedPreferences("reminder_prefs", Context.MODE_PRIVATE) + val lastCheckedTime = prefs.getLong(MISSED_PREF_KEY, 0) + val currentTime = System.currentTimeMillis() + + // 如果上次检查时间是0,说明是首次运行应用 + if (lastCheckedTime == 0L) { + prefs.edit().putLong(MISSED_PREF_KEY, currentTime).apply() + return + } + + // 检查是否错过了提醒时间点 + val lastCheckedCalendar = Calendar.getInstance().apply { timeInMillis = lastCheckedTime } + val currentCalendar = Calendar.getInstance().apply { timeInMillis = currentTime } + + // 如果不是同一天,或者超过了设定的提醒时间点 + val missedReminder = checkIfMissedReminderTime(lastCheckedCalendar, currentCalendar) + + if (missedReminder) { + android.util.Log.d("ReminderWorker", "检测到错过的提醒,立即执行一次") + // 立即安排一次性任务执行提醒检查 + val oneTimeRequest = OneTimeWorkRequestBuilder<ReminderWorker>() + .setConstraints( + Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + .build() + + WorkManager.getInstance(context).enqueue(oneTimeRequest) + } + + // 更新最后检查时间 + prefs.edit().putLong(MISSED_PREF_KEY, currentTime).apply() + } + + // 检查是否错过了提醒时间点 + private fun checkIfMissedReminderTime(lastChecked: Calendar, current: Calendar): Boolean { + // 如果日期不同,说明至少过了一天 + if (lastChecked.get(Calendar.DAY_OF_YEAR) != current.get(Calendar.DAY_OF_YEAR) || + lastChecked.get(Calendar.YEAR) != current.get(Calendar.YEAR)) { + + // 检查当前时间是否超过了9:00或13:50 + val currentHour = current.get(Calendar.HOUR_OF_DAY) + val currentMinute = current.get(Calendar.MINUTE) + + return (currentHour > 9 || (currentHour == 9 && currentMinute >= 0)) || + (currentHour > 13 || (currentHour == 13 && currentMinute >= 50)) + } + + // 如果同一天,检查是否在上次检查后经过了9:00或13:50时间点 + val lastHour = lastChecked.get(Calendar.HOUR_OF_DAY) + val lastMinute = lastChecked.get(Calendar.MINUTE) + val currentHour = current.get(Calendar.HOUR_OF_DAY) + val currentMinute = current.get(Calendar.MINUTE) + + // 检查是否错过了9:00 + if ((lastHour < 9 || (lastHour == 9 && lastMinute == 0)) && + (currentHour > 9 || (currentHour == 9 && currentMinute > 0))) { + return true + } + + // 检查是否错过了13:50 + if ((lastHour < 13 || (lastHour == 13 && lastMinute < 50)) && + (currentHour > 13 || (currentHour == 13 && currentMinute >= 50))) { + return true + } + + return false + } } } \ No newline at end of file -- Gitblit v1.9.3