I implemented an BroadcastReceiver. The Problem is, that it is allways called twice if it is triggered. I don’t get why. I hope you can help me.
The manifest is the only place i register the receiver. I habe not registered it again in code.
the Alarm is scheduled in the onCreate Methode of MainActivity
AndroidManifest.xml:
<receiver android:name=".alarmManager.domain.AlarmReceiver"/>
MainActivity onCreate():
setContent {
WorkingTimeCalculatorTheme {
WorkingTimeCalculator()
//Day Reminder Alarm
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)
}
}
AlarmScheduleImpl:
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")
}
}
}
You are scheduling an alarm every time WorkingTimeCalculatorTheme()
recomposes. Either:
- Move this logic somewhere else that you better control the lifecycle, such as in a repository or viewmodel, or
- Use
LaunchedEffect()
orDisposableEffect()
to arrange to do that work only once while the composable is in composition
The first option is vastly superior for something like an AlarmManager
alarm.
Recognized by Mobile Development Collective
1