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:
LaunchedEffect()
or DisposableEffect()
to arrange to do that work only once while the composable is in compositionThe first option is vastly superior for something like an AlarmManager
alarm.