You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中BroadcastReceiver被重复调用两次的问题求助

BroadcastReceiver触发时被调用两次的排查与解决

我实现了一个BroadcastReceiver,但触发时总会被调用两次,不清楚原因。我仅在AndroidManifest.xml中注册了该接收器,没有在代码中重复注册。闹钟是在MainActivity的onCreate方法中调度的,相关代码如下:

AndroidManifest.xml

<receiver android:name=".alarmManager.domain.AlarmReceiver"/>

MainActivity onCreate()代码

setContent {
    WorkingTimeCalculatorTheme {
        WorkingTimeCalculator()

        //每日提醒闹钟
        val scheduler = AndroidAlarmSchedulerImpl(LocalContext.current)

        val localTimeReminder = LocalTime.of(10, 30)
        val nowNanos = LocalTime.now().toNanoOfDay()
        val notificationNanos = localTimeReminder.toNanoOfDay()
        val localDateReminder =
            LocalDate.now().plusDays(if (notificationNanos <= nowNanos) 1 else 0)

        val alarmItem: AlarmItem = AlarmItem(
            time = LocalDateTime.now()
                .plusSeconds(5),//LocalDateTime.of(localDateReminder, localTimeReminder),
            title = stringResource(R.string.EnterWorkingHours),
            message = stringResource(R.string.PleaseSetTheTimesForThisDay),
            notificationType = NotificationType.DayUnchangedReminder.value
        )
        alarmItem.let(scheduler::schedule)
    }
}

AndroidAlarmSchedulerImpl代码

class AndroidAlarmSchedulerImpl(
    private val context: Context
) : AlarmScheduler {

    private val alarmManager = context.getSystemService(AlarmManager::class.java)

    override fun schedule(item: AlarmItem) {
        val intent = Intent(context, AlarmReceiver::class.java).apply {
            putExtra("EXTRA_TITLE", item.title)
            putExtra("EXTRA_MESSAGE", item.message)
            putExtra("EXTRA_NOTIFICATION_TYPE", item.notificationType)
        }
        alarmManager.setRepeating(
            AlarmManager.RTC_WAKEUP,
            item.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000,
            60000, //AlarmManager.INTERVAL_DAY,
            PendingIntent.getBroadcast(
                context,
                item.hashCode(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

        )
    }

    override fun cancel(item: AlarmItem) {
        alarmManager.cancel(
            PendingIntent.getBroadcast(
                context,
                item.hashCode(),
                Intent(context, AlarmReceiver::class.java),
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        )
    }
}

AlarmReceiver代码

@AndroidEntryPoint
class AlarmReceiver : BroadcastReceiver() {

    @Inject
    lateinit var addDayReminderNotificationSingleton: AddDayReminderNotification

    override fun onReceive(context: Context?, intent: Intent?) {
        var title = intent?.getStringExtra("EXTRA_TITLE") ?: return
        title += "\n${LocalDate.now().toDateString()}"
        val message = intent.getStringExtra("EXTRA_MESSAGE") ?: return
        val notificationType =
            NotificationType.fromValue(intent.getIntExtra("EXTRA_NOTIFICATION_TYPE", 0))?.value

        Log.d("AlarmTest", "BroadCastReceiver Called")

        val notification = Notification(
            id = null,
            date = LocalDate.now(),
            time = LocalTime.now(),
            title = title,
            description = message,
            unread = true,
            notificationType = notificationType ?: 0
        )
        if (::addDayReminderNotificationSingleton.isInitialized) {
            CoroutineScope(Dispatchers.IO).launch {
                addDayReminderNotificationSingleton.addNotification(context, notification)
            }
        } else {
            Log.e("AlarmReceiver", "addDayReminderNotificationSingleton is not initialized")
        }
    }
}

可能的原因及解决方法

  1. Activity重复触发onCreate:如果Activity因屏幕旋转、系统回收重建等原因多次执行onCreate,会重复调度闹钟。解决方式:

    • 调度前先取消同类型闹钟,确保仅保留一个有效实例:
      scheduler.cancel(alarmItem)
      scheduler.schedule(alarmItem)
      
    • 将调度逻辑移到onStart并添加判断,仅在首次启动时执行。
  2. PendingIntent的requestCode冲突:item.hashCode()可能存在重复值,导致创建多个PendingIntent。可以改用固定唯一ID(如针对每日提醒用1001),或者重写AlarmItem的hashCode方法保证唯一性。

  3. AlarmManager重复触发:部分Android版本中setRepeating可能因系统优化出现重复广播。可以改用setExactAndAllowWhileIdle,每次触发后手动设置下一次闹钟,替代重复调度。

  4. 接收器实例重复创建:通过@AndroidEntryPoint注入的接收器可能被系统创建多个实例。可以在onReceive中打印实例hashCode确认:

    Log.d("AlarmTest", "BroadCastReceiver Called, instance: ${this.hashCode()}")
    

内容的提问来源于stack exchange,提问作者SkAppCoding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:50:21