Flutter — Communicate with Android activity or iOS ViewController through method channel

Chetan Bhalerao
4 min readAug 6, 2018

I am mobile developer and I faced a lot of problems while developing for Android and iOS applications, and sometime those problems are related to maintenance of two different source codes. One fine day I came to know about Flutter mobile SDK, initially I thought this is yet another SDK in bunch of SDK’s available in market, but then I decided to give a try on one of the precious weekend of mine :P

I found some amazing features of Flutter which makes me curious, what if I want to make some screens which are platform-specific or integrate existing screens from old code. Flutter provide amazing support for platform specific code.

Flutter’s platform-specific API support rely on a flexible message passing style between flutter code and native language code. It’s simple host and client mechanism to pass messages.

  • The Flutter portion of your app sends messages to its host over a platform channel to the iOS or Android portion of your app.
  • The host listens on the platform channel, and receives the message. It then calls into any number of platform-specific APIs — using the native programming language — and sends back a response to the client, the Flutter portion of your app.

Method channel api enables sending messages to client and receive messages from host. Messages and responses are passed asynchronously, to avoid any glitch in UI. On the platform side, MethodChannel on Android (API) and FlutterMethodChannel on iOS (API) enable receiving method calls and sending back a result. Lets try some code for more clarity.

Create flutter project with support of Kotlin.

Import this two files in main.dart file.

import 'dart:async';
import 'package:flutter/services.dart';

services.dart is required for MethodChannel class which is essential for sending message as discussed earlier and dart:async is required to execute code asynchronously. Now construct the method channel for communication.

static const platform = const MethodChannel("test_activity");

Here I named my channel as “test_activity”.

We need one async function to execute in flutter part, which will invoke method in Android or iOS native code.

_getNewActivity() async {
try {
await platform.invokeMethod('startNewActivity');
} on PlatformException catch (e) {
print(e.message);
}
}

We have to handle Platform exception if the platform does not support the platform API (such as when running in a simulator). So add invoking method in try catch. By mentioning ‘startNewActivity’ while invoking method, we can differentiate which method to call at Native code.

Now call _getNewActivity method on button click.

new MaterialButton(
child: const Text('Open Screen'),
elevation: 5.0,
height: 48.0,
minWidth: 250.0,
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
_getNewActivity();
})

Now open android part of code in another window like shown below.

Here we will create instance of MethodChannel with param as flutterView which is part of FlutterActivity and channel name. After creating method channel, we have to set method call handler where we will execute some action which we have to taken. In below code snippet I am opening new android activity.

class HomeActivity : FlutterActivity() {
private val CHANNEL = "test_activity"

override fun
onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, CHANNEL).setMethodCallHandler(
object : MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if(call.method.equals("startNewActivity")) {
startNewActivity()
}
}
})
}

private fun startNewActivity() {
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}

Now lets handle this in iOS. Open iOS part in Xcode like we open android part.

In AppDelegate create flutter channel just like android. In iOS flutter channel class name is different which is FlutterMethodChannel. For initializing we need channel name which used in flutter code ‘test_activity’ and binaryMessenger which is flutterViewController. To handle listener we need handler for method channel.

let flutterChannel = FlutterMethodChannel.init(name: "test_activity", binaryMessenger: flutterViewController);

Now set method call handler to handle iOS specific action.

flutterChannel.setMethodCallHandler { (flutterMethodCall, flutterResult) in
if flutterMethodCall.method == "startNewActivity" {
UIView.animate(withDuration: 0.5, animations: {
self.window?.rootViewController = nil

let viewToPush = SecondViewController()

let navigationController = UINavigationController(rootViewController: flutterViewController)

self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.makeKeyAndVisible()
self.window.rootViewController = navigationController
navigationController.isNavigationBarHidden = true
navigationController.pushViewController(viewToPush, animated: true)
})
}
}

If method name matches I am pushing new viewController. In method handler we can do a lot of things

In below gif you can see common flutter component and two different implementations for Android and iOS.

Here is github link for above code.

--

--

Chetan Bhalerao

Android developer, Backend developer. Interested in exploring new technologies. https://twitter.com/csbhalerao