Method channel is a named channel for communicating with the Flutter application using asynchronous method calls.
You may also check our Flutter app development page.
Method calls are encoded into binary before being sent, and binary results received are decoded into Dart values.
Why do we require Method Channel?
- One of the biggest challenges for mobile cross-platform frameworks is how to achieve native performance
- how to help developers create different kinds of features for different devices and platforms with as little effort as possible.
- In doing so, we need to keep in mind that UX should remain the same but with unique components that are specific for each particular platform (Android and iOS).
As a result, we are in a need of communication between our flutter application with native code.
The question is, how can those frameworks establish communication between the specific platform and application? The best example is Flutter’s Platform Channel.
How does it work?
Method Channel is based on the idea of sending and receiving messages without having to generate any code. The communication is asynchronous and bidirectional. In this communication, the Flutter program (the Dart-based element of the app) represents a client that sends messages to the host (Android or iOS) and waits for a response, either as a success or failure.
When the message is received on the host’s side, we can execute the necessary logic in native code (Java/Kotlin for Android or Objective-C/Swift for iOS) or call any platform-specific APIs and send a response back to the Flutter application through the channel. When channels are created, we need to be mindful of naming conventions. The name of the channel in the Flutter application needs to be the same as the one on the native side.
All MethodChannels provided by the Flutter framework guarantee FIFO ordering.
Let’s start the implementation
In this blog, we are going to learn about the basic implementation of the Method channel.
Step-1: First setup in dart side
1 2 |
static const methodChannelName = "com.demo.methodchannel"; //-----Name your channel-----// |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import 'package:flutter/services.dart'; //=========Handle Deep Linking=========// var methodChannel = const MethodChannel(AppConstant.methodChannelName); Future<String> callNativeCode() async { try { var data = await methodChannel.invokeMethod('messageFunction'); return data; } on PlatformException catch (e) { return "Failed to Invoke: '${e.message}'."; } } |
Step-2: Setup in android
In your MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.webkul.flutter_project_structure import android.app.Activity import android.app.role.RoleManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Build import androidx.annotation.NonNull import androidx.annotation.RequiresApi import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import webkul.opencart.mobikul.mlkit.CameraSearchActivity class MainActivity : FlutterFragmentActivity() { private val EVENTS = "com.demo.methodchannel" var methodChannelResult: MethodChannel.Result? = null override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel( flutterEngine.dartExecutor.binaryMessenger, EVENTS ).setMethodCallHandler { call, result -> methodChannelResult = result; if (call.method == "messageFunction") { result.success("Message From Android") } } } } |
Step-3: Setup in iOS
In your AppDelegate.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let mlkitChannel = FlutterMethodChannel(name: "com.demo.methodchannel", binaryMessenger: controller.binaryMessenger) mlkitChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in if call.method == "messageFunction"{ result("Message From Ios") } }) } } |
Step-4: use this function in your dart file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import 'package:flutter/material.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: const MyHomePage(title: 'Method Channel Demo'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { callNativeCode(); return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Demo Application for method channel', ), ], ), ), ); } } |
As a result, you will receive messages according to the Host (Android, IOS).
From Ios ==> “Message From Ios”
From Android ==> “Message From Android”