flutter_watch_connectivity
Define lightweight Apple Watch pages in Flutter, sync them to a paired Apple
Watch with WatchConnectivity, and render them in a native SwiftUI watchOS app.
Flutter widgets do not run on Apple Watch. This package sends a portable page schema from the iPhone app; the Watch App target renders that schema natively with the included SwiftUI renderer.
What this package does
- Lets your Flutter app define watch pages with Dart models.
- Sends those pages from iPhone to Apple Watch through
WCSession. - Provides a SwiftUI renderer file for the Watch App target.
- Supports basic watch components: text, buttons, spacers, and dividers.
What you still need to do
Apple requires a real watchOS target. A Flutter package cannot automatically create or fully configure that target for the host app.
Every app using this package must do a one-time Xcode setup:
- Add a Watch App target.
- Add the renderer file to that Watch App target.
- Link
WatchConnectivity.framework. - Run the iOS app and the Watch App on paired devices or simulators.
Install
Add the package to your app:
dependencies:
flutter_watch_connectivity: ^0.0.1
Then run:
flutter pub get
Define watch pages in Flutter
import 'package:flutter_watch_connectivity/flutter_watch_connectivity.dart';
const watch = FlutterWatchConnectivity();
Future<void> syncWatchPages() async {
await watch.configurePages(
initialPageId: 'home',
pages: const [
WatchPage(
id: 'home',
title: 'Daily summary',
components: [
WatchText('1,248 steps', style: WatchTextStyle.largeTitle),
WatchText('Move ring is 72% complete.'),
WatchSpacer(height: 10),
WatchButton(title: 'Refresh', action: 'refresh_summary'),
],
),
WatchPage(
id: 'hydration',
title: 'Hydration',
components: [
WatchText('4 cups logged', style: WatchTextStyle.title),
WatchDivider(),
WatchText('Goal: 8 cups'),
WatchButton(title: 'Add cup', action: 'add_water'),
],
),
],
);
}
Future<void> showHydrationPage() {
return watch.showPage('hydration');
}
Call configurePages(...) when your app has the data that should appear on the
watch. The package stores the latest payload in the watch connectivity
application context, so the watch can read it when it opens.
Add the Watch App target
Open the iOS workspace:
open ios/Runner.xcworkspace
In Xcode:
- Select the blue project icon.
- Choose
File -> New -> Target. - Select
watchOS -> Watch App. - Create the watch target for your iOS app.
- Use SwiftUI for the Watch App interface.
Add the renderer to the Watch App
Copy this file from the package into your Watch App target:
watchos/WatchConnectivityPageRenderer.swift
When adding the file in Xcode, make sure target membership is checked for the Watch App target, not only for the iOS Runner target.
Then replace your Watch App entry point with:
import SwiftUI
@main
struct MyWatchApp: App {
var body: some Scene {
WindowGroup {
WatchPageRenderer()
}
}
}
You can keep your own app struct name. The important part is that the watch
window shows WatchPageRenderer().
Link WatchConnectivity.framework
Some Xcode versions do not show a Watch Connectivity capability. That is OK.
Link the framework instead.
For the iOS app target:
- Select the iOS app target, usually
Runner. - Open
General. - Find
Frameworks, Libraries, and Embedded Content. - Click
+. - Add
WatchConnectivity.framework.
For the Watch App target:
- Select the Watch App target.
- Open
General. - Find
Frameworks, Libraries, and Embedded Content. - Click
+. - Add
WatchConnectivity.framework.
If you do not see that section, use:
Build Phases -> Link Binary With Libraries -> + -> WatchConnectivity.framework
Check build phase order
If your iOS app target has a watch companion app, Xcode can produce a dependency
cycle if the watch app is embedded after Flutter's Thin Binary script.
For the iOS app target, open Build Phases and keep this order:
Run Script
Sources
Frameworks
Resources
Embed Frameworks
Embed Watch Content
Thin Binary
If Embed Watch Content is below Thin Binary, drag it above Thin Binary.
Then run Product -> Clean Build Folder.
Run on simulators
You need a paired iPhone simulator and Apple Watch simulator.
- Open Xcode.
- Select the iOS app scheme, usually
Runner. - Select a paired iPhone simulator.
- Run the iOS app.
- Press the button in your app that calls
configurePages(...). - Select the Watch App scheme.
- Select the paired Apple Watch simulator.
- Run the Watch App.
The watch should show the latest page sent by the iOS app.
You can also build from the command line, but Flutter needs a concrete paired simulator id when the app has a watch companion:
flutter devices
flutter run -d <iphone-simulator-id>
Run on real devices
- Pair your real Apple Watch with your iPhone.
- Open
ios/Runner.xcworkspacein Xcode. - Select the iOS app target and set signing.
- Select the Watch App target and set signing.
- Run the iOS app on the iPhone.
- Run or install the Watch App on the paired Apple Watch.
- Open the iOS app and call
configurePages(...). - Open the Watch App.
If the watch opens first, it may show:
Open the iPhone app to sync watch pages.
Open the iOS app and sync pages again.
Test this package locally
From the package root:
flutter analyze
flutter test
flutter pub publish --dry-run
From the example app:
cd example
flutter test test
To compile only the example Watch App target:
cd example/ios
xcodebuild -project Runner.xcodeproj \
-target "RunnerWatchApp Watch App" \
-configuration Debug \
-destination generic/platform=watchOS \
build
Supported components
WatchText
const WatchText('Hello watch');
const WatchText('Big number', style: WatchTextStyle.largeTitle);
WatchButton
const WatchButton(title: 'Refresh', action: 'refresh');
Button taps are sent by the SwiftUI renderer as action messages. A Dart action stream is planned, but not exposed yet.
WatchSpacer
const WatchSpacer(height: 12);
WatchDivider
const WatchDivider();
Troubleshooting
I do not see a Watch Connectivity capability
That is normal in many Xcode versions. Add WatchConnectivity.framework to both
the iOS app target and the Watch App target.
Cycle inside Runner
Move Embed Watch Content above Thin Binary in the iOS app target's build
phases, then clean the build folder.
The watch shows the empty message
Run the iOS app and call configurePages(...). The watch needs page data from
the phone before it can render anything.
The watch layout looks old after changing the renderer
In Xcode, run Product -> Clean Build Folder, then rebuild the Watch App.
Can this package create the Watch App target automatically?
No. Flutter packages cannot create or fully configure host app Xcode targets. The one-time Watch App target setup must be done in Xcode.