A beginner's introduction to native communication (MethodChannel and EventChannel)
Flutter Beginners haven’t necessarily built native apps. That said the developers who started their development life with Flutter wonder how this cross platform thing works!
For the newcomers to the Flutter ecosystem, this post offers a conceptual exploration of Platform Channels. Grab your coffee and get ready for a story that will spark your imagination.

Part 1: The Code Newbie
Sam, fresh-faced and fueled by caffeine, stared at the blinking cursor on his screen. His fingers, itching to code, hovered above the keyboard, the weight of his first solo project pressing down on him. As a junior developer, he’d been tasked with building their flagship app – Aladin, an ERP app to lessen the hassle on their HR and Admin. Initially it will be released as an Android app, but later on there will be release for iOS. The team lead left the initial choice of framework on him.
He scrapped the internet, sifting through frameworks like a chef choosing spices and ended up choosing Flutter.

The magic of cross-platform development was showing its mana. It amazed Sam how the same code can run on both Android and iOS devices when they are totally different from each other. The app was going through its alpha release. But, as the honeymoon phase wore off, reality brought its first bitter bite.
So far his task was converting designs to code. Now they need to integrate third party login to access user’s information.
Part 2: Unlocking Efficiency (Case Study)
Their virtual workspace’s login system access token can only be accessed with a web browser. Thinking of solutions, Sam decided to launch a browser inside the app and read its view. Flutter doesn’t have that, but Sam knew that Android did. After Googling Sam finds out that he needs a plugin to launch an in-app browser and generate a token from that view. (Wait a minute… Did I just say plugin? I will get back to the part later).. He thought he was lucky, he found a plugin developed by someone he didn’t know which can create a webview inside his Flutter App. Ctrl + C and Ctrl + V were hit and he felt glad when the code compiled without any error. When he hit the run button, the plugin was showing that website properly. Happy tears were about to come out from his eyes but happiness didn’t last long. When he tried to access the data from the view he found out that the SDK was not providing enough support to read the content of that page the way Sam wanted. Sam was trying hard. The webView felt like a stubborn gatekeeper, blocking Sam from unleashing the browser’s full potential.

He threw himself into research, nights blurring into a haze of documentation and tutorials. Platform channels, it seemed, were the key. These mysterious bridges connecting Flutter to the native world, whispering secrets of sensors and APIs. It was a steep learning curve, but Sam relished the challenge.
But what was so special about Platform channel, how it was allowing him to do what he couldn’t do previously. What did Sam learn? We don’t know for sure, but we can try to learn with him now. This might be a bit lengthy, so I have kept a gift for you that I will give after you finish reading this post.
Part 3: Breaking the Dart’y Walls

It hurts more than a breakup when you flex with this meme and, as your experiences grow you find out that this meme is a lie. You are actually a native developer AND ALSO A FLUTTER DEVELOPER. The question is how your Flutter(dart) codes run in the native?

Currently our concern is Android and iOS. We have a plan of writing in detail about it, but to keep us on track I will only share an overview from Android’s perspective of what it is. Let’s see them in step:
Step 1: Your dart code along with the framework gets compiled into machine code that can run directly on your CPU (arm64, x86 etc.).
Step 2: The compiled Dart code, along with the necessary libraries, is packaged within a native APK. The apk acts as a container here.
Step 2.5: This is not a step but it took months for me to understand it properly. It’s worth describing. The Skia engine of Flutter doesn’t render the UI, it makes the Native code render UI for you.
Step 3: For features that require access to native Android APIs or services (e.g., camera, GPS, Bluetooth), Flutter provides platform channels. These channels act as bridges, allowing Dart code to communicate with native Java/Kotlin code and vice versa.
Step 4: Your app crashes as you haven’t properly debugged your codes. Just kidding! Dart VM handles input and output for you. This process is repeated again and again in your app.
Part 4: Junior Dev Lost in Translation
This basically means whenever I am drawing something on the screen like a button or a text input field, Skia (or, Impeller) is there to minimize my hassle. Skia handles most of the UI related stuff so smoothly that you need not to know about the process. Just like the collision detection on Unity. You write code for what happens if two objects collide with each other, but you need not to write code to calculate if they are colliding. You rarely think about the internal code for detecting a collision. Most probably you have never checked that code. Your game just runs fine even without bothering much about the internal code.

However, when the requirement is custom, like accessing a sensor to read its value can dart code access that? That’s a yes and a no.
Part 5: Visualizing is Believing (Explanation)
Think of a case where you need the weights to be shown in your Flutter app, if your BMI index is over 35, your Android phone’s flash light will blink like a SOS signal.
Assume Android has an API for reading the value from its pressure sensor (actually it has, but that’s air pressure). But Flutter is an UI framework, how would it know if your weight machine is connected to your Android device. Your Flutter app is trying to read that value.

So, it needs a medium, to be specific a channel to communicate with the platform (Android). Luckily Flutter has that channel created for you. Now read the image below.
Don’t just skip, I put effort into making it. 😒

Part 6: The Nutshell Version
Things sound a bit geeky? Let’s summarize:
Flutter whispers her UI requests – “Draw me a stunning button, Native!” – and he dutifully crafts pixel-perfect elements. Native confides his platform secrets – “Access my sensors, Flutter!” – and she gracefully integrates them into her app.
Still messy? As Flutter is a Dart’y girl she has no idea of the native code. So we write something in the Dart, open a channel and send an event to the native. Then we decide what we want to do when we receive that event on the native side. We write that code as well, we can send either a single result for that event (MethodChannel), or we can send multiple events when we need (EventChannel). This means thousands of plugins that we are seeing and using on a daily basis are actually written by someone. Quite interesting, right?
Part 7: Under the Hood, We see Code (Enough theory, we will see code now 🤩)
Now let’s visualize our understanding in code. Here we are creating a class with a static method which will help us to turn on hotspots on our device. Flutter doesn’t support this feature. We created a channel and in that channel we asked to trigger a method, the method’s name is turnOnHotspot.

In the native side we have created a class extending MethodCallHandler. We are registering a binary channel with the same channel name. Whenever a method call is received on this channel we are checking if the name of the method is exactly what we are looking for. If matches we do some job on the native side and then send the result.

In this way we can do almost everything with Flutter that we could do with the native code. This is how Flutter open’s possibilities for us. Also, this is the reason why a Flutter developer should know native also.
You can now go through the Flutter Platform Channel documentations for a detailed view and write your first plugin.
That’s all for today. Here’s your candy for reading the whole post with patience.
🍬🍬🍬