Lesson 21 / 25
Platform Channels, Plugins and Permissions
Reaching native APIs.
Talking to Kotlin, Swift and friends
Most native features (camera, location, sensors, payments) are already wrapped by plugins on pub.dev; check platform support, maintenance and the "Flutter Favorite" or verified publisher badges before adopting one. When nothing fits, a platform channel sends asynchronous messages between Dart and native code: a MethodChannel on the Dart side calls invokeMethod, and Kotlin or Swift code registered on the same channel name handles it and returns a result or error (surfaced as PlatformException). Pigeon generates type-safe channel code from a Dart interface, and dart:ffi calls C libraries directly. Runtime permissions are typically requested with the permission_handler package, but you must also declare them in AndroidManifest.xml and add usage descriptions to iOS Info.plist.
Calling native code over a MethodChannel
Dart side; Kotlin/Swift register a handler for the same name.
import 'package:flutter/services.dart';
class Battery {
static const _channel = MethodChannel('com.example.app/battery');
Future<int?> level() async {
try {
return await _channel.invokeMethod<int>('getBatteryLevel');
} on PlatformException catch (e) {
debugPrint('Battery unavailable: ${e.message}');
return null;
}
}
}
// permission_handler (check the docs for your version)
// final status = await Permission.camera.request();
// if (status.isGranted) { openCamera(); }Explain before you ask
Show your own screen explaining why a permission is needed before the system prompt, and handle the "permanently denied" case by offering a link to app settings.
Quick check: What Dart class sends method calls to native Android or iOS code?
- FutureBuilder
- MethodChannel
- InheritedWidget
- GoRouter
Answer
MethodChannel — Native code registers a handler on the same channel name.