Android通知定时功能异常:用户自定义时间不生效求助
Android 自定义通知时间不生效问题修复方案
核心问题分析
- 偏好设置不同步:用户修改时间后仅保存了字符串格式的
notifA,但未同步更新用于闹钟触发的整数类型noti1,导致读取闹钟时间时仍使用旧值或默认的7点。 - 未更新旧闹钟:修改时间后没有取消原有重复闹钟,新旧闹钟冲突导致触发逻辑混乱。
- Spinner初始化逻辑冗余:用大量
if-else转换时间格式既繁琐又易遗漏,且未在用户修改后实时同步noti1。
具体修复步骤
1. 同步偏好设置,简化Spinner逻辑
修改Spinner选择后的保存逻辑,同时保存字符串格式和整数格式的时间,避免数据不一致:
dropdown.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener { override fun onItemSelected( parent: AdapterView<*>, view: View, pos: Int, id: Long ) { val selectedTimeStr = parent.getItemAtPosition(pos) as String // 直接从选中字符串提取小时数 val selectedHour = selectedTimeStr.split(":")[0].toInt() apply.setOnClickListener { val settingsPref = getSharedPreferences("settings", MODE_PRIVATE).edit() // 同时保存两种格式的时间 settingsPref.putString("notifA", selectedTimeStr) settingsPref.putInt("noti1", selectedHour) settingsPref.commit() // 修改完成立即更新闹钟 updateAlarm(selectedHour) } } override fun onNothingSelected(parent: AdapterView<*>?) {} })
简化Spinner初始化,不用冗余的if-else:
val dropdown = dialog.findViewById<Spinner>(R.id.spinnyboi) val items = arrayOf("5:00", "6:00", "7:00", "8:00", "9:00", "10:00", "11:00", "12:00", "13:00") val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, items) dropdown?.adapter = adapter val settingsPref = getSharedPreferences("settings", MODE_PRIVATE) val timeAA = settingsPref.getString("notifA", "7:00") // 直接通过数组索引设置选中状态 val selectedPos = items.indexOf(timeAA) if (selectedPos != -1) { dropdown.setSelection(selectedPos) }
2. 新增闹钟更新/重置函数
创建专门的函数用于取消旧闹钟并设置新的重复闹钟,确保修改时间后立即生效:
private fun updateAlarm(targetHour: Int) { // 先取消已存在的闹钟 val mIntent = Intent(this, MyReceiver::class.java) val mPendingIntent = PendingIntent.getBroadcast( this, 1, mIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) val mAlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager mAlarmManager.cancel(mPendingIntent) // 配置新的闹钟时间 val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, targetHour) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) // 增加秒数精度,避免触发误差 // 如果当前时间已过目标点,自动设置为明天 if (timeInMillis < System.currentTimeMillis()) { add(Calendar.DAY_OF_MONTH, 1) } } // 设置每日重复闹钟,用系统常量替代硬编码的间隔值 mAlarmManager.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, mPendingIntent ) }
3. 优化初始闹钟设置
在App启动或初始化闹钟的位置,读取最新设置并调用更新函数:
val settingsPref = getSharedPreferences("settings", MODE_PRIVATE) val targetHour = settingsPref.getInt("noti1", 7) updateAlarm(targetHour)
额外注意事项
- 确保
PendingIntent的requestCode统一(这里是1),否则无法正确取消旧闹钟。 - Android 19及以上版本,
setRepeating会被系统调整为不精确触发,若需要精确重复,可在MyReceiver中每次触发后重新设置下一次闹钟。 - 检查App是否已申请
POST_NOTIFICATIONS权限(Android 12+)及后台运行权限,避免通知被系统拦截。
内容的提问来源于stack exchange,提问作者Joshu
相关产品推荐
相关产品推荐

