Hi Guys, Welcome to Proto Coders Point, In this Flutter tutorial we will learn how to call Android Native code from Flutter.
Flutter provide a framework that helps us to access platform specific feature, By doing this developer can extend the functionality of flutter framework using android specific code.
You can easily access platform specific code functionality like camera, battery Level, MAC address etc through flutter framework.
Platform specific Architecture flutter framework
How flutter communicate to Native Platform code
The Flutter client, sends message to Host(Native Code i.e. Android/iOS code).
The Host native code listen to Message / Method Channel, receive the message & does the necessary functionality as defined & return the result back to client through method channel
Flutter Call Native Android Code – Easily Example
Let’s create a flutter app that calls Android Specific code and print the message on console & show a Toast message to user from Native code.
Flutter Side Code main.dart
1. Create a new Flutter Project
2. Import services dart classes
import 'package:flutter/services.dart';
3. Create a method channel
static const channel = MethodChannel('yourpackageName/channelName');
Here MethodChannel name should be unique so it better to use your app package name with channelName because it happens unique.
4. A button, that calls a function that invoke native code
Write a Function/Method(), _showToast() that calls and invoke platform method through method channel.
So In below Snippet method, we have used channel.invokeMethod to invoke Native Code
Future<void> _showToast() async{ final int callToast = await channel.invokeMethod('showToast',<String,String>{ 'message':'This is a Toast from From Flutter to Android Native Code Yes, It is working' }); print(callToast); }
Here showToast key we need to use in android code to detect which method to invoke on android side, and we are also passing message in map form.
Android Module MainActivity.kt
To write android native codde, you need to open flutter – android module in new Window, to do that follow below step as shown in screenshot
flutter project > android > app > src > main > kotlin > MainActivity.kt
1. Initialize variable
private val CHANNEL = "yourpackageName/channelName";
private lateinit var channel: MethodChannel
2. override configureFlutterEngine
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) channel.setMethodCallHandler { call, result -> var argument = call.arguments() as Map<String, String>; var message = argument["message"]; if (call.method == "showToast") { Log.d("TAG", "message"); Toast.makeText(this, message, Toast.LENGTH_LONG).show() } } }
Here, when flutter send a event through methodChannel, host(android code) will listen to the event, channel it was, and setMethodCallHandler process the data and perform the functionality as defined & return the result back to flutter through method channel.
Flutter Call Native Android Code – Complete Source Code
Flutter – main.dart
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { //channel name, used in android code to invoke method static const Channel = MethodChannel('yourpackageName/channelName'); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Call Native Code to show Toast Message"), ElevatedButton(onPressed: (){ _showToast(); },child: Text("Show Toast"),), ], ), ), ); } //a method that invoke native code Future<void> _showToast() async{ final int batteryLevel = await Channel.invokeMethod('showToast',<String,String>{ 'message':'This is a Toast from From Flutter to Android Native Code Yes, It is working' }); print(batteryLevel); } }
Android – MainActivity.kt
package com.example.native import android.util.Log import android.widget.Toast import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import java.lang.reflect.Method class MainActivity: FlutterActivity() { private val CHANNEL = "yourpackageName/channelName"; private lateinit var channel: MethodChannel override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) channel.setMethodCallHandler { call, result -> var argument = call.arguments() as Map<String, String>; var message = argument["message"]; if (call.method == "showToast") { Log.d("TAG", "message"); Toast.makeText(this, message, Toast.LENGTH_LONG).show() } } } }