Platform Channels
When Dart is not enough
Section titled “When Dart is not enough”Flutter draws its own pixels, but some things live only in the native OS — the battery level, a specific sensor, a platform SDK, the secure enclave. To reach them, Flutter uses platform channels: a typed, asynchronous message pipe between your Dart code and native (Kotlin/Java on Android, Swift/Objective-C on iOS).
The model is the same async message passing you already know from Dart: you send a message, the native side handles it, and a Future completes with the reply. Nothing blocks the UI thread.
flowchart LR
dart["Dart
invokeMethod('getBattery')"] -->|message| platform["platform channel"]
platform --> native["native code
reads battery level"]
native -->|reply| platform
platform -->|Future completes| dart MethodChannel: call a native method
Section titled “MethodChannel: call a native method”A MethodChannel names a pipe and lets you invokeMethod on it. The call is async and returns a Future with the native result. Arguments and results are standard types (numbers, strings, lists, maps) serialized across the boundary.
const channel = MethodChannel('samples.app/battery');
Future<int> getBatteryLevel() async { try { final level = await channel.invokeMethod<int>('getBatteryLevel'); return level ?? -1; } on PlatformException catch (e) { // native side reported an error return -1; }}The native side registers a handler for the same channel name and switches on the method string to run the real platform code.
EventChannel: a stream of native events
Section titled “EventChannel: a stream of native events”Where MethodChannel is one call and one reply, an EventChannel delivers a stream of events from native — sensor updates, connectivity changes, location. It maps to a Dart Stream, so you consume it exactly like any other stream.
const events = EventChannel('samples.app/accelerometer');
Stream<AccelData> accelerometer() { return events.receiveBroadcastStream().map((e) => AccelData.parse(e));}Plugins vs raw channels
Section titled “Plugins vs raw channels”You rarely write channel code by hand. A plugin is a package that wraps platform channels plus the native implementation behind a clean Dart API — battery_plus, geolocator, camera. Reach for a well-maintained plugin first; write a raw channel only for something bespoke to your app.
Declaring assets
Section titled “Declaring assets”Not native, but part of app structure: images, fonts, and JSON you bundle must be declared in pubspec.yaml so they ship with the app.
flutter: assets: - assets/images/logo.png - assets/data/ fonts: - family: Inter fonts: - asset: assets/fonts/Inter-Regular.ttf// Then load them by their declared path:Image.asset('assets/images/logo.png');