Glance Widgets

The Glance Composable Model and a Home Screen Widget for BookNest

A home screen widget doesn't run in your process. The launcher draws it from RemoteViews, a serialized description of a view tree built from a small set of allowed layouts and widgets. Jetpack Glance 234 (androidx.glance:glance-appwidget and glance-material3, 1.2.0, 26 August 2026) lets you write that tree with composable functions and translates the result into RemoteViews. The functions look like Compose 234 but are Glance's own (androidx.glance.text.Text, Column, GlanceModifier). A Hilt entry point gives the widget the app's Room 234 DAO and sync store:

widget/BookNestWidget.kt: the three cheapest books (excerpt)Kotlin
@EntryPoint
@InstallIn(SingletonComponent::class)
interface WidgetEntryPoint {
  fun bookDao(): BookDao
  fun syncStore(): DataStore<SyncState>
}
class BookNestWidget : GlanceAppWidget() {
  override suspend fun provideGlance(context: Context, id: GlanceId) {
    val deps = EntryPointAccessors.fromApplication(context, WidgetEntryPoint::class.java)
    provideContent {                                      // Glance composables, not Compose UI
      // 5.30.5 collect inside the composition, so every change in Room redraws the widget
      val books by deps.bookDao().observeAll().collectAsState(initial = emptyList())
      val sync by deps.syncStore().data.collectAsState(initial = SyncState())
      val at = if (sync.at == 0L) "not yet" else clock.format(Instant.ofEpochMilli(sync.at))
      ...
      GlanceTheme { WidgetContent(books.sortedBy { it.price }.take(3), books.size, at) }
    }
  }
}
...
class BookNestWidgetReceiver : GlanceAppWidgetReceiver() {
  override val glanceAppWidget: GlanceAppWidget = BookNestWidget()
}

WidgetContent is a Column of Rows using GlanceTheme.colors (wallpaper-based on Android 12+) and a clickable(actionStartActivity<MainActivity>()). The manifest declares the receiver with an appwidget-provider XML file (3 by 2 cells, resizable, a picker description). Since Android 8 the app can also offer the widget itself:

ui/AlertsScreen.kt: asking the launcher to pin the widget (excerpt)Kotlin
        val shown = GlanceAppWidgetManager(context)
          .requestPinGlanceAppWidget(BookNestWidgetReceiver::class.java)

The launcher answers with its own sheet (right of the figure in Notification Channels); after "Add to home screen" the log showed the request and the system binding the new widget to BookNest's receiver:

Output of 173
I/BookNestWidget( 8183): pin request shown=true
I/AppWidgetServiceImpl(  681): Bound widget 2 to provider ProviderId{user:0, app:10216, cmp:...