I'm implementing generated widget previews (API 35, AppWidgetManager.setWidgetPreview) for an app with 12 AppWidgetProviders (RemoteViews path, not Glance's providePreview). Publishing works, platform-side storage is verifiably correct, but the widget picker UI does not reflect updated previews — on either Pixel Launcher (API 36 emulator) or Samsung One UI Home 16 (SM-S921U, Android 15).
On data changes (content-hashed so unchanged data never triggers a call, throttled well under the documented ~2 calls/provider/hour limit):
val accepted = appWidgetManager.setWidgetPreview(
ComponentName(context, providerClass),
AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
remoteViews
)
I check the Boolean (rate-limit rejections return false rather than throwing) and only record success on true.
Immediately after an accepted call, reading the preview back from my own app returns the correct, updated content:
val stored = appWidgetManager.getWidgetPreview(
ComponentName(context, providerClass), null,
AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN
)
// Inflating `stored` and reading the bound TextView shows the NEW value,
// e.g. "$12,346" — so AppWidgetService stored exactly what I pushed.
So the app → AppWidgetService half works. The failure is launcher-side rendering:
Pixel Launcher (enable_generated_previews=true on this image): after an accepted update, the picker keeps showing the previous preview. am force-stop on the launcher made it pick up the stored preview once, but in a repeat of the same experiment the picker stayed stale even after force-stop. Not deterministic.
One UI Home 16.0.05.29: picker always shows the static previewLayout. am force-stop doesn't help; only pm clear on the launcher (or uninstalling/reinstalling my app) makes it render the stored preview — after which it sticks to that snapshot and ignores subsequent updates.
A fresh app uninstall → install → setWidgetPreview reliably shows the new preview in both launchers, which makes me think launchers cache per-package preview bitmaps and are missing (or ignoring) an invalidation signal for in-place updates.
Possibly relevant: this is a debug build whose versionCode never changes between iterations (always 1).
Questions:
When an app calls setWidgetPreview, what is the intended notification path to launchers/hosts? Are launchers required to re-query getWidgetPreview, or is caching-until-process-death acceptable behavior?
Is Launcher3's (and OEM forks') picker preview cache keyed by versionCode or another token an app can influence? Is "previews only refresh on app update" the de-facto contract?
Is there any legitimate way for an app to know its generated preview will actually be displayed (vs merely stored), or to nudge a re-render?
Is One UI 16 known to support generated previews at all, given it renders the stored preview only after its own data is cleared?