Bridging Between Dart and Native Code with Flutter Channel for Communicate Each Other

Farhan Yuda Pahlevi
4 min readJun 22, 2019

After several time code with flutter, I learn how to communicate between Flutter and Native code. It’s something like you make a bridge from your Flutter code and then it will connect to the other side in Native code. The fact is Flutter allow us to communicate from Dart code to Kotlin/Java in Android and Objective C/Swift in iOS, this is not new but for me it’s something new. So I want to share how I do in sample code.

Getting Started

At the beginning, I assume you already own your Flutter SDK, Android SDK, XCode (with iOS SDK absolutely), and integrate it with your IDE. So I start with creating new project like usual, here I use Android Studio as my IDE because Android Studio is my daily weapon as Native Android Engineer, you can use your IDE here. Create your first project, if you don’t know how to do it, please search in google like How to create Flutter project . After that Flutter will generate new code, see the code in lib folder and you can found main.dart as the only one files.

First Code
Here you can add code below as bridge to the native code:

class MyHomePage extends StatelessWidget {
static const platform = const MethodChannel(CHANNEL);
final String title;

MyHomePage({Key key, this.title}) : super(key: key) {
platform.setMethodCallHandler(_handleMethod);
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new RaisedButton(
child: new Text('Move to Native World!'),
onPressed: _showNativeView,
),
],
),
),
);
}

Future<Null> _showNativeView() async {
await platform.invokeMethod(KEY_NATIVE);
}

Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case "message":
debugPrint(call.arguments);
return new Future.value("");
}
}
}

This is class that will show as our Main Page, there is one button if you click it will trigger the _showNativeView() method. This method will use platform variable, which is the Bridge that use MethodChannel . MethodChannel can be call in Native code so if you invoke it with some key it will trigger in Native code based on your key, easy right? But this is only the simple case. For illustration you can see below:

It’s Magic?

No magic used here but Flutter provide Platform Channel , Platform Channel is a way for Flutter to communicate between it host (Native Android or Native iOS) to the consumer side (Flutter itself). I think this is very useful if we want to trigger some native feature in each platform (Android or iOS) that not provided by Flutter. Like I said before, it something like you make a bridge from Flutter side to Native side. Platform Channel only use key so it only work if the key same and that’s make it very simple. Just need declare the Method Channel in your Flutter code like this :

const CHANNEL = "id.pahlevikun.native_communication.channel";
static const platform = const MethodChannel(CHANNEL);

And then put MethodChannel too in your native code, for example in Android side :

companion object {
const val CHANNEL = "id.pahlevikun.native_communication.channel"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)

MethodChannel(
flutterView,
CHANNEL
).setMethodCallHandler { call, result ->
// Handle here
}
}

Easy right? But this code not trigger anything because you not pass any key and not do something with the key. So, how to pass an event to the native code? First, you need a Future method like this:

Future<Null> _showNativeView() async {
await platform.invokeMethod(KEY_NATIVE);
}

This method will call if you press button that already created in MyHomePage class. What you need is put that method as action for RaisedButton like this :

new RaisedButton(
child: new Text('Move to Native World!'),
onPressed: _showNativeView,
)

Ok, until this you finish in the Flutter side, then you need to set an action in Native side. For example I already create new Activity in Android Native code. So I want intent to that activity if you press button in Flutter side. Remember the code that you put in Native side previously? Yes, you can put your action inside the MethodCallHandler like this

MethodChannel(
flutterView,
CHANNEL
).setMethodCallHandler { call, result ->
if (call.method == KEY_NATIVE) {
val intent = Intent(this, NativeAndroidActivity::class.java)
startActivity(intent)
result.success(true)
} else {
result.notImplemented()
}
}

The result parameter act as callback to the Flutter side and then inside control flow you can add action based on key.

Conclusion

Flutter have many feature that makes you happy code in one repository for supporting two mobile platform. It’s very easy to communication between Flutter and Native code in a seamless way through Flutter Platform (Also known as Platform-Channel). You can define your own channels, your own key, also your own method so it can pass from consumer side (Flutter) into host side (Native — Android/iOS). You can see my code here. Thanks for reading, don’t forget to share this article and feel free to ask or share more information about Flutter here in comments.

--

--

Farhan Yuda Pahlevi

Software Engineer | Senior Mobile Engineer at Gojek — Flutter - Android - iOS - KMM | Google Associate Android Developer 2017–2020 | http://pahlevikun.id