Skip to content
tezvyn:
Menu

Safely gating native OS version APIs in a custom Flutter plugin

Source: docs.flutter.devMediumHow cards are made

Tests platform channel contracts and defensive native coding. Gate native calls with OS version checks, return result.error with an UNSUPPORTED code, handle PlatformException in Dart, and avoid Dart-only checks.

What's really being asked

This question evaluates whether you understand the full contract across a Flutter MethodChannel, specifically how to write defensive native code that avoids runtime crashes on older operating systems and how to communicate three distinct outcomes, success, failure, and feature unavailable, back to Dart in a structured way. It also tests whether you know that the native side must be the final authority on API availability.

The full answer

A good answer hits four things in order. First, on Android, wrap the call in a check for Build.VERSION.SDK_INT >= Build.VERSION_CODES.R, which is API 30, and on iOS use if #available(iOS 15, *) in Swift or @available checks in Objective-C before calling the newer API. Second, design a result contract: if the version gate fails, return result.error with a well-defined error code such as UNSUPPORTED_OS and a clear message, or alternatively return result.success with a structured map that includes a status field so Dart can parse it consistently. Third, on the Dart side, wrap the invokeMethod call in a try-catch block that catches PlatformException and inspects the error code to distinguish between unsupported OS, missing permissions, and runtime failures. Fourth, explicitly state that Dart-side version checks using Platform.operatingSystemVersion are useful for UI hints but must not be the only guard, because the native implementation is the source of truth and Dart checks can drift or be spoofed.

The mistakes people make

The biggest red flag is calling the native API unconditionally and letting the app crash on older devices with a NoSuchMethodError on Android or an unrecognized selector on iOS. Another red flag is returning result.success with an error string inside the payload, which forces Dart to parse text instead of using typed error codes. Some candidates suggest checking the OS version only in Dart and skipping the MethodChannel call from there; this is incorrect because it creates a race condition and duplicates logic that belongs in native code. Finally, throwing a Kotlin or Swift exception without catching it inside the platform channel method will cause an unhandled channel error that surfaces in Dart as a generic platform exception with no useful code.

What usually comes next

An interviewer might ask how you would unit test the unsupported path without maintaining physical devices running old OS versions. The answer is to mock the MethodChannel in Dart widget tests and to write native unit tests that mock Build.VERSION.SDK_INT or the iOS system version before invoking the plugin method. Another follow-up is how you expose this cleanly in your public Dart API; the best practice is to define a sealed class or a custom exception hierarchy so consumers receive strongly typed results instead of raw PlatformException objects. You might also be asked what happens if the OS version is sufficient but the hardware lacks support, in which case you add a second runtime capability check after the version gate and return a different error code such as UNSUPPORTED_HARDWARE.

A concrete example

Suppose your plugin exposes a scanNearbyWifi method. In Kotlin, you write if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val results = wifiManager.scanResults; result.success(results) } else { result.error("UNSUPPORTED_OS", "Requires Android 11 or higher", null) }. In Swift, you write if #available(iOS 15, *) { NEHotspotConfigurationManager.shared.getConfiguredSSIDs { ssids in result(ssids) } } else { result(FlutterError(code: "UNSUPPORTED_OS", message: "Requires iOS 15 or higher", details: nil)) }. In Dart, you define a WifiScanResult class with subclasses Available, Failed, and Unsupported, and you map PlatformException(code: "UNSUPPORTED_OS") to WifiScanResult.unsupported(). This keeps the native side authoritative and the Dart side predictable.

Interview question

You are writing a Flutter plugin that wraps a native API available only on Android 11+ and iOS 15+. How should your plugin handle invocations from older OS versions?

  • a.Check the OS version in Dart using Platform.operatingSystemVersion and avoid calling the method channel on older devices.
  • b.Invoke the native API unconditionally and let the platform exception propagate to Dart as a generic error.
  • c.Return result.success containing an error string when the OS version is insufficient, then parse that string in Dart.
  • d.On the native side, verify the OS version before calling the API and return result.error with a code like UNSUPPORTED_OS if the version is too low.Correct
Why?

B is correct because the native implementation must be the source of truth for API availability, and returning a structured error code lets Dart distinguish unsupported OS versions from other failures. A is tempting but wrong because Dart-side version checks can drift or be spoofed, and they duplicate logic that belongs in native code.

Just read this? Test yourself on what you have been reading.

Read the original → docs.flutter.dev

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on flutter — each one lists the topics its interview covers.

See open roles