Building a Plugin for Wear OS Tiles with Flutter

Summary
Summary
Summary
Summary

This tutorial guides you through building a Flutter plugin for Wear OS Tiles. You’ll set up the plugin scaffold, register and implement an Android TileService in Kotlin, expose a Dart API with MethodChannel, and integrate tile updates in a Flutter app. By following these steps, you can push dynamic content to Wear OS Tiles and maintain a clean separation between your Flutter UI and native service logic.

This tutorial guides you through building a Flutter plugin for Wear OS Tiles. You’ll set up the plugin scaffold, register and implement an Android TileService in Kotlin, expose a Dart API with MethodChannel, and integrate tile updates in a Flutter app. By following these steps, you can push dynamic content to Wear OS Tiles and maintain a clean separation between your Flutter UI and native service logic.

This tutorial guides you through building a Flutter plugin for Wear OS Tiles. You’ll set up the plugin scaffold, register and implement an Android TileService in Kotlin, expose a Dart API with MethodChannel, and integrate tile updates in a Flutter app. By following these steps, you can push dynamic content to Wear OS Tiles and maintain a clean separation between your Flutter UI and native service logic.

This tutorial guides you through building a Flutter plugin for Wear OS Tiles. You’ll set up the plugin scaffold, register and implement an Android TileService in Kotlin, expose a Dart API with MethodChannel, and integrate tile updates in a Flutter app. By following these steps, you can push dynamic content to Wear OS Tiles and maintain a clean separation between your Flutter UI and native service logic.

Key insights:
Key insights:
Key insights:
Key insights:
  • Prerequisites and Setup: Ensure Flutter SDK, Android SDK, and a Wear OS target are ready before scaffolding the plugin.

  • Plugin Scaffold: Define a Dart MethodChannel to expose updateTile and match it on the Android side.

  • Android Tile Service Implementation: Subclass TileService in Kotlin to build and update the ge1ar tile layout.

  • Dart-Android Bridge: Handle updateTile in onMethodCall to pass data to the TileService for dynamic rendering.

  • Flutter Integration: Call updateTile from your Flutter UI to push new content to the Wear OS Tile.

Introduction

Building custom Tiles on Wear OS enhances user engagement by surfacing glanceable actions directly on the watch. Flutter does not ship a built-in API for Wear OS Tiles, so you need a plugin that bridges Dart with the native Android TileService. In this tutorial you will create a Flutter plugin that exposes a simple Tile, register it in Android manifest, implement the TileService on the Java/Kotlin side, and invoke it from Dart using platform channels.

Prerequisites and Setup

Before you begin, make sure your development machine has:

  • Flutter SDK (stable channel)

  • Android Studio or VS Code with Android SDK

  • A Wear OS emulator or physical watch for testing

Create a plugin template by running flutter create --template=plugin wear_tiles_plugin

In your project root you will see android/, ios/, lib/, example/. Focus on the android/ and lib/ folders.

Open android/build.gradle and ensure compileSdkVersion is at least 31. In android/src/main/AndroidManifest.xml add the TileService declaration under the <application> tag:

<service
    android:name=".MyTileService"
    android:exported="true">
    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
</service>

This registers the TileService entry point for Wear OS.

Creating the Plugin Scaffold

In lib/wear_tiles_plugin.dart define a class with a method channel to communicate with Android. Keep it minimal:

import 'package:flutter/services.dart';

class WearTilesPlugin {
  static const MethodChannel _channel =
      MethodChannel('wear_tiles_plugin');

  static Future<void> updateTile(String data) async {
    await _channel.invokeMethod('updateTile', {'data': data});
  }
}

This Dart API exposes updateTile, which you will call from your Flutter app. The method channel name must match the one declared in Android.

Implementing the Android Tile Service

In android/src/main/java/com/example/wear_tiles_plugin/MyTileService.kt implement a subclass of TileService. Use the Tiles API to push layout and actions.

class MyTileService: TileService() {
  override fun onTileRequest(requestParams: RequestBuilders.TileRequest) {
    val layout = ResourceBuilders.Layout.Builder()
      .setRoot(
        LayoutElementBuilders.Text.Builder()
          .setText("Hello Wear Tile")
          .build()
      ).build()
    val tile = TileBuilders.Tile.Builder()
      .setResourcesVersion("1")
      .setTileLiveDataTimetable(
        TileLiveDataBuilders.TimelineSchedule.Builder()
          .addTimelineEntry(
            TimelineBuilders.TimelineEntry.Builder()
              .setLayout(layout)
              .build()
          ).build()
      ).build()
    val response = TileBuilders.TileResponse.Builder()
      .setTile(tile)
      .build()
    requestParams.getHostTileManager(this)
      .updateTile(tile, null

Also add the channel handler in android/src/main/java/com/example/wear_tiles_plugin/WearTilesPlugin.kt. Inside onMethodCall handle updateTile by invalidating the tile or pushing fresh data to the service.

Exposing Dart API via Platform Channels

In the plugin’s main class implement MethodCallHandler. Resolve calls from Dart to Android:

class WearTilesPlugin: FlutterPlugin, MethodCallHandler {
  private lateinit var channel : MethodChannel

  override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(binding.binaryMessenger, "wear_tiles_plugin")
    channel.setMethodCallHandler(this)
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    when (call.method) {
      "updateTile" -> {
        val data = call.argument<String>("data")
        // Send broadcast or update shared prefs for TileService
        result.success(null)
      }
      else -> result.notImplemented()
    }
  }

Drop data into a shared storage or send a broadcast so your TileService can pick it up in onTileRequest and render dynamic content.

Integrating the Tile in the Flutter App

Open example/lib/main.dart. Import the plugin and call updateTile whenever you need to push new content:

import 'package:flutter/material.dart';
import 'package:wear_tiles_plugin/wear_tiles_plugin.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Wear Tile Demo')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              await WearTilesPlugin.updateTile('New data at ${DateTime.now()}');
            },
            child: Text('Update Wear OS Tile'),
          ),
        ),
      ),
    );
  }
}

Run the example on your Wear OS device. Open the Tiles menu, swipe to find your new Tile and verify it shows the updated text.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

You have created a Flutter plugin that registers a native Wear OS TileService, bridges data via platform channels, and displays dynamic content on the watch. This architecture keeps Dart code concise while leveraging the full power of the Android Tiles API. Extend your Tile with action triggers or timeline schedules for richer interactions.

Introduction

Building custom Tiles on Wear OS enhances user engagement by surfacing glanceable actions directly on the watch. Flutter does not ship a built-in API for Wear OS Tiles, so you need a plugin that bridges Dart with the native Android TileService. In this tutorial you will create a Flutter plugin that exposes a simple Tile, register it in Android manifest, implement the TileService on the Java/Kotlin side, and invoke it from Dart using platform channels.

Prerequisites and Setup

Before you begin, make sure your development machine has:

  • Flutter SDK (stable channel)

  • Android Studio or VS Code with Android SDK

  • A Wear OS emulator or physical watch for testing

Create a plugin template by running flutter create --template=plugin wear_tiles_plugin

In your project root you will see android/, ios/, lib/, example/. Focus on the android/ and lib/ folders.

Open android/build.gradle and ensure compileSdkVersion is at least 31. In android/src/main/AndroidManifest.xml add the TileService declaration under the <application> tag:

<service
    android:name=".MyTileService"
    android:exported="true">
    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
</service>

This registers the TileService entry point for Wear OS.

Creating the Plugin Scaffold

In lib/wear_tiles_plugin.dart define a class with a method channel to communicate with Android. Keep it minimal:

import 'package:flutter/services.dart';

class WearTilesPlugin {
  static const MethodChannel _channel =
      MethodChannel('wear_tiles_plugin');

  static Future<void> updateTile(String data) async {
    await _channel.invokeMethod('updateTile', {'data': data});
  }
}

This Dart API exposes updateTile, which you will call from your Flutter app. The method channel name must match the one declared in Android.

Implementing the Android Tile Service

In android/src/main/java/com/example/wear_tiles_plugin/MyTileService.kt implement a subclass of TileService. Use the Tiles API to push layout and actions.

class MyTileService: TileService() {
  override fun onTileRequest(requestParams: RequestBuilders.TileRequest) {
    val layout = ResourceBuilders.Layout.Builder()
      .setRoot(
        LayoutElementBuilders.Text.Builder()
          .setText("Hello Wear Tile")
          .build()
      ).build()
    val tile = TileBuilders.Tile.Builder()
      .setResourcesVersion("1")
      .setTileLiveDataTimetable(
        TileLiveDataBuilders.TimelineSchedule.Builder()
          .addTimelineEntry(
            TimelineBuilders.TimelineEntry.Builder()
              .setLayout(layout)
              .build()
          ).build()
      ).build()
    val response = TileBuilders.TileResponse.Builder()
      .setTile(tile)
      .build()
    requestParams.getHostTileManager(this)
      .updateTile(tile, null

Also add the channel handler in android/src/main/java/com/example/wear_tiles_plugin/WearTilesPlugin.kt. Inside onMethodCall handle updateTile by invalidating the tile or pushing fresh data to the service.

Exposing Dart API via Platform Channels

In the plugin’s main class implement MethodCallHandler. Resolve calls from Dart to Android:

class WearTilesPlugin: FlutterPlugin, MethodCallHandler {
  private lateinit var channel : MethodChannel

  override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(binding.binaryMessenger, "wear_tiles_plugin")
    channel.setMethodCallHandler(this)
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    when (call.method) {
      "updateTile" -> {
        val data = call.argument<String>("data")
        // Send broadcast or update shared prefs for TileService
        result.success(null)
      }
      else -> result.notImplemented()
    }
  }

Drop data into a shared storage or send a broadcast so your TileService can pick it up in onTileRequest and render dynamic content.

Integrating the Tile in the Flutter App

Open example/lib/main.dart. Import the plugin and call updateTile whenever you need to push new content:

import 'package:flutter/material.dart';
import 'package:wear_tiles_plugin/wear_tiles_plugin.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Wear Tile Demo')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              await WearTilesPlugin.updateTile('New data at ${DateTime.now()}');
            },
            child: Text('Update Wear OS Tile'),
          ),
        ),
      ),
    );
  }
}

Run the example on your Wear OS device. Open the Tiles menu, swipe to find your new Tile and verify it shows the updated text.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

You have created a Flutter plugin that registers a native Wear OS TileService, bridges data via platform channels, and displays dynamic content on the watch. This architecture keeps Dart code concise while leveraging the full power of the Android Tiles API. Extend your Tile with action triggers or timeline schedules for richer interactions.

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Other Insights

Other Insights

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025