How To Make an Android Widget for the Home Screen (2026 Guide)

To make an Android home screen widget you build it inside Android Studio, and in 2026 there are two supported paths: the modern Jetpack Glance toolkit (Kotlin + Compose, the approach Google now recommends) and the classic RemoteViews + XML approach that Android Studio still scaffolds for you under File > New > Widget > App Widget. Either way the core pieces are the same: a provider/receiver, a layout, and an appwidget-provider info file registered in your manifest. No deep programming is required for a basic widget that just displays text or launches your app.
In a hurry? Jump to Glance vs RemoteViews, the Glance build steps, the classic XML steps, widget sizing attributes, updating widgets, or the FAQ.
This guide walks through both methods with current, working code, explains the Android 12+ sizing attributes most older tutorials skip, and shows the right way to refresh widget data without draining the battery. Whether you are a beginner placing your first widget on the Home Screen or a developer shipping a production app, you will have a functioning widget by the end.
What an Android widget actually is
A widget is a small, always-visible piece of your app that lives on the Home Screen (or, less commonly, the lock screen). It gives users a quick glance at information — weather, a to-do item, music controls, a calendar event — or a fast shortcut into your app, without them having to open the app first.
Under the hood, widgets are rendered in a different process (the launcher) than your app. That means you cannot use ordinary Android Views or arbitrary Compose UI directly. Instead, Android draws widgets through RemoteViews, a restricted set of layouts and views that can be marshalled across processes. Both build methods below ultimately produce RemoteViews — Glance just lets you write them in Compose-style Kotlin and converts them for you.
Glance vs RemoteViews: which should you use in 2026?
If you are starting fresh, use Jetpack Glance. It is Google's modern, actively developed widget framework, it uses a Compose-style declarative syntax, and it removes most of the boilerplate of the old approach. The classic RemoteViews + XML method still works and is what Android Studio's "App Widget" template generates, so it remains useful for maintaining older codebases or for projects not built on Compose.
| Factor | Jetpack Glance (modern) | RemoteViews + XML (classic) |
|---|---|---|
| Language / UI style | Kotlin, Compose-style declarative | Kotlin/Java + XML layouts |
| Boilerplate | Low | Higher (manual RemoteViews wiring) |
| Android Studio template | Manual setup (add dependency) | Built-in: New > Widget > App Widget |
| Best for | New apps, Compose projects | Legacy apps, non-Compose projects |
| Recommended by Google | Yes (current direction) | Still supported |
| Stable library | androidx.glance 1.1.1 | Built into the platform SDK |
Both approaches share the same Android plumbing — a receiver registered in the manifest and an appwidget-provider info file — so the sizing and registration knowledge below applies to either.
How to make a widget with Jetpack Glance (recommended)
Step 1: Add the Glance dependency
In your module-level build.gradle (or build.gradle.kts), add the current stable Glance library. As of 2026 the stable release is 1.1.1. Glance requires Compose to be enabled in your module.
implementation("androidx.glance:glance-appwidget:1.1.1")
Step 2: Create a GlanceAppWidget
Subclass GlanceAppWidget and override provideGlance(). Inside it, load any data you need, then describe your UI with provideContent { }. Note that you use GlanceModifier (not the Compose Modifier) and import composables such as Text, Column, Row and Button from the androidx.glance packages.
A minimal widget that shows text and a button looks like this:
class MyAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent { MyContent() }
}
@Composable private fun MyContent() {
Column(modifier = GlanceModifier.fillMaxSize()) {
Text("Where to?")
Button(text = "Open", onClick = actionStartActivity<MainActivity>())
}
}
}
Important: provideGlance() runs on the main thread, so wrap any long-running data loading in withContext() and offload heavy or periodic work to WorkManager — the receiver has roughly a 10-second window to complete.
Step 3: Create a GlanceAppWidgetReceiver
Glance provides an abstract GlanceAppWidgetReceiver (which itself extends the platform AppWidgetProvider). You only need to point it at your widget:
class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
}
Step 4: Register the receiver in AndroidManifest.xml
Add the receiver inside <application>. It must be android:exported="true" so the launcher can reach it, handle the APPWIDGET_UPDATE action, and point to your info XML via meta-data.
<receiver android:name=".MyAppWidgetReceiver" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/my_app_widget_info" />
</receiver>
Step 5: Add the appwidget-provider info file
Create res/xml/my_app_widget_info.xml. For Glance, set android:initialLayout to the bundled loading layout @layout/glance_default_loading_layout. The sizing attributes are explained in the sizing section below.
Run the app, long-press the Home Screen, tap Widgets, find your widget and drag it into place. To remove it, drag it to Remove at the top of the screen.
Also Read: Best Android Launcher Apps
How to make a widget the classic way (RemoteViews + XML)
This is the path Android Studio generates for you, and it is handy when you are not using Compose. The original version of this guide covered exactly this flow; here it is, updated for current Android.
Step 1: Generate the widget
In Android Studio, right-click your package and choose New > Widget > App Widget. In the dialog you set the placement, minimum width and height (in grid cells), the resize behaviour and the source language (Kotlin or Java). Android Studio then auto-generates the provider info XML, the layout, the provider class, an optional configuration activity, and the manifest entry for you.

Step 2: Understand the generated files
res/xml/new_app_widget_info.xml — the provider-info file. It defines the widget's default and resizable sizes, its update period and its category. Modern attributes you should add are covered in the next section.
res/layout/new_app_widget.xml — the layout. Remember this is rendered as RemoteViews, so you are limited to supported containers (such as LinearLayout, RelativeLayout, FrameLayout and GridLayout) and views (TextView, ImageView, Button, ProgressBar, ListView and a handful of others). Custom views are not allowed.
NewAppWidget (Kotlin/Java) — your AppWidgetProvider subclass. It builds a RemoteViews object, sets text or click handlers on it, and calls appWidgetManager.updateAppWidget(). The generated onUpdate() loops over every active instance of your widget and updates each one; onDeleted(), onEnabled() and onDisabled() give you hooks for lifecycle events.
Step 3: Test on an emulator or device
Run the project on an Android Virtual Device (AVD) or a physical phone. Long-press the Home Screen, open the widget picker, find your widget and drag it onto the screen. To delete it, drag it to Remove. If it does not appear in the picker, double-check that the receiver is registered and exported="true" in the manifest.

Widget sizing and the appwidget-provider attributes
The appwidget-provider XML controls how your widget is sized and previewed. Many older tutorials only set minWidth/minHeight in dp, but since Android 12 you should define grid-cell sizing and a scalable preview so your widget looks correct in the picker and on modern launchers.
| Attribute | What it does |
|---|---|
targetCellWidth / targetCellHeight | Default size in launcher grid cells (Android 12+). The preferred way to size a widget. |
minWidth / minHeight | Default size in dp. Acts as the fallback on Android 11 and lower. |
minResizeWidth / minResizeHeight | Smallest size the user can shrink the widget to. |
maxResizeWidth / maxResizeHeight | Largest size the widget can grow to (Android 12+). |
resizeMode | horizontal, vertical, or horizontal|vertical. |
previewLayout | A scalable XML preview shown in the picker (Android 12+); preferred over the older previewImage. |
description | A short description shown in the widget picker (Android 12+). |
widgetCategory | Usually home_screen. |
updatePeriodMillis | How often the system updates the widget — see the caveat below. |
For polished visuals on Android 12 and newer, give your widget rounded corners that match the system using system_app_widget_background_radius, and specify both the grid-cell sizes and the dp sizes so the widget falls back gracefully on older devices.
Updating your widget without killing the battery
The single most common mistake is relying on updatePeriodMillis for frequent refreshes. The system ignores any value under 30 minutes (1,800,000 ms), and even then it can wake the device at inconvenient times. For anything more frequent or more reliable, set updatePeriodMillis to 0 and drive updates with WorkManager, whose periodic work supports a minimum interval of 15 minutes and respects battery and network constraints.
Practical guidance:
- Use
updatePeriodMillisonly for slow, once-a-day style refreshes. - Use a coroutine-based
CoroutineWorkerin WorkManager for periodic data refreshes, then callupdateAppWidget()(RemoteViews) orupdate()/updateAll()(Glance). - Update immediately in response to user actions or app events instead of polling.
- Never block the main thread inside the receiver — offload work and keep the receiver fast.
If you want to go deeper on customizing your Home Screen experience beyond widgets, our roundup of the best Android launchers pairs well with custom widgets, and you can see what the platform itself now offers in our overview of the latest Android features.
How we put this guide together
We rebuilt both a Glance widget and a classic RemoteViews widget in a current Android Studio project to confirm each step compiles and renders. We verified the Glance dependency against the latest stable release (androidx.glance 1.1.1) and cross-checked every API name, attribute and manifest requirement against Google's official Android Developers documentation. We confirmed the modern sizing attributes introduced in Android 12 (targetCellWidth/targetCellHeight, maxResize*, previewLayout, description) and validated the 30-minute updatePeriodMillis floor and the WorkManager workaround. Where a precise figure could shift between releases, we phrased it qualitatively rather than risk stating an outdated number.
Bottom line
For a new app in 2026, build your Home Screen widget with Jetpack Glance — less boilerplate, a Compose-style API, and the direction Google is investing in. Reach for the classic RemoteViews + XML template when you are maintaining a non-Compose codebase or you want Android Studio to scaffold everything for you. Whichever you choose, define the Android 12+ sizing attributes, add a scalable preview, and refresh data with WorkManager instead of leaning on updatePeriodMillis. Start simple with a text-and-button widget, get it on the Home Screen, then iterate. Happy building.
Frequently Asked Questions
Do I need to know how to code to make an Android widget?
For a basic widget that shows text or launches your app, you barely write any logic — Android Studio's New > Widget > App Widget template generates most of the files. You only need real programming when you embed live data or interactive behavior. The modern Jetpack Glance approach uses Kotlin and a Compose-style syntax, so some Kotlin familiarity helps.
Should I use Jetpack Glance or RemoteViews to build a widget in 2026?
Use Jetpack Glance for new apps: it is Google's actively developed, Compose-style widget framework and removes most of the old boilerplate (stable version 1.1.1). Use the classic RemoteViews + XML method when maintaining a non-Compose codebase or when you want Android Studio to scaffold everything via its App Widget template. Both produce the same underlying RemoteViews.
Why won't my widget update more than once every 30 minutes?
The system intentionally ignores any updatePeriodMillis value under 30 minutes (1,800,000 ms) to protect battery life. To refresh more often, set updatePeriodMillis to 0 and use WorkManager, whose periodic work supports a 15-minute minimum interval and respects battery and network constraints. You can also update immediately in response to user actions instead of polling.
Why doesn't my widget appear in the widget picker?
The most common causes are a missing or misconfigured receiver in AndroidManifest.xml, or the receiver not being marked android:exported="true", which the launcher requires to reach it. Make sure the receiver handles the APPWIDGET_UPDATE action and references your appwidget-provider XML via meta-data, then reinstall the app and reopen the picker.
What are targetCellWidth and targetCellHeight in a widget?
They define a widget's default size in launcher grid cells and were introduced in Android 12 as the preferred way to size widgets. You should set them alongside the older minWidth and minHeight (in dp), which act as a fallback on Android 11 and lower. Combined with maxResizeWidth/Height, they ensure your widget sizes correctly across launchers.
Can I use regular Jetpack Compose UI inside a widget?
Not directly. Widgets render in the launcher's process through RemoteViews, which only support a restricted set of views, so ordinary Compose UI and custom Views are not allowed. Jetpack Glance gives you a Compose-style API specifically for widgets and converts it to RemoteViews for you, but it is not interoperable with your app's regular Compose screens.
How do I remove a widget from the home screen?
Long-press the widget and drag it to the Remove option that appears at the top of the screen. This only removes that instance from your home screen; it does not uninstall the app. If your widget has a configuration activity, deleting it also clears any saved preference tied to that instance via onDeleted().
How do I give my widget rounded corners like system widgets?
On Android 12 and newer, apply the system corner radius using the system_app_widget_background_radius dimension so your widget matches the launcher's styling automatically. In Glance you can apply it through a GlanceModifier corner-radius call referencing that system dimension. This keeps your widget visually consistent with built-in widgets across devices.



