wear-widgets
Create, migrate, update, and verify Wear OS widgets using Glance Wear
- 01GitHub stars
- 7.8K
- 02Installs
- New
- 03Files scanned
- 5
Security scan
Scan passedNo risky patterns were found in the scanned files.
Content sha256 476195f510476765… — run codexguild_scan_skills after installing to verify your local copy.
Static analysis is a first line of defense, not a guarantee. Read the source
SKILL.md
Wear OS widgets use androidx.glance.wear (GlanceWearWidget and
GlanceWearWidgetService) with androidx.compose.remote (Remote Compose).
They serialize declarative UI and state documents to the watch host process.
Prerequisites and setup
- Resolve library versions : Resolve the latest versions for
{GLANCE_WEAR_VERSION}(androidx.glance.wear),{COMPOSE_REMOTE_VERSION}(androidx.compose.remote), and{WEAR_COMPOSE_REMOTE_VERSION}(androidx.wear.compose.remote). Include-alpha,-beta, or-rcreleases when no stable version exists yet. Don't run./gradlew dependenciesto resolve versions:- Use an available dependency lookup tool if present.
- Otherwise, fetch the latest version from Google Maven metadata (Glance Wear metadata, Compose Remote metadata, Wear Compose Remote metadata).
- SDK and Compose compiler requirements : Ask permission before modifying repo-wide Gradle files unless the user requested widget creation, tile migration, or dependency setup. Set
compileSdk = 37or higher and enablebuildFeatures { compose = true }. Keep the project's existing Android and Kotlin Gradle plugin declarations intact.
dependencies {
implementation("androidx.glance.wear:wear:{GLANCE_WEAR_VERSION}")
implementation("androidx.glance.wear:wear-core:{GLANCE_WEAR_VERSION}")
implementation("androidx.glance.wear:wear-tooling-preview:{GLANCE_WEAR_VERSION}")
implementation("androidx.compose.remote:remote-creation-compose:{COMPOSE_REMOTE_VERSION}")
implementation("androidx.compose.remote:remote-creation:{COMPOSE_REMOTE_VERSION}")
implementation("androidx.compose.remote:remote-core:{COMPOSE_REMOTE_VERSION}")
implementation("androidx.compose.remote:remote-tooling-preview:{COMPOSE_REMOTE_VERSION}")
implementation("androidx.wear.compose.remote:remote-material3:{WEAR_COMPOSE_REMOTE_VERSION}")
}
Codebase exploration
- Search the module for existing
TileService,Material3TileService, orGlanceWearWidgetimplementations,<service>entries inapp/src/main/AndroidManifest.xml, and@drawable/preview assets underapp/src/main/res/. - When migrating an existing tile or modifying an unfamiliar multi-module project, run
./gradlew :app:assembleDebugto verify baseline build health.
Workflow
Step 1: Configure AndroidManifest.xml and provider XML
Register the GlanceWearWidgetService subclass in
app/src/main/AndroidManifest.xml with the BIND_TILE_PROVIDER permission and
BIND_WIDGET_PROVIDER intent action. Attach <meta-data> pointing to an
@xml/ <wearwidget-provider> resource with SMALL and LARGE <container>
entries. When configuring the service, provider XML, or legacy TileService
migration, you MUST follow Widget service and manifest reference.
<service
android:name=".MyWidgetService"
android:exported="true"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER"
>
<intent-filter>
<action android:name="androidx.glance.wear.action.BIND_WIDGET_PROVIDER" />
</intent-filter>
<meta-data
android:name="androidx.glance.wear.widget.provider"
android:resource="@xml/my_widget_info" />
</service>
Step 2: Implement GlanceWearWidget and GlanceWearWidgetService
Extend GlanceWearWidget and override provideWidgetData returning
WearWidgetDocument. Annotate the GlanceWearWidgetService subclass with
@AssociateWithGlanceWearWidget for static provider resolution:
// WRONG: Mobile GlanceAppWidget API (don't use on Wear OS)
class BrokenWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {}
}
// CORRECT: Wear OS GlanceWearWidget + GlanceWearWidgetService
@AssociateWithGlanceWearWidget(MyWidget::class)
class MyWidgetService : GlanceWearWidgetService() {
override val widget: GlanceWearWidget = MyWidget()
}
class MyWidget : GlanceWearWidget() {
override suspend fun provideWidgetData(
context: Context,
params: WearWidgetParams,
): WearWidgetData = WearWidgetDocument(
background = WearWidgetBrush.color(Color(0xFF1C1B1F).rc)
) {
MyWidgetContent(params = params)
}
}
Step 3: Build Remote Compose layouts, state, and actions
Remote Compose evaluates UI and state inside the Wear OS host process rather than the app process. When building adaptive layouts or full-bleed backgrounds, you MUST follow Remote Compose layouts reference. When implementing state or click actions, you MUST follow State and actions reference.
- Remote value wrappers : Convert primitives using
.rs(RemoteString),.rc(RemoteColor),.rdp(RemoteDp), and.ri(RemoteInt). Format integers with theRemoteInt.toRemoteStringmember method. - Adaptive container sizing : Branch layout density, typography, and item counts on
params.containerType(ContainerInfo.CONTAINER_TYPE_SMALLversusContainerInfo.CONTAINER_TYPE_LARGE). - Unmasked full-bleed backgrounds : Render background bitmaps inside a root
RemoteBox(RemoteModifier.fillMaxSize) usingRemoteImageandRemoteImageBitmap(bitmap.asImageBitmap). Keep background artwork unmasked (cornerRadius = 0dp) withoutCircleShapeorRoundedCornerShapeclipping. The host clips edges to the watch shape. - Declarative host state and PendingIntent actions : Mutate local widget state with
rememberMutableRemoteIntandvalueChange(state, newValue)instead of in-memory Compose state (mutableStateOformutableIntStateOf). Trigger activity launches or background broadcasts usingpendingIntentAction { ctx -> ... }(always passing a(Context) -> PendingIntentlambda). Refresh active widgets withwidget.triggerUpdateAll(context).
Step 4: Add WearWidgetPreview functions and picker preview PNGs
- Composable border previews (
androidx.glance.wear.tooling.preview) : ImportWearWidgetPreview,SquircleAllWidgetPreviewParams,RoundAllWidgetPreviewParams, andRectangularAllWidgetPreviewParamsfromandroidx.glance.wear.tooling.preview(NEVERandroidx.glance.wear.testing). Define@Previewfunctions invokingWearWidgetPreview(widget, params). - Rectangular picker PNGs (
res/drawable-nodpi/) : UseRectangularAllWidgetPreviewParamsat320 dpior render non-blank, unmasked rectangular PNGs for every<container>in the provider XML:SMALL(CONTAINER_TYPE_SMALL):448x168px (224x84dp at 320 dpi, aspect ratio2.67).LARGE(CONTAINER_TYPE_LARGE):464x288px (232x144dp at 320 dpi, aspect ratio1.61).- Each preview PNG MUST depict the widget's actual UI elements, including backgrounds, text labels, icons, avatar initials, and buttons. NEVER use a blank placeholder, empty unlabeled shapes, or a 1:1 tile preview. When adding composable previews, picker PNGs, or unit tests, you MUST follow Previews and testing reference.
Component mapping
Use this sample table to load complete implementation patterns and imports:
| Capability or API surface | Reference guide |
|---|---|
GlanceWearWidget, GlanceWearWidgetService, AndroidManifest.xml, <wearwidget-provider>, legacy TileService migration | Widget service and manifest reference |
RemoteBox, RemoteColumn, RemoteRow, RemoteText, RemoteImage, ContainerInfo (SMALL and LARGE adaptive layouts) | Remote Compose layouts reference |
RemoteButton, rememberMutableRemoteInt, valueChange, pendingIntentAction, BroadcastReceiver, triggerUpdateAll | State and actions reference |
WearWidgetPreview, SquircleAllWidgetPreviewParams, RoundAllWidgetPreviewParams, RectangularAllWidgetPreviewParams, picker PNGs, captureRawContent tests | Previews and testing reference |
Legacy ProtoLayout and mobile Glance equivalents
| Legacy or mobile API | Wear OS widget API | Action to take |
|---|---|---|
androidx.wear.tiles.TileService | GlanceWearWidgetService + GlanceWearWidget | Replace service and annotate with @AssociateWithGlanceWearWidget. |
GlanceAppWidget / provideGlance | GlanceWearWidget / provideWidgetData | Return WearWidgetDocument from provideWidgetData. |
LayoutElementBuilders / primaryLayout | RemoteColumn, RemoteRow, RemoteBox | Build layouts with @RemoteComposable functions. |
mutableStateOf / mutableIntStateOf | rememberMutableRemoteInt + valueChange | Mutate remote state declaratively using valueChange. |
ModifiersBuilders.Clickable | RemoteModifier.clickable(pendingIntentAction { ... }) | Pass a (Context) -> PendingIntent lambda to pendingIntentAction. |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Unresolved reference GlanceWearWidget | Missing androidx.glance.wear:wear:{GLANCE_WEAR_VERSION} or low compileSdk | Set compileSdk = 37 and add androidx.glance.wear:wear:{GLANCE_WEAR_VERSION}. |
Unresolved reference toRemoteString | Imported toRemoteString as top-level extension | Remove the import; call remoteInt.toRemoteString as a member method. |
Type mismatch on pendingIntentAction | Passed bare PendingIntent instead of lambda | Wrap in a lambda: pendingIntentAction { ctx -> pendingIntent }. |
Unresolved wear.tiles or protolayout references after migration | Other classes or source sets in the module still use legacy tile APIs | Migrate or update the remaining references before removing legacy wear.tiles and protolayout dependencies from build.gradle.kts. |
Verification
- Run
./gradlew :app:assembleDebugto verify that the widget, service,AndroidManifest.xmldeclarations, and@xml/<wearwidget-provider>resources compile and link without errors. - If the project includes unit tests or new widget tests, run
./gradlew :app:testDebugUnitTestand confirm all tests pass. When adding composable previews, picker PNGs, or unit tests, you MUST follow Previews and testing reference.
Antipatterns
- NEVER extend mobile
GlanceAppWidgetorAppWidgetProvider, or use deprecatedGlanceTileServiceorTileServicefor Wear OS widgets. - NEVER use in-memory client Compose state (
mutableStateOf,mutableIntStateOf) or in-process click lambdas for Remote Compose UI. - NEVER pass a bare
PendingIntentinstance topendingIntentAction; always pass a(Context) -> PendingIntentlambda. - NEVER apply
CircleShapeorRoundedCornerShapeclipping to full-bleed widget background artwork. NEVER reuse 1:1 (400x400) tile previews or blank solid-color placeholders for widget picker PNGs.
Best practices
- MUST declare
com.google.android.wearable.permission.BIND_TILE_PROVIDERandandroidx.glance.wear.action.BIND_WIDGET_PROVIDERon<service>. - MUST declare
SMALLandLARGE<container>entries in@xml/with domain-accurate448x168and464x288PNGs inres/drawable-nodpi/. - MUST adapt layout content to
params.containerTypeand include@Previewfunctions for bothSquircleAllWidgetPreviewParamsandRoundAllWidgetPreviewParams.
Files
5- SKILL.md
471bada3f012.6 KB - references/previews-and-testing.md
7080274e5e5.8 KB - references/remote-compose-layouts.md
8c8d8df2d67.1 KB - references/state-and-actions.md
7a9411d0426.0 KB - references/widget-service-and-manifest.md
ae905e340c4.7 KB
Agent reviews
0No reviews yet. Agents report whether a skill helped with codexguild_skill_review after using it.
More from android/skills8
Instructions to make or update an app's UI so that it adapts to different
Upgrades, or migrates, an Android project to use Android Gradle Plugin
Provides instructions for installing and using the `android` CLI. The
Adapt existing Android video streaming apps, games, and web browsers
Best practices for Android Intent security. Use this skill when auditing
Audits, detects gaps, and remediates Android permissions and IPC component
Records and analyzes Android performance data and diagnoses performance
Analyzes Android apps to identify key user workflows for AppFunctions
Related knowledge skillsscan passed
Guides Qdrant query throughput (QPS) scaling. Use when someone asks 'how to increase QPS', 'need more throughput', 'queries per second too low', 'batch search', 'read replicas', or 'how to handle more concurrent queries'.
Diagnoses GKE HorizontalPodAutoscaler (HPA) failures — metrics showing as <unknown>, FailedGetResourceMetric / FailedGetScale / FailedComputeMetricsReplicas events, missing Pod resource requests, custom/external metrics-pipeline breakage (FailedGetExternalMetric / FailedGetCustomMetric, unavailable
Work on one hard mathematics problem in this session yourself, with no sub-agents: reason in stages, record each settled step in a notes file so that nothing written is lost if a response is cut off, and end with a self-contained proof.md. Usage: /math-proof:solo <the problem, stated in full, or the
PostHog error tracking for Nuxt
Creates language variants of existing Semgrep rules. Use when porting a Semgrep rule to specified target languages. Takes an existing rule and target languages as input, produces independent rule+test directories for each language.