ABausG / home_widget

Flutter Package for Easier Creation of Home Screen Widgets
785 stars 218 forks source link

Distinguish manual update vs system update of home screen widget #314

Open tenhobi opened 1 week ago

tenhobi commented 1 week ago

Problem to solve

Currently we can trigger HomeWidget.updateWidget to update home screen widget.

Proposal

I would like to distinguish whether in the update method (in onUpdate for GlanceAppWidgetReceiver?) it is run because system wants to rebuild the widget, or because we triggered manual update from Flutter app.

For android, there is this updateWidget method https://github.com/ABausG/home_widget/blob/main/packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetPlugin.kt#L101 which already on 111 adds an extra. I think we can use similar approach and do

intent.putExtra("isManualUpdate", true)

And then in our widget we can do something like this

class MyGlanceAppWidget : GlanceAppWidget() {
    override suspend fun onUpdate(context: Context, glanceId: GlanceId) {
        // Retrieve any relevant state or intent information
        val intent = (context as? Activity)?.intent
        val isManualUpdate = intent?.getBooleanExtra("isManualUpdate", false) ?: false

        if (isManualUpdate) {
            // Handle manual update logic
            Log.d("MyGlanceAppWidget", "Handling manual update")
        } else {
            // Handle regular update logic
            Log.d("MyGlanceAppWidget", "Handling system update")
        }

        // Perform widget update
    }
}

I suppose iOS might work similarly.

More information

I have a periodic worker which is run every time the update is done. And inside of the work I check that I only run it once per 1 minute in case it is called multiple times because of the system or whatever. But on manual trigger from Flutter app I would want to run it every time and therefore I would like to have some way to determine the type of the update.

Which Platform would be improved?

Android, iOS

Other

tenhobi commented 1 week ago

I found a solution that I have to then put check for intent to onReceive, not to onUpdate. There I have to manually also get the ids, but that's ok. And from there I can run my logic. I completely removed onUpdate since I don't to anything in there.

class MyWidgetReceiver : GlanceAppWidgetReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)

        if (intent.action != AppWidgetManager.ACTION_APPWIDGET_UPDATE) {
            return
        }
        val appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
        if (appWidgetIds == null) {
            WidgetLogger.warning("appWidgetIds in onReceive were null")
            return
        }

        val isManualUpdate = intent.getBooleanExtra("isManualUpdate", false)
        handleWidgetUpdate( // out function that runs WorkManager
            context = context,
            appWidgetIds = appWidgetIds,
            isManualUpdate = isManualUpdate,
        )
    }