Call Platform Code

Start with the highest-level boundary that solves the problem.

Choose The Boundary

NeedUse
Common device capabilityExisting plugin
A few app-owned native callsMethodChannel
Larger typed host APIPigeon
C-compatible native libraryFFI
Native UI inside FlutterPlatform view
Browser API on webJS interop

MethodChannel Shape

Keep the Dart side small and typed at your app boundary:

import 'package:flutter/services.dart';

class BatteryService {
  static const _channel = MethodChannel('app.example/battery');

  Future<int> batteryLevel() async {
    final level = await _channel.invokeMethod<int>('batteryLevel');
    if (level == null) {
      throw StateError('Platform returned no battery level');
    }
    return level;
  }
}

Then hide BatteryService behind a repository or view model dependency so tests can fake it.

Rules

  1. Document channel names and method names.
  2. Validate arguments and nulls on both sides.
  3. Keep platform calls asynchronous.
  4. Test missing plugin and unsupported platform paths.
  5. Avoid calling platform code directly from widgets.

Gotcha: Web does not use normal platform channels for browser APIs. Plan a web-specific interop path or mark web unsupported for the feature.