AndroidX Glance ImageProvider(Bitmap) does not update after system theme changes while ColorProvider content does
I'm investigating what appears to be an issue with AndroidX Glance widgets and would like to know whether this is expected behavior, a limitation of ImageProvider(Bitmap), or a bug.
AndroidX Glance: 1.1.1
Android API: 34–36
Tested on:
Android Emulator (AOSP / Pixel Launcher)
Xiaomi 15 (HyperOS Launcher)
ZTE Blade V70 MAX
Kotlin
My widget contains:
a Text using ColorProvider
an Image created from a Bitmap using ImageProvider(bitmap)
When the system theme changes (Light ↔ Dark), I expect:
the Text to update
a new bitmap to be generated
the widget image to update to the newly generated bitmap
<s>The Text updates correctly.</s> Text color updates, the content doesn't.
The bitmap-backed Image continues displaying the previous bitmap.
The bitmap only updates after a completely new widget session is created (for example after force stopping the app or recreating the widget).
code to reproduce: https://github.com/JuanJoseDev88/Glance-imageprovider-theme-bug.git
minimal example (updated):
class GlanceBugWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
Log.d("GlanceBug", "provideGlance()")
provideContent {
WidgetContent()
}
}
}
@Composable
private fun WidgetContent() {
val context = LocalContext.current
val uiMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
val isDark = uiMode == Configuration.UI_MODE_NIGHT_YES
val timestamp = System.currentTimeMillis()
val uuid = UUID.randomUUID().toString()
Log.d("GlanceBug", "WidgetContent()")
Log.d("GlanceBug", "timestamp=$timestamp")
Log.d("GlanceBug", "uuid=$uuid")
val bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)
if (isDark) {
bitmap.eraseColor(android.graphics.Color.WHITE)
} else {
bitmap.eraseColor(android.graphics.Color.BLACK)
}
Log.d("GlanceBug", "uiMode=${if (isDark) "DARK" else "LIGHT"}")
Log.d("GlanceBug", "bitmap generationId=${bitmap.generationId}")
Log.d("GlanceBug", "bitmap hash=${System.identityHashCode(bitmap)}")
Log.d("GlanceBug", "bitmap size=${bitmap.width}x${bitmap.height}")
Log.d("GlanceBug", "pixel00=${String.format("#%08X", bitmap.getPixel(0, 0))}")
val themeText = "Theme: ${if (isDark) "DARK" else "LIGHT"}\n\nTimestamp:\n$timestamp\n\nUUID:\n$uuid"
Column {
Text(
text = themeText,
style = TextStyle(
color = ColorProvider(
day = Color.Black,
night = Color.White
)
)
)
Image(
provider = ImageProvider(bitmap),
contentDescription = "Theme rectangle",
modifier = GlanceModifier.size(100.dp)
)
}
}
I spent quite a bit of time trying to rule out application bugs.
I verified that:
A new Bitmap is created every render.
Every bitmap has a new generationId.
Every bitmap has a different object identity.
The bitmap contains the expected pixels before being passed to ImageProvider.
The bitmap colors are correct before ImageProvider(bitmap) is constructed.
The issue reproduces on both Pixel Launcher and HyperOS Launcher.
The issue reproduces on the Android Emulator and real device.
The only thing that does not update is the bitmap displayed by ImageProvider.