Skip to content

Support per-instance Android widget configuration #206

Description

@V3RON

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions