Most Flutter apps never need custom native code. Plugins on pub.dev cover the camera, push notifications, payments and storage well enough. Then a requirement lands that no plugin handles properly: a lock-screen widget, background GPS that survives the app being swiped away, a health data sync, a vendor SDK that only ships for Swift and Kotlin. That's the point where you need a Flutter platform channels developer, someone who writes the Dart side and the native side and owns the bridge between them. This post is for founders and product owners trying to work out whether they're at that point, and how to tell a capable hire from someone who has only read the docs.
When your app actually needs platform channels
A platform channel is how Dart talks to Swift, Kotlin, or Objective-C inside the same app. Flutter gives you three kinds, and a developer should be able to tell you which one fits your problem without looking anything up:
- MethodChannel for request and response. "Start a workout session", "read today's step count", "open this vendor SDK's checkout". Dart calls, native answers once.
- EventChannel for a stream of updates from native to Dart. Location fixes, sensor readings, a download's progress, a Bluetooth device's state.
- BasicMessageChannel for simple two-way messages with a custom codec. Less common in app work.
Then there's Pigeon, a code generator from the Flutter team. You describe the interface once in Dart and it generates type-safe code for Swift, Kotlin and Dart (plus Java, Objective-C and C++), so you're not matching method names as strings on both sides. If your bridge has more than a handful of calls, Pigeon is usually the better choice, and a good developer will say so.
Signs you need this work:
- A feature exists only in a native SDK (HealthKit, Health Connect, a bank's or a hardware vendor's SDK).
- The plugin that claims to do it is unmaintained, has open crash reports, or doesn't support the OS version you need.
- You need something that runs outside the Flutter UI: home screen widgets, Live Activities, background location, a foreground service on Android.
- Performance-sensitive work (image processing, high-frequency sensor data) where crossing into Dart for every sample costs too much.
Signs you don't: you've found a plugin with recent releases, an active issue tracker and the features you need. Use it. Custom native code is code you maintain through every iOS and Android release.
What to look for in a Flutter platform channels developer
The hard part of this job isn't the channel. It's the native platform on the other end. Someone who writes great Dart but has never shipped Swift will get the happy path working and then lose a week to a background task that iOS suspends long before the work is done. So test for the native side directly.
Questions worth asking
- "Which thread does a channel handler run on, and what happens if native code replies from a background thread?" Flutter's docs require channel handlers to be invoked on the platform's main thread. A good answer mentions dispatching back to the main queue on iOS, and background task queues on Android for heavy work.
- "How do you handle errors across the bridge?" You want to hear about returning structured errors (Flutter's
PlatformExceptionon the Dart side, typed error codes from native) instead of letting native exceptions crash the app or silently return null. - "What happens to your EventChannel stream when the app goes to the background, or the user revokes a permission halfway through?" This is where background location and health integrations break. Listen for an answer that covers cancelling native listeners when Dart stops listening.
- "Would you use Pigeon here? Why or why not?" Either answer can be right. No answer is a warning.
- "Show me native code you've shipped." A store link and a walkthrough of the Swift or Kotlin side tells you more than any certificate.
Red flags
- Proposes platform channels for something a well-maintained plugin already does.
- Can't explain iOS background execution limits or Android's foreground service rules for the feature you're describing.
- Plans to test only on a simulator. Health data, GPS and widgets all behave differently on real devices.
- Writes the bridge with string method names scattered across files and no single place that lists the contract.
- Quotes the feature without asking which OS versions you support.
What good platform channel work looks like when it's handed over
You'll probably own this code longer than the developer who wrote it. When the work is done you should get:
- One clearly named Dart class per native capability (for example, a
HealthBridge) that the rest of the app talks to, so the channel details stay in one file. - Matching native files in the iOS and Android folders, not logic buried inside
AppDelegateorMainActivity. - A written note on permissions, entitlements and background modes each feature needs, because these are what break at App Store review.
- Tests for the Dart side with the channel mocked, and a short manual test list for the device-only behaviour.
Here's what this looked like for us. In Crumb Count we connected Flutter to HealthKit and Health Connect through platform channels into Swift and Kotlin, and built native widgets, Live Activities and Dynamic Island support. In Kompete, a running app, background location runs through platform channels so tracking keeps going when the screen is off. Neither of those could have been done in Dart alone, and both needed most of their testing time on physical phones.
Hiring one person or a team
If the native work is a bounded piece (one SDK, one widget, one background feature), a short fixed-scope engagement is usually cheaper than a hire. You get the bridge, the docs and a handover, and your existing Flutter team keeps going. If native features are central to your product roadmap, you want someone on the team long term who reads Swift and Kotlin as comfortably as Dart.
orithLabs builds Flutter apps with native Swift and Kotlin where the platform needs it, and the person you talk to on the first call is the person who writes the code. See our mobile development page if you'd like to talk through a specific integration.