Passing value to widget receiver

81 Views Asked by At

I'm currently working with a widget Android app using Kotlin 1.9.10 and Glance 1.0.0. I want to pin widget to home screen programmatically. I can get the widget id in onReceive fun but I want to pass more value into that.

I'm using this piece of code to pin my widget to home screen.

val appWidgetManager = AppWidgetManager.getInstance(context)
val myProvider = ComponentName(context, MyWidgetReceiver::class.java)

val pinnedWidgetCallbackIntent = Intent(Intent.ACTION_MAIN)
pinnedWidgetCallbackIntent.addCategory(Intent.CATEGORY_HOME)
pinnedWidgetCallbackIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

val successCallback = PendingIntent.getActivity(
        context, 0,
        pinnedWidgetCallbackIntent, PendingIntent.FLAG_IMMUTABLE
    )
    
appWidgetManager.requestPinAppWidget(myProvider, null, successCallback)

And in my Receiver, I override onReceive fun to get the Widget ID which have just been pinned to home screen.

override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        if (intent.action == AppWidgetManager.ACTION_APPWIDGET_UPDATE) {
            val extras = intent.extras
            val widgetId = extras?.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS)?.firstOrNull() ?: -1
        }
    }

But the problem is I want to pass one more value so that I can save it to the local storage as map, using widget id as key. How can I do that, please help me.

2

There are 2 best solutions below

5
Skizo-ozᴉʞS ツ On

Reading the requestPinAppWidget documentation I've found that you can pass a Bundle as a parameter and you are passing null.

So you should change this

appWidgetManager.requestPinAppWidget(myProvider, null, successCallback)

To this

val extras = Bundle().apply {
    putString("key", "value")
}
appWidgetManager.requestPinAppWidget(myProvider, null, successCallback)

In case you want to do it after it, you should use updateAppWidgetOptions and send also a Bundle and override the onUpdate method and getting the values using

val extras = appWidgetManager.getAppWidgetOptions(appWidgetId)
val value = extras.getString("key")
0
Dang Nguyen Hoang On

2 thousand years later, I found this answer. This solution is the best and it work well on my case. https://stackoverflow.com/a/47352244/22885025

Shortly: Create a BroadcastReceiver (remember to declare it in manifest). Then the success callback will use PendingIntent getBroadcast, which is our receiver

val pinnedWidgetCallbackIntent = Intent(context, PinnedWidgetReceiver::class.java)
    pinnedWidgetCallbackIntent.putExtras(bundleOf("key" to "value"))

    val successCallback = PendingIntent.getBroadcast(
        context, 0,
        pinnedWidgetCallbackIntent, PendingIntent.FLAG_UPDATE_CURRENT
    )

    appWidgetManager.requestPinAppWidget(myProvider, null, successCallback)

If the widget is pinned successfully, it will send a broadcast, which contain widgetId as extras (and our value, too). In onReceive of our broadcast receiver (in my case is PinnedWidgetReceiver), we can do the stuff we want.

class PinnedWidgetReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent == null || context == null) return

        val widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
        val widgetName = intent.getStringExtra("key") ?: "default value"
        //do the stuff here
    }
}