Reputation: 150
I'm developing an application using Jetpack Compose and I have some widgets created using Glance Widget. I need to update a counter on the widget every time I receive a notification in the application. Notifications can arrive very frequently, up to 4 times per second, but can also have larger intervals of 10-15 seconds.
To update the widget, I'm using the
suspend fun GlanceAppWidget.updateAll(context: Context): Unit
method every time a notification is received. However, I'm encountering an issue where the widget sometimes updates the counter but sometimes it doesn't.
My questions are:
Any advice or best practices would be greatly appreciated!
Upvotes: 4
Views: 514
Reputation: 478
i have faced the same issue, the problem with updating glance frequently is that updatePeriodMillis in app widget provider could be at minumum 30 minutes and if you set it less than that it won't work as excpected and in my use case i had to update more frequently and this could be done using combination of alarm manager and GlanceAppWidgetReceiver.
the widget receiver :
class WidgetReceiver() : GlanceAppWidgetReceiver(), KoinComponent{
override val glanceAppWidget: GlanceAppWidget = MyWidget()
private val alarmManager: AlarmManager by inject()
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
//this will get called when the widget gets firstly initialized so we schedule the first alarm there
override fun onEnabled(context: Context?) {
alarmManager.scheduleUpdateWidgetAlarm(
id = "widget",
triggerAt = 60000,
)
super.onEnabled(context)
}
//this will get called when the normal update widget gets called we use it as a fallback to schedule the alarm again in case it it was cancelled
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
alarmManager.scheduleUpdateWidgetAlarm(
id = "widget",
triggerAt = 60000,
)
}
// this will get called whenever alarm manager sends broadcast to the widget receiver
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
println("intent extra: " + intent.getStringExtra("prayerTime"))
scope.launch {
updateWidget(context)
}
alarmManager.scheduleUpdateWidgetAlarm(
id = "widget",
triggerAt = 60000,
)
}
private suspend fun updateWidget(context: Context) {
try {
val manager = GlanceAppWidgetManager(context)
val glanceIds = manager.getGlanceIds(PrayerTimesWidget::class.java)
glanceIds.forEach { glanceId ->
glanceAppWidget.update(context, glanceId)
}
} catch (e: Exception) {
println("WIDGET error in updateWidget of widget receiver ${e.message}")
}
}
}
fun scheduleUpdateWidgetAlarm(id: String, triggerAt: Long) {
val intent =
Intent(context, WidgetReceiver::class.java).apply {
putExtra("id", id)
}
if (canScheduleExactAlarm) {
alarmManager.setAlarmClock(
android.app.AlarmManager.AlarmClockInfo(
Clock.System.now().toEpochMilliseconds() + triggerAt,
null,
),
PendingIntent.getBroadcast(
context,
id.hashCode(),
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
),
)
}
}
so the whole idea is to use this combination to make sure that the widget gets updated whenever needed depending on the usecase in mine it get's updated every 1 minute . this is the only workaround i did find also don't forget to reschedule your alarms when the device reboots.
Upvotes: 0
Reputation: 1
Facing the same issue, below are my observations
This is the log you should look for:
Worker result SUCCESS for Work [ id=69cc3029-d1b1-4e9a-9084-108baa942a49, tags={ androidx.glance.session.SessionWorker } ]
Please update if anyone got any fix/work around.
Upvotes: 0
Reputation: 480
There are no limitations on how often the composable is recomposed.We can't initialise the recomposition process manually. If the parameters of the Composable function you are using is updated, It will get recomposed with the new data automatically. Please refer this documentation https://developer.android.com/develop/ui/compose/mental-model#recomposition
Upvotes: -1