Flutter plugins with Apple Watch (watchOS) support, maintained by the flutterwatch.dev organization.
These are companions to flutter-watchos
— the Flutter watchOS custom embedder. Most are federated *_watchos
implementations of popular pub.dev plugins, produced with the
flutter-watchos plugin port tool and finished/verified by hand.
Every package here is on pub.dev under the
flutterwatch.dev
publisher (see Usage).
watchOS plugins ship native code via dart:ffi: the package exports C
symbols from watchos/Classes/*.m, declares them under
flutter.plugin.platforms.watchos.ffiSymbols, and the flutter-watchos
CLI statically links them into the watch binary where Dart resolves them
with DynamicLibrary.process(). A plugin can additionally ship native
SwiftUI platform views (watchos/Views/*.swift) that the CLI compiles
into the app and the plugin embeds with WatchPlatformView
(package:flutter_watchos) — see video_player_watchos. Method-channel
plugins are not supported on watchOS — a package whose watchos: block
declares only pluginClass: will build but its channel calls throw
MissingPluginException (the CLI warns about this at build time).
One package here is not a port of an upstream plugin, because there is no upstream to port: WatchConnectivity is the only transport Apple provides between a watch and its phone, and it needs an implementation on both sides.
| Plugin | What it is | Backend |
|---|---|---|
flutter_watch_link |
First-party. One Dart API for phone↔watch messaging, application context, and guaranteed transfers — the same code on both devices. | WCSession (one FFI implementation, compiled for both) |
Upstream watch_connectivity is
phone-side only, and its "platform interface" is explicitly not a federated one
— there is no instance hook to implement — so a *_watchos implementation of
it is not possible. It also has no transferUserInfo, which is the tier a
companion app needs when the counterpart is asleep.
See its example/ for a worked
companion app — one main.dart, running on both devices.
Every plugin below has a watchOS implementation, and each package's example
builds and starts on the watchOS 27.0 Simulator. Three of those examples
start with an error: sensors_plus_watchos (the barometer is not
implemented), in_app_purchase_watchos (the StoreKit platform addition it
asks for fails) and network_info_plus_watchos (the example's
permission_handler has no watchOS implementation). What each package
covers and what it leaves out are in its README.md. Its
PORTING_REPORT.md records how the package was ported and what was checked
at the time; the last full run on the Simulator is under
Examples & tests.
| Plugin | Upstream | watchOS backend |
|---|---|---|
path_provider_watchos |
path_provider |
NSSearchPathForDirectoriesInDomains |
shared_preferences_watchos |
shared_preferences |
NSUserDefaults |
package_info_plus_watchos |
package_info_plus |
NSBundle |
device_info_plus_watchos |
device_info_plus |
WKInterfaceDevice |
url_launcher_watchos |
url_launcher |
ASWebAuthenticationSession (web pages on the watch), WKApplication.openSystemURL (tel:/sms:), NSUserActivity Handoff (web, externalApplication) |
battery_plus_watchos |
battery_plus |
WKInterfaceDevice battery |
connectivity_plus_watchos |
connectivity_plus |
nw_path_monitor |
flutter_secure_storage_watchos |
flutter_secure_storage |
Keychain (SecItem*) |
network_info_plus_watchos |
network_info_plus |
getifaddrs (IP; no SSID) |
sensors_plus_watchos |
sensors_plus |
CoreMotion (CMMotionManager) |
local_auth_watchos |
local_auth |
LocalAuthentication (passcode) |
geolocator_watchos |
geolocator |
CoreLocation (CLLocationManager) |
video_player_watchos |
video_player |
AVFoundation + AVKit platform view |
audioplayers_watchos |
audioplayers |
AVFoundation (AVPlayer) |
in_app_purchase_watchos |
in_app_purchase |
StoreKit (SKProductsRequest, SKPaymentQueue) |
games_services_watchos |
games_services |
GameKit (GKLeaderboard, GKLocalPlayer) — leaderboards only † |
firebase_core_watchos |
firebase_core |
Firebase Apple SDK (FirebaseCore) |
firebase_auth_watchos |
firebase_auth |
Firebase Apple SDK (FirebaseAuth) |
firebase_storage_watchos |
firebase_storage |
Firebase Apple SDK (FirebaseStorage) |
firebase_messaging_watchos |
firebase_messaging |
Firebase Apple SDK (FirebaseMessaging) |
† games_services_watchos: sign-in and score
submission have been observed working on a physical Apple Watch;
reading leaderboard entries has not — GKLocalPlayer reports an
authenticated player with an unresolved alias and GameKit then refuses
the read. The app under test was side-loaded rather than installed
through its companion, which is the leading suspect. See its
PORTING_REPORT.md.
First-party watch capabilities (platform detection, device info, haptics,
Digital Crown) ship in
flutter_watchos
itself — check there before adding a plugin.
These upstream plugins' core capability does not exist on watchOS, so a published package would be misleading:
| Plugin | Why not on watchOS |
|---|---|
webview_flutter |
No WebKit in the watchOS SDK, so no embeddable web view; a page can only be shown as a full-screen system sheet, which url_launcher_watchos does |
google_sign_in |
No GoogleSignIn watchOS SDK; sign-in is delegated to the paired iPhone |
image_picker |
No camera and no photo-picker UI on the watch |
google_maps_flutter |
No Google Maps SDK for watchOS (an Apple MapKit backend would not honestly implement the interface) |
Note the difference from tvOS: CoreLocation, HealthKit, CoreMotion, StoreKit purchasing, and (watchOS 9+) LocalAuthentication all exist on the watch — plugins built on those are portable, not excluded.
These have a watchOS-viable native backend and are good future additions;
they are simply out of scope for now (large surface or partial support):
sqflite (SQLite), flutter_tts (AVFoundation),
wakelock_plus (only a session-typed WKExtendedRuntimeSession, not a
general idle-timer disable), and cloud_firestore (the Firebase Apple SDK
ships Firestore's core as a prebuilt binary with no watchOS slice, so a
port needs Firebase's from-source Firestore build; the rest of the
network-viable Firebase family — core, auth, storage, messaging — is
ported above).
The upstream plugins do not endorse a watchOS implementation, so add
the *_watchos package to your app explicitly, alongside the upstream
plugin:
dependencies:
shared_preferences: ^2.5.5
shared_preferences_watchos: ^0.1.0The version badges in the table above are the current published versions —
use those, since these packages are still pre-1.0 and a caret constraint on
0.x is narrower than you may expect.
Then call the upstream plugin's API — the *_watchos implementation
registers automatically via Flutter's federated plugin runner, with no
imports or client code changes. Not every method has a watchOS counterpart:
each package's README lists the ones that do not, and what they do instead.
flutter_watch_link is the exception: it is not an implementation of an
upstream plugin, so depend on it on its own and call its API directly —
in the iPhone app and the watch app alike.
dependencies:
flutter_watch_link: ^0.1.0A few packages need a writable directory and therefore also
path_provider_watchos: e.g. video_player_watchos (for
VideoPlayerController.file). Their READMEs note this.
Each ported package ships the upstream plugin's own example (its demo
lib/ and, where upstream has one, its official integration_test/), ported
by flutter-watchos plugin port --include-example with a watchOS runner on
top, plus host-side unit tests. The example imports only the app-facing
plugin, and the *_watchos implementation registers itself through
federation. The four Firebase packages add a smoke test, because their
upstream examples have none. To run an integration test on the Simulator:
cd packages/<plugin>_watchos/example
flutter-watchos drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/<test-file> -d <watch-sim>On the watchOS 27.0 Simulator, on 29 September 2026:
- Pass: path_provider, shared_preferences, battery_plus,
connectivity_plus, sensors_plus, network_info_plus, local_auth,
games_services, device_info_plus, url_launcher, video_player (both of its
tests), in_app_purchase (
in_app_purchase_testandregistration_test), and firebase_core's smoke test. Some cases skip themselves off Android, as upstream intends. - Fail, for reasons outside the plugin's native code:
- package_info_plus:
fromPlatformpasses; theexampletest is a phone-UI sweep that looks for more of the demo's list than a watch screen shows. - flutter_watch_link: two of its tests wait for the session to activate, which needs an iPhone Simulator paired with the watch Simulator. On an unpaired one they fail.
- flutter_secure_storage: the upstream
app_testwas written forflutter_secure_storage10.x. The example resolves 11.x, which no longer has two cipher names the test uses, so the test does not compile. - audioplayers (
lib_test): one case streams a file from a remote server that now answers 404.
- package_info_plus:
- Not run: the firebase_auth, firebase_messaging and firebase_storage
smoke tests; audioplayers'
app_testandplatform_test; and in_app_purchase'spurchase_testandstorekit_products_test, which need StoreKit test products (see that package's README). geolocator's upstream example has nointegration_test/(its demo is manual); its example builds and starts.
Where an official test surfaced a genuine behavioural gap, the fix went into the
implementation, not the test — e.g. shared_preferences_watchos now throws
TypeError on a wrong-typed read (matching every other platform), and
package_info_plus_watchos now returns installerStore / installTime /
updateTime natively.
These packages were not hand-written from scratch. Each was generated with
the flutter-watchos plugin port tool (part of
flutter-watchos) and then
verified — and where needed finished — by hand.
flutter-watchos plugin port takes an existing Apple plugin (the iOS
implementation package) and emits a federated *_watchos FFI scaffold.
# from a published pub.dev package (what we used):
flutter-watchos plugin port --from-pub shared_preferences_foundation \
--output packages/shared_preferences_watchos --include-example
# or from git, or from a local path:
flutter-watchos plugin port --from-git https://github.com/foo/bar.git --ref main --output ...
flutter-watchos plugin port ../some_plugin_ios --output ...The exact upstream source for each package is recorded at the top of its
PORTING_REPORT.md (e.g. video_player_watchos ←
video_player_avfoundation, shared_preferences_watchos ←
shared_preferences_foundation, audioplayers_watchos ←
audioplayers_darwin).
What the porter does automatically: lays out the federated package
(pubspec, lib/, watchos/, analysis_options.yaml, LICENSE,
CHANGELOG.md), federates through the upstream *_platform_interface,
emits an FFI header/.m scaffold with the C-symbol declarations wired into
flutter.plugin.platforms.watchos.ffiSymbols, generates a
PORTING_REPORT.md recording the source, the watchOS capability outlook
(driven by a watchOS API-availability database), and a checklist, and — with
--include-example — ports the upstream example app and its official
integration_test/ verbatim under a watchOS runner.
Every package gets a PORTING_REPORT.md: the source + version, the watchOS
capability outlook, the FFI surface, every unsupported region with the
reason, and a ## Verification status table. Read it before trusting a port.
The porter emits a scaffold, not a working backend (by design — the
native .m functions are stubs). The real native implementation is written
by hand against the platform interface, following
AUTHORING.md and path_provider_watchos as the reference.
A package only joins the list once it is green:
cd packages/<plugin>_watchos/example
flutter-watchos build watchos --simulator --debug # must be green
cd ..
flutter-watchos test # host unit tests
cd example
flutter-watchos drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/<test-file> -d <watch-sim> # real native code on-simPackages whose primary purpose can't work on watchOS are not shipped — they are documented under Evaluated but not provided rather than published broken.
See AUTHORING.md for the deeper per-plugin recipe.
plugins/
├── packages/<plugin>_watchos/ # one directory per plugin
│ ├── lib/ # Dart (federated impl + FFI bindings)
│ ├── watchos/Classes/ # native FFI (Objective-C, exported C symbols)
│ ├── watchos/Views/ # native SwiftUI platform views (optional)
│ ├── watchos/Package.swift # SwiftPM manifest
│ ├── example/ # upstream example + integration_test, verbatim
│ ├── test/ # host-side unit tests (FFI bindings faked)
│ ├── PORTING_REPORT.md # port detail + verification-status table
│ ├── README.md CHANGELOG.md LICENSE
└── AUTHORING.md # how to add a new one
- Federate via the upstream
*_platform_interface; suffix_watchos. - Ship native code as dart:ffi exported C symbols; method-channel
pluginClass:-only plugins are inert on watchOS. - Guard watchOS-unsupported APIs and document them in the package
README.mdandPORTING_REPORT.mdso users can assess compatibility. - Add host-side unit tests and, where the upstream has one, its official
integration_test/verbatim — fix gaps in the implementation, never the test. - A package only ships if it builds green and verifies on the watch simulator.
BSD-3-Clause — see LICENSE. Ported packages retain their upstream copyright; watchOS additions are © The FlutterWatch Authors.
These packages are an independent project and are not affiliated with, endorsed by, or sponsored by Google LLC, Apple Inc., or the authors of the upstream plugins. Flutter, Dart and Firebase are trademarks of Google LLC. Apple Watch and watchOS are trademarks of Apple Inc.