DEV Community

Cover image for Supercharge Your Flutter App with Native Python Execution
Sumeet Sharma
Sumeet Sharma

Posted on

Supercharge Your Flutter App with Native Python Execution

Ever wondered if you could run native Python code directly inside your Flutter app? Yes, you read that right—it’s absolutely possible! As a senior mobile app developer working with both Flutter and hybrid stacks like Ionic, I’ll walk you through how to unlock this power in your next project.

Previously, I published a guide on running Python in native Android using Chaquopy. If you haven't gone through that setup yet, check out my Medium post first:

.

That post covers the foundational Chaquopy integration. Once you’ve set up the basic dependencies in your root and app-level Gradle files, you only need a small tweak to make things work smoothly with your Flutter setup.

Step 1: Adjust your root-level build.gradle.kts

buildscript {
    dependencies {
        classpath("com.android.tools.build:gradle:8.8.2")
        classpath("com.chaquo.python:gradle:16.1.0")
    }
}
Enter fullscreen mode Exit fullscreen mode

Keep the rest of your Chaquopy configurations from the Medium guide the same.

Step 2: Set up the Method Channel in Flutter
To bridge communication between Flutter (Dart) and Android native (Kotlin), create a Method Channel service in your Flutter code:

class MyMethodChannelService {
  static const platform = MethodChannel('my_method_channel');

  static Future<String> helloWorld() async {
    try {
      return await platform.invokeMethod('hello_world');
    } on PlatformException catch (e) {
      return 'Failed to invoke Python method: ${e.message}';
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This service lets you invoke native Android code from your Flutter widgets.

Step 3: Configure Kotlin (MainActivity.kt)
On the Kotlin side, set up the method channel with the same name, initialize Python (if not already started), and define the channel handler. This handler will listen for Flutter invocations and call the desired Python function..

private val CHANNEL = "my_method_channel"
private lateinit var python: Python
private lateinit var pythonModule: com.chaquo.python.PyObject

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    if (!Python.isStarted()) {
        Python.start(AndroidPlatform(this))
    }
    python = Python.getInstance()
    pythonModule = python.getModule("main")

    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
        when (call.method) {
            "hello_world" -> {
                handleAsyncCall(result) {
                    pythonModule.callAttr("hello_world").toString()
                }
            }
            else -> {
                result.notImplemented()
            }
        }
    }
}

private fun handleAsyncCall(result: MethodChannel.Result, pythonCall: suspend () -> String) {
    CoroutineScope(Dispatchers.IO).launch {
        try {
            val pythonResult = pythonCall()
            withContext(Dispatchers.Main) {
                result.success(pythonResult)
            }
        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                result.error("PYTHON_ERROR", "Error executing Python function: ${e.message}", e.toString())
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This setup ensures the async Python call doesn’t block the main thread, and all exceptions are gracefully handled.

Step 4: Call from Your Flutter UI
Now, hook it up to your Flutter UI. For example, in your Home widget:

class Home extends StatelessWidget {
  const Home({super.key});

  void helloWorld(BuildContext context) async {
    final result = await MyMethodChannelService.helloWorld();
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(result)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => helloWorld(context),
          child: const Text("Run Python Function"),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Check out the code on GitHub.

When the button is pressed, it calls your native Python function and displays the result in a snackbar.

That’s it! You now have a clean, production-ready bridge to execute Python code from Flutter, leveraging native Android with Chaquopy. Perfect for embedding AI, data science, or any Python-powered feature in your cross-platform app.

Demo run screenshot of the debug logs

Top comments (0)