fix: OS widget cleanup crash and ordering#935
Merged
Conversation
This comment has been minimized.
This comment has been minimized.
Contributor
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Collaborator
ovitrif
approved these changes
May 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

This PR:
AddWidgetsScreenordering.Description
1. Receiver crash on widget removal
All five Glance receivers (
Price,Headlines,Blocks,Facts,Weather) overrodeonDeletedto unregister the widget entry from the preferences store. The override calledsuper.onDeleted()first and thengoAsync()itself. Glance'sGlanceAppWidgetReceiver.onDeletedalready consumes the broadcastPendingResultvia its internalgoAsyncextension, so the second call returnednullandpendingResult.finish()in ourfinallyblock threw aNullPointerException. Per Glance's own KDoc:The unregister logic now lives on each
GlanceAppWidget.onDelete(context, glanceId)override, which Glance invokes inside its own broadcast-scoped coroutine. TheonDeletedoverrides on every receiver are removed, so there is no longer a duplicategoAsynccall to NPE on.2. Provider lookup ordering
AppWidgetConfigActivity.resolveWidgetTypewas listing the providers inHeadlines, Price, Blocks, Weatherorder. Reordered toPrice, Headlines, Blocks, Weatherso it matches theAppWidgetTypeenum, the manifest receivers, the refresh worker, and the in-appAddWidgetsScreenlisting. Pure code-style change with no behavior difference.A note on the system widget picker order
The Android system widget picker (long-press home → Widgets) is rendered by the launcher, not by us. The Pixel launcher groups widgets within an app by their
targetCellWidth × targetCellHeightarea, in descending order, then by manifest declaration order within each size bucket. Becauseappwidget_info_facts.xmldeclarestargetCellHeight="1"while every other widget declarestargetCellHeight="2", Facts ends up alone in the smaller bucket and appears last in the picker. That positioning is launcher-controlled and intentional given the widget's existing 1-cell-tall design — this PR does not change widget sizes.Preview
Screen_recording_20260507_120327.webm
QA Notes
Manual Tests