Tuesday, February 10, 2026
HomeFlutterHow to use native code in flutter

How to use native code in flutter

Using native code in Flutter is totally normal—and powerful—when you need platform-specific features (camera APIs, sensors, SDKs, payment gateways, etc.). Flutter does this via Platform Channels (and a couple of newer options). Let’s walk it step-by-step, clean and practical. 👇


🔹 Ways to Use Native Code in Flutter

  1. Platform Channels (Most common)
  2. Flutter Plugins
  3. Pigeon (Type-safe platform channels)
  4. FFI (For C/C++ native libraries)

I’ll focus mainly on Platform Channels, because that’s what you’ll use 90% of the time.


✅ 1. Platform Channels (Dart ↔ Native Communication)

Platform Channels allow Flutter (Dart) to talk to:

  • Android → Kotlin / Java
  • iOS → Swift / Objective-C

📌 Use case examples

  • Get battery level
  • Call native SDK
  • Access hardware features not supported by Flutter

🔹 Step 1: Create a MethodChannel in Flutter (Dart)

import 'package:flutter/services.dart';

class NativeService {
  static const platform = MethodChannel('com.example/native');

  static Future<String> getNativeMessage() async {
    try {
      final String result =
          await platform.invokeMethod('getNativeMessage');
      return result;
    } catch (e) {
      return "Failed to get native message";
    }
  }
}

Call it from UI:

ElevatedButton(
  onPressed: () async {
    String message = await NativeService.getNativeMessage();
    print(message);
  },
  child: Text("Call Native Code"),
)

🔹 Step 2: Android Native Code (Kotlin)

📍 File:
android/app/src/main/kotlin/.../MainActivity.kt

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example/native"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
            .setMethodCallHandler { call, result ->
                if (call.method == "getNativeMessage") {
                    result.success("Hello from Android Native Code 🚀")
                } else {
                    result.notImplemented()
                }
            }
    }
}

🔹 Step 3: iOS Native Code (Swift)

📍 File:
ios/Runner/AppDelegate.swift

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    let controller = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(
      name: "com.example/native",
      binaryMessenger: controller.binaryMessenger
    )

    channel.setMethodCallHandler { call, result in
      if call.method == "getNativeMessage" {
        result("Hello from iOS Native Code 🍏")
      } else {
        result(FlutterMethodNotImplemented)
      }
    }

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

✅ Result

Flutter → Native → Flutter
✔ Works on Android
✔ Works on iOS
✔ Same Dart API


🔹 2. Creating a Flutter Plugin (Best Practice)

If you plan to reuse native code across multiple apps:

flutter create --template=plugin my_native_plugin

This gives:

  • Dart API
  • Android native code
  • iOS native code

✅ Clean
✅ Reusable
✅ Production-ready


🔹 3. Pigeon (Type-Safe Platform Channels)

Instead of strings & maps, Pigeon generates:

  • Dart
  • Kotlin
  • Swift

Best for:

  • Large apps
  • Clean architecture
  • No runtime type errors

📌 Example use cases:

  • Payments
  • Complex data models

🔹 4. FFI (Calling C/C++ Code)

Use dart:ffi when:

  • You already have C/C++ libraries
  • High-performance native computation
import 'dart:ffi';

Not for Android/iOS APIs—only native libraries.


🧠 Best Practices

✅ Keep channel names unique
✅ Handle errors properly
✅ Don’t block UI thread in native code
✅ Use plugins for reusable logic
✅ Prefer Pigeon for large projects


🚀 When Should YOU Use Native Code?

✔ Flutter doesn’t support a feature
✔ Existing native SDK
✔ Performance-critical logic
✔ Platform-specific behavior

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments