From 6a2f490b1ac266ad3f22e5490f496c3c40ff099f Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Thu, 30 Jul 2026 15:23:11 +0200 Subject: [PATCH] fix(widget): keep the two widgets apart in release builds (#89) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Glance identifies a widget by its GlanceAppWidget subclass's canonical name: GlanceAppWidgetManager stores a providerName -> receivers map under that string, and updateAll resolves a widget's app-widget ids through it. R8 full mode horizontally merged MonthWidget into AgendaWidget — same supertype, same overrides, nothing to tell them apart — so both receivers registered under one provider name and AgendaWidget().updateAll() also matched the month widget's id, redrawing it as the agenda widget on the next PROVIDER_CHANGED. 2.16.0 is where it started because that release gave AgendaWidget the SizeMode.Exact override MonthWidget already had, which is what made the two classes mergeable. Verified in the releaseTest mapping: before, only AgendaWidget survived, carrying an $r8$classId field and MonthWidget's constructor frames; after, both classes are there under their own names. Keeping the real names also survives app updates, which would otherwise renumber the obfuscated name and orphan the stored mapping. --- app/proguard-rules.pro | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 8b1a5d3..ef98b3a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -38,3 +38,15 @@ # SessionWorker never ran, and widgets were stuck on their loading layout # (a blank spinner) in release builds. Keep every InputMerger's name + ctor. -keep class * extends androidx.work.InputMerger { (...); } + +# Glance identifies a widget by its GlanceAppWidget subclass's *canonical name*: +# GlanceAppWidgetManager persists a providerName -> receivers map under that +# string, and `updateAll` looks the widget's app-widget ids up through it. Under +# R8 full mode (AGP 9 default) MonthWidget and AgendaWidget — same supertype, +# same overrides, no distinguishing members — were horizontally merged into one +# class, so both receivers registered under the *same* provider name and +# `AgendaWidget().updateAll()` resolved the month widget's id too, redrawing a +# placed month widget as the agenda one on the next data change (#89). Keeping +# the real names also survives app updates, which would otherwise renumber the +# obfuscated name and orphan the stored mapping. +-keep class * extends androidx.glance.appwidget.GlanceAppWidget