Method Channels in Flutter: solved exercise with native Android and iOS code
Method Channels in Flutter: solved exercise with native code
Platform channels are Flutter’s mechanism for calling native Android (Kotlin/Java) and iOS (Swift/Objective-C) APIs that have no pub.dev plugin, or when you need low-level platform access. MethodChannel is the most common channel: it enables synchronous request-response calls from Dart to native code.
Problem statement
Implement a screen that reads the device battery level using native code:
- Define the
MethodChannelwith a unique name in Dart. - Implement the handler in Kotlin (
MainActivity.kt) for Android. - Implement the handler in Swift (
AppDelegate.swift) for iOS. - Display the percentage with an icon that changes based on the level.
- Handle
PlatformExceptionwhen the battery is unavailable.
Dependencies
Only the Flutter SDK — MethodChannel is in package:flutter/services.dart.
Full solution
Flutter (Dart)
Android — android/app/src/main/kotlin/.../MainActivity.kt
iOS — ios/Runner/AppDelegate.swift
Key concepts
| Concept | Detail |
|---|---|
MethodChannel('name') | Channel identified by a unique name; must match in Dart and native |
channel.invokeMethod<T>('method') | Calls the native method and awaits T; throws PlatformException on error |
result.success(value) | Native responds with success and a value |
result.error(code, msg, details) | Native responds with error → PlatformException in Dart |
result.notImplemented() | Method is not implemented on this native side |
PlatformException | Typed error from the native layer; has code and message |
configureFlutterEngine | Android override to register channels |
FlutterMethodChannel | iOS equivalent of MethodChannel in Dart |
Common mistakes
- Channel name mismatch: if the string in Dart differs from native,
invokeMethodreturnsnullor throws. Use a shared constant or document the name clearly. result.success()called multiple times: the native channel can only respond once per call. Callingresult.success()twice throws a native exception.- Not covering
else -> result.notImplemented(): without this case, unknown methods hang indefinitely waiting for a response. - Testing on iOS simulator:
isBatteryMonitoringEnableddoes not work on simulators. Use a physical device or return a mock value in debug mode.
Practical application
Platform channels are the standard path for low-level Bluetooth, NFC, high-frequency accelerometer sensors, custom Face ID/Touch ID, or any system API that existing plugins do not cover. The MethodChannel pattern is the most common; for continuous events from native to Flutter, use EventChannel, which provides a Stream in Dart.
Recommended next exercises
- Biometrics with local_auth in Flutter: solved exercise
- Permissions with permission_handler in Flutter: solved exercise
- All Flutter exercises
Guided practice and next step
- More Flutter exercises
- C exercises to strengthen fundamentals
- Programming in C in 100 Solved Exercises
- View on Amazon (included in Kindle Unlimited)
FAQ
Is it better to use an existing plugin or create a custom Method Channel?
Always search pub.dev first. Custom platform channels have a maintenance cost: you need to update native code when the OS API changes. If no plugin exists or the existing ones don’t cover your case, then a custom channel is the right solution.
Can I send data in both directions?
MethodChannel is request-response: Dart calls, native responds. For continuous events from native to Dart (sensors, Bluetooth, real-time geolocation), use EventChannel, which provides a Stream in Dart.
Do Method Channels work on Flutter Web and Desktop?
On Web there is no equivalent native code; use JavaScript interop with dart:js_interop. On Desktop (macOS, Windows, Linux) platform channel equivalents exist with each platform’s APIs.