Jetpack Glance: A Modern Way to Build App Widgets in Android

Table of Contents

Widgets are one of the oldest and most-loved features of Android. They let users access app content directly from the home screen, offering convenience, quick interactions, and persistent information.

But let’s be honest — building widgets used to be a pain. If you’ve ever dealt with RemoteViews, you probably remember how clunky and restrictive it felt. From limited layout options to awkward state updates, it often felt like using outdated tools in a modern development world.

Enter Jetpack Glance— a fresh, modern, and composable way to build Android app widgets.

In this blog, we’ll explore what Jetpack Glance is, how it works, why it matters, and how you can start building beautiful widgets that feel right at home in 2025.

What is Jetpack Glance?

Jetpack Glance is an Android Jetpack library that lets developers build app widgets using a declarative Kotlin API, inspired by Jetpack Compose. It’s designed to bring the modern development experience of Compose to Android widgets — without completely replacing the underlying AppWidget system.

Glance provides a Compose-like DSL for creating UI elements, handling interactions, and managing widget state. Under the hood, it still translates your code to the RemoteViews used by the Android system, ensuring full compatibility with homescreens and launchers.

Why Jetpack Glance Matters

If you’ve ever built widgets with XML and RemoteViews, you know how painful it can be. Layout constraints, limited interactivity, and poor testability were common complaints.

Jetpack Glance solves this by offering:

  • Declarative UI: Say goodbye to boilerplate XML. Use familiar composables like Text, Image, Row, Column, and Box.
  • Kotlin-first Development: Leverage the benefits of modern Kotlin and Compose practices.
  • Theming Support: Build widgets that match your app’s Material design and even adapt to dynamic colors.
  • Improved Readability and Maintainability: Code that’s easier to read, test, and update.
  • Compatibility with AppWidget System: Works seamlessly with Android’s native widget infrastructure.

Building UI with Glance Composables

Jetpack Glance offers a minimal set of UI elements modeled after Compose. Here’s what you can expect:

  • Text, Button, Image — for basic elements.
  • Row, Column, Box — for layouts.
  • LazyColumn — for scrollable lists (with limitations).
  • Spacer, Modifier, Padding, Alignment — to structure your layout.

These components are optimized for the widget framework, so you can’t use every Compose API, but it’s still a huge leap forward compared to traditional methods.

Kotlin
@Composable
fun MyWidgetContent() {
    Column(
        modifier = GlanceModifier.padding(16.dp)
    ) {
        Text("Hello Widget!")
        Button(
            text = "Open App",
            onClick = actionStartActivity<MainActivity>()
        )
    }
}

Handling User Interactions

Widgets aren’t just for display — they should be interactive. Glance makes this easier by providing built-in Action APIs.

You can define actions such as:

  • Launching Activities
  • Triggering Services
  • Sending Broadcasts
  • Executing Callbacks (via actionCallback)
Kotlin
Button(
    text = "Launch",
    onClick = actionStartActivity<MyActivity>()
)

Handling interactions has never been this straightforward in a widget context.

Theming and Styling

Glance supports both Material 2 and Material 3 themes, including dynamic color integration on supported devices. You can wrap your UI in a GlanceTheme to ensure consistent styling.

Kotlin
@Composable
fun ThemedWidget() {
    GlanceTheme {
        Text("Styled with Material 3")
    }
}

Glance adapts to light/dark mode and the device’s color palette, ensuring your widget looks native and polished.

State Management and Updates

Unlike Compose, which is reactive by default, Glance widgets are stateless and passive. That means you control when and how the widget updates.

You’ll typically use:

  • GlanceAppWidget.update(context) — to trigger a UI refresh.
  • GlanceStateDefinition — to persist data across updates.

It’s your job to observe changes (e.g., LiveData, WorkManager, or repository data) and update the widget manually when needed.

How to Get Started

Let’s walk through a simple step-by-step guide to help you get started with building widgets using Jetpack Glance.

1. Add Dependencies

Kotlin
dependencies {
    implementation "androidx.glance:glance-appwidget:1.1.1"
    implementation "androidx.glance:glance-material3:1.1.1"
}

2. Enable Compose Support

Kotlin
android {
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.15"
    }
}

3. Define Your Widget

Kotlin
class MyGlanceWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        MyWidgetContent() 
    }
}

4. Register the Widget

Update your AndroidManifest.xml and provide metadata via a resource XML file like res/xml/my_widget_info.xml.

Kotlin
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:resizeMode="horizontal|vertical"
    android:minWidth="250dp"
    android:minHeight="100dp"
    android:initialLayout="@layout/placeholder"
    android:updatePeriodMillis="1800000" />

Known Limitations

While Glance is a significant improvement, it’s still bound by the limitations of Android’s RemoteViews system:

  • No complex animations
  • Limited custom drawing or gestures
  • Limited real-time data updates

Expect more support in future releases, but for now, design within these constraints.

Conclusion

Jetpack Glance is a game-changer for Android widget development. It modernizes an aging system with a declarative approach that feels right at home in the Jetpack ecosystem.

Whether you’re updating legacy widgets or building new ones from scratch, Glance provides a smoother, more maintainable path forward.

So go ahead — give your users beautiful, functional widgets without the pain of XML and RemoteViews.

Skill Up: Software & AI Updates!

Receive our latest insights and updates directly to your inbox

Related Posts

error: Content is protected !!