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:

Bring Python to Your Android App Using Chaquopy | by Sumeet Sharma | Jul, 2025 | Medium
Sumeet Sharma ・ ・
Medium
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")
}
}
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}';
}
}
}
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())
}
}
}
}
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"),
),
),
);
}
}
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.
Top comments (0)