flutter Call Android Native Code
flutter Call Android Native Code

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

Flutter platform specific architecture
Flutter platform specific architecture

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

open for editing in android studio android module
open for editing in android studio android module

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()
            }
        }
    }
}