app/src/main/java/com/example/firstapp/App.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/MainActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/activity/ReminderListActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/service/ReminderWorker.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/ui/notifications/NotificationsFragment.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/activity_reminder_list.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/fragment_notifications.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/values-v23/themes.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
app/src/main/java/com/example/firstapp/App.kt
@@ -453,41 +453,15 @@ * 设置定时提醒Worker * 配置为每天运行一次检查是否有新的提醒内容 */ private fun setupReminderWorker() { fun setupReminderWorker() { Log.d(TAG, "设置定时提醒Worker") // 方式1:使用周期性执行 val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() // 创建周期性工作请求 val reminderWorkRequest = PeriodicWorkRequestBuilder<ReminderWorker>( ReminderWorker.REPEAT_INTERVAL, ReminderWorker.REPEAT_INTERVAL_TIME_UNIT ) .setConstraints(constraints) .addTag("reminder_worker") .build() // 使用 REPLACE 策略确保新配置生效 WorkManager.getInstance(this).enqueueUniquePeriodicWork( "reminder_work", ExistingPeriodicWorkPolicy.REPLACE, reminderWorkRequest ) // 方式2:设置在特定时间执行(例如每天上午9点和下午18点) // 仅在特定时间执行(每天指定时间) // 可根据需要设置多个不同时间点的提醒 ReminderWorker.setupScheduledWorker(this, 9, 0) // 上午9:00 ReminderWorker.setupScheduledWorker(this, 13, 50) // 下午18:00 ReminderWorker.setupScheduledWorker(this, 13, 50) // 下午13:50 // 注意:不再立即执行一次提醒检查,避免重复提醒 // 如果需要立即检查,可以设置一个延迟,例如5分钟后执行 val delayedWorkRequest = OneTimeWorkRequestBuilder<ReminderWorker>() .setInitialDelay(5, TimeUnit.MINUTES) // 延迟5分钟执行 .build() WorkManager.getInstance(this).enqueue(delayedWorkRequest) // 不再使用周期性轮询和立即执行的方式 } } app/src/main/java/com/example/firstapp/MainActivity.kt
@@ -75,6 +75,9 @@ // 只保留底部导航的设置 navView.setupWithNavController(navController) // 重置提醒计划并检查是否有错过的提醒 resetReminders() // 检查权限 if (ContextCompat.checkSelfPermission( this, Manifest.permission.RECEIVE_SMS @@ -323,4 +326,25 @@ Toast.makeText(this, "同步短信失败:${e.message}", Toast.LENGTH_SHORT).show() } } // 重置提醒计划 private fun resetReminders() { try { // 取消所有现有的提醒任务 androidx.work.WorkManager.getInstance(this).cancelAllWorkByTag("reminder_worker") // 清除旧的提醒偏好设置 getSharedPreferences("reminder_prefs", Context.MODE_PRIVATE).edit().clear().apply() // 重新设置提醒任务 (application as App).setupReminderWorker() // 检查是否有错过的提醒 com.example.firstapp.service.ReminderWorker.checkMissedReminders(this) android.util.Log.d("MainActivity", "已重置提醒计划") } catch (e: Exception) { android.util.Log.e("MainActivity", "重置提醒计划失败: ${e.message}") } } } app/src/main/java/com/example/firstapp/activity/ReminderListActivity.kt
@@ -90,7 +90,7 @@ } // 添加已读按钮点击事件 binding.clearReadMessagesButton.setOnClickListener { binding.clearReadContainer.setOnClickListener { lifecycleScope.launch { // 将所有未读消息标记为已读 adapter.currentList.forEach { record -> @@ -99,7 +99,7 @@ } } Toast.makeText( this@ReminderListActivity, "所有消息已标记为已读", Toast.LENGTH_SHORT this@ReminderListActivity, "所有消息已标记为删除", Toast.LENGTH_SHORT ).show() checkUnreadMessages() } app/src/main/java/com/example/firstapp/service/ReminderWorker.kt
@@ -40,9 +40,15 @@ override suspend fun doWork(): Result = withContext(Dispatchers.IO) { android.util.Log.d("ReminderWorker", "doWork 开始执行") try { // 强制发送一条测试通知(确认Worker是否执行) // sendTestNotification() android.util.Log.d("ReminderWorker", "发送测试通知确认Worker已执行") // 获取当前时间 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() @@ -158,8 +164,12 @@ val channel = NotificationChannel( CHANNEL_ID, "提醒通知", NotificationManager.IMPORTANCE_DEFAULT ) NotificationManager.IMPORTANCE_HIGH // 提高重要性级别 ).apply { enableLights(true) // 开启指示灯 enableVibration(true) // 开启震动 description = "重要提醒通知" // 设置描述 } notificationManager.createNotificationChannel(channel) } @@ -168,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() @@ -233,10 +245,11 @@ companion object { private const val CHANNEL_ID = "reminder_channel" private const val MISSED_PREF_KEY = "last_checked_reminder_time" // 定时任务执行频率 - 可选不同配置 val REPEAT_INTERVAL = 15L // 设置为每15分钟运行一次 val REPEAT_INTERVAL_TIME_UNIT = TimeUnit.MINUTES // 定时任务执行频率(不再使用) val REPEAT_INTERVAL = 24L // 设置为每24小时运行一次 val REPEAT_INTERVAL_TIME_UNIT = TimeUnit.HOURS // 创建在指定时间运行的定时任务 fun setupScheduledWorker(context: Context, hour: Int, minute: Int) { @@ -255,11 +268,22 @@ // 计算初始延迟 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 策略确保新配置生效 @@ -268,6 +292,84 @@ 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 } } } app/src/main/java/com/example/firstapp/ui/notifications/NotificationsFragment.kt
@@ -312,7 +312,7 @@ val userInfo = response.data // 本地保存我的邀请码 PreferencesManager.setInviteCode(userInfo.intervialcode); //PreferencesManager.setInviteCode(userInfo.intervialcode); // 设置头像 Glide.with(this) .load(userInfo.cover) app/src/main/res/layout/activity_reminder_list.xml
@@ -13,18 +13,38 @@ android:elevation="4dp" android:padding="8dp"> <!-- 将已读按钮改为图标 --> <!-- 使用 LinearLayout 包裹图标和文字 --> <LinearLayout android:id="@+id/clearReadContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginEnd="16dp" android:orientation="horizontal" android:gravity="center_vertical" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" android:focusable="true"> <!-- 调整后的图标按钮 --> <ImageButton android:id="@+id/clearReadMessagesButton" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginEnd="16dp" android:background="?attr/selectableItemBackgroundBorderless" android:background="@null" android:contentDescription="标记所有消息为已读" android:padding="8dp" android:src="@drawable/reminder_delete" /> <!-- 添加“全部删除”文字 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全部删除" android:layout_marginEnd="8dp" android:textColor="@color/black" /> </LinearLayout> </RelativeLayout> <androidx.recyclerview.widget.RecyclerView app/src/main/res/layout/fragment_notifications.xml
@@ -122,17 +122,26 @@ android:layout_height="wrap_content" android:text="VIP会员 " android:textColor="#B8741A" android:textSize="18sp" android:textSize="16sp" android:textStyle="bold"/> <!-- 添加间隔 --> <View android:layout_width="6dp" android:layout_height="0dp"/> <TextView android:id="@+id/tv_vip_expire" android:layout_width="wrap_content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:singleLine="true" android:ellipsize="end" android:textColor="#F2F2F2" android:textSize="14sp"/> android:textSize="12sp" android:clickable="true" android:focusable="true" android:background="?attr/selectableItemBackground"/> </LinearLayout> <!-- 第二行:续费提示(上移调整) --> app/src/main/res/values-v23/themes.xml
@@ -7,10 +7,10 @@ <!-- <item name="android:windowLightStatusBar">?attr/isLightTheme</item>--> <!-- </style>--> <style name="Theme.FirstApp" parent="Base.Theme.FirstApp"> <!-- Transparent system bars for edge-to-edge. --> <item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:windowLightStatusBar">?attr/isLightTheme</item> </style> <!-- <style name="Theme.FirstApp" parent="Base.Theme.FirstApp">--> <!-- <!– Transparent system bars for edge-to-edge. –>--> <!-- <item name="android:navigationBarColor">@android:color/transparent</item>--> <!-- <item name="android:statusBarColor">@android:color/transparent</item>--> <!-- <item name="android:windowLightStatusBar">?attr/isLightTheme</item>--> <!-- </style>--> </resources>