Your Flutter app must read a Bluetooth thermometer on Android, iOS and web: how do you decide between adopting an existing plugin, extending it, or writing your own federated plugin?
answer
- per-platform coverage, not the README
- maintenance and SwiftPM readiness
- non-endorsed package fills one gap
- vendor SDK or protocol forces ownership
- every owned plugin is native upkeep
basics
~20 sAdopt when an existing plugin covers every target platform with active maintenance; fill a single missing platform with your own implementing package rather than a fork; write your own federated plugin only when a vendor SDK, protocol or roadmap no public plugin can serve forces it.
solid answer
~50 sI start from requirements per platform, not from a package search: which devices, which Bluetooth operations, which browsers for the web target. Then I audit candidates by their pubspec `platforms:` map and implementing packages, release history, open issues on the platforms I need, Swift Package Manager readiness and license. If one plugin covers everything, adopt it behind a thin repository interface so it can be swapped. If it lacks one platform, the federated design lets me publish or vendor a **non-endorsed implementing package** and add it as a direct dependency — or contribute it upstream for endorsement — instead of forking. I write my own federated plugin when the thermometer needs a vendor's native SDK or a proprietary protocol, or when no candidate is maintained; then I budget for native upkeep on three platforms, keep the platform interface small, and use Pigeon for typed messages.
go deeper
Know that you check a plugin's supported platforms before adopting it and that a plugin brings native code the app must build.
Explain how to verify coverage from the pubspec platforms map and how a direct dependency lets you choose a different implementation.
Lay out the audit — coverage, maintenance, SwiftPM readiness, API shape, license — and wrap the adopted plugin so it can be replaced.
Argue the ownership-versus-control tradeoff, including the middle option of owning one platform package, and name the triggers that would change the decision.
## Why this is a judgment call A plugin is native code on every platform it supports. Adopting one means inheriting someone else's release cadence and bugs; writing one means owning Kotlin, Swift and web code, their build systems and every OS update. There is no universally right answer — the decision depends on coverage, risk and how central the capability is to the product. ## Step 1: pin the requirements per platform Before looking at packages, write down per target: - **Android** — which OS versions and which Bluetooth operations (scan, connect, read a characteristic, subscribe to notifications). - **iOS** — the same operations, the minimum iOS version, and background behaviour if readings must continue off-screen. - **Web** — which browsers must work. Browser support for Bluetooth is uneven, so the web target may need a fallback path in the UI whatever package you pick. - Whether the thermometer speaks a standard profile or requires the **vendor's own SDK**. Permissions and their prompts are a separate concern (owned by the app-lifecycle and permissions topic) but belong on the same checklist. ## Step 2: audit candidates by evidence | Signal | Where to look | Why it matters | |---|---|---| | Platform coverage | The pubspec `flutter: plugin: platforms:` map and any `default_package` implementing packages | The README can claim more than the pubspec actually registers | | Maintenance | Release history, issue response on *your* platforms | A stale plugin becomes your fork | | Apple readiness | A `Package.swift` alongside the podspec | Since Flutter 3.44, SwiftPM is the default | | API shape | Stream-based readings, error types, cancellation | Leaks and error handling are hard to retrofit | | License | The package's LICENSE | Must fit the product's distribution | ## Step 3: choose among four options 1. **Adopt as is.** Coverage and maintenance are good. Wrap it behind your own small Dart interface (a repository or service class) so the rest of the app never imports the plugin directly and a swap stays cheap. 2. **Extend with an implementing package.** One platform is missing or weak — say, the web. Because the plugin is federated, write `thermo_web_custom` that extends its platform interface and declares `implements:`; the app lists it as a direct dependency, which the Flutter tool prefers over the endorsed default. Offer it upstream so it can become endorsed and you stop carrying it. 3. **Fork.** Only when the maintainer is gone *and* the changes cut across platforms. A fork is an ongoing obligation: you merge upstream fixes by hand. 4. **Write your own federated plugin.** The device needs a vendor SDK, a proprietary protocol, or behaviour no candidate offers, or thermometer readings are core product value you must control. Structure it as app-facing, platform-interface and one package per platform so each can move independently. ## Step 4: if you write it, limit what you own - Keep the **platform interface small** and grow it by adding methods with throwing default bodies, so platform packages are not forced to change in lockstep. - Generate channel code with **Pigeon** rather than hand-written string method names; that topic has its own questions. - Ship both a podspec and `Package.swift` for iOS while unmigrated apps exist. - Budget per platform: CI builds on Android, iOS and web, device testing with real thermometers, and time for each OS release. ## The principal-level tradeoff The deciding question is ownership cost versus control. Adopting is cheapest until the plugin stalls on the platform you need; writing is most controllable but multiplies native maintenance by three. Federation narrows the gap: it lets a team own **only the platform where it disagrees with upstream** instead of the whole plugin. A good answer names that middle option and says what would trigger moving from one option to the next — for example, "we adopt, wrap it, and switch to our own web implementation if upstream has not fixed reconnects within two releases".
- Why wrap an adopted plugin behind your own Dart interface?The wrapper confines the plugin's API to one place. If the plugin stalls or a platform needs a custom implementation, you change one class instead of every screen, and tests can substitute a fake without touching the plugin's platform interface.
- When is forking the plugin better than adding a non-endorsed implementing package?When the fix spans the app-facing API or several platforms at once, so a single implementing package cannot express it, and the maintainer is unresponsive. Otherwise an implementing package keeps you on upstream's app-facing releases and limits what you carry.
saying these in an interview costs you the question
- Pick whichever Bluetooth package appears first in search results.
- A missing platform means you must fork the whole plugin.
- Writing your own plugin is always cheaper in the long run.
- The README's platform list proves the platforms are implemented.
- Web support can be assumed to match mobile once the plugin compiles.