Problem statement
Android assigns every placed app widget a unique appWidgetId. That instance id is the right storage key for user configuration such as label: "London" on one weather widget and label: "New York" on another.
Voltra currently supports Android widget type-level flows well:
requestPinAndroidWidget(widgetId) can request pinning a configured Voltra widget provider.
updateAndroidWidget(widgetId, variants) renders and stores one payload for the Voltra widget type id.
getActiveWidgets() can discover placed widget instances and exposes Android instance ids.
- Dynamic Widgets already receive
env.configuration during Hermes rendering.
What is not possible today:
- A user cannot configure each placed Android widget instance independently.
setWidgetConfiguration(widgetId, key, value) stores values by Voltra widget type id, so all instances of that widget type share the same configuration.
updateAndroidWidget(widgetId, variants) stores one payload per widget type and fans it out to all placed instances.
- Generated
appwidget-provider XML does not attach an Android android:configure Activity, so launcher-added widgets have no guaranteed insert-time configuration hook.
- Pin-with-preview and pin-without-preview only report whether the pin request was accepted. They do not currently surface the created
appWidgetId or enter a per-instance configuration flow.
- Server-driven widgets fetch one payload per widget type id, so a server cannot reliably return different content for each placed instance.
Android/Glance provides the lifecycle hook, but not the UI. A widget configuration Activity can receive AppWidgetManager.EXTRA_APPWIDGET_ID, persist app-defined configuration, update the exact Glance widget instance, and return RESULT_OK. Voltra needs to bridge that platform contract to React Native and to its widget storage model.
Suggested solution
Introduce per-instance Android widget configuration as a Voltra runtime feature.
High-level changes:
- Treat
widgetTypeId and appWidgetId as distinct concepts in public API and native code.
- Add generated Android configuration Activity support from the Expo plugin.
- Let the generated configuration Activity act as a thin trampoline into React Native rather than providing built-in form UI.
- Store Dynamic Widget configuration by
appWidgetId, while keeping appIntent.parameters[].default keyed by widget type.
- Update
VoltraClientGlanceWidget to resolve GlanceId -> appWidgetId and pass per-instance configuration into env.configuration.
- Add targeted client-rendered widget update support, for example
updateAndroidWidgetInstance(appWidgetId, variants) or updateAndroidWidget(widgetTypeId, variants, { appWidgetId }).
- Extend server-driven widgets to include both
widgetId / widgetTypeId and appWidgetId in requests, fetch/render per instance, and cache payloads per instance.
- Add opt-in configuration behavior in widget config, with optional support for
reconfigurable and configuration_optional on Android 12+.
Expected outcome:
- Two widgets of the same Voltra type can be placed on the home screen with different user configuration.
- Launcher-added widgets and in-app pinned widgets can enter the same per-instance configuration flow.
- Dynamic Widgets rendered through Hermes receive correct per-instance
env.configuration.
- Client-rendered and server-driven update paths can update one instance without overwriting all sibling instances.
Problem statement
Android assigns every placed app widget a unique
appWidgetId. That instance id is the right storage key for user configuration such aslabel: "London"on one weather widget andlabel: "New York"on another.Voltra currently supports Android widget type-level flows well:
requestPinAndroidWidget(widgetId)can request pinning a configured Voltra widget provider.updateAndroidWidget(widgetId, variants)renders and stores one payload for the Voltra widget type id.getActiveWidgets()can discover placed widget instances and exposes Android instance ids.env.configurationduring Hermes rendering.What is not possible today:
setWidgetConfiguration(widgetId, key, value)stores values by Voltra widget type id, so all instances of that widget type share the same configuration.updateAndroidWidget(widgetId, variants)stores one payload per widget type and fans it out to all placed instances.appwidget-providerXML does not attach an Androidandroid:configureActivity, so launcher-added widgets have no guaranteed insert-time configuration hook.appWidgetIdor enter a per-instance configuration flow.Android/Glance provides the lifecycle hook, but not the UI. A widget configuration Activity can receive
AppWidgetManager.EXTRA_APPWIDGET_ID, persist app-defined configuration, update the exact Glance widget instance, and returnRESULT_OK. Voltra needs to bridge that platform contract to React Native and to its widget storage model.Suggested solution
Introduce per-instance Android widget configuration as a Voltra runtime feature.
High-level changes:
widgetTypeIdandappWidgetIdas distinct concepts in public API and native code.appWidgetId, while keepingappIntent.parameters[].defaultkeyed by widget type.VoltraClientGlanceWidgetto resolveGlanceId -> appWidgetIdand pass per-instance configuration intoenv.configuration.updateAndroidWidgetInstance(appWidgetId, variants)orupdateAndroidWidget(widgetTypeId, variants, { appWidgetId }).widgetId/widgetTypeIdandappWidgetIdin requests, fetch/render per instance, and cache payloads per instance.reconfigurableandconfiguration_optionalon Android 12+.Expected outcome:
env.configuration.