How to Integrate Event Channel in Flutter: A Step-by-Step Guide With Git Example Code

Flutter’s cross-platform nature is remarkable, but there are times when you need real-time updates from native layers, like sensor data or system events. This is where event channels shine! Unlike method channels, event channels enable continuous data streaming between Flutter and native platforms.

In this guide, I’ll show you how to integrate event channels into your Flutter project to handle real-time data streaming. Let’s get started!


What Are Event Channels?

Event channels are a mechanism in Flutter that allows streaming of data from native code to Dart. This is ideal for scenarios where you need continuous updates, like listening to device sensors or tracking location changes.

The process involves three main components:

  1. Dart Side: Receiving streams using EventChannel.
  2. Native Side (Android/iOS): Sending data streams to Dart.
  3. Channel Name: A string that uniquely identifies the communication channel.

Step 1: Create a New Flutter Project

If you don’t already have a Flutter project, create one:

flutter create --org com.kotlincodes event_channel_demo

Open the project in your favorite IDE (e.g., VS Code).


Step 2: Define the Event Channel in Dart

In your Dart code, define an EventChannel and specify a channel name. This channel name will be used to communicate with the native side.

Open lib/main.dart and add the following code:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: EventChannelDemo(),
    );
  }
}

class EventChannelDemo extends StatefulWidget {
  @override
  _EventChannelDemoState createState() => _EventChannelDemoState();
}

class _EventChannelDemoState extends State<EventChannelDemo> {
  static const eventChannel = EventChannel('com.kotlincodes.event_channel_demo/stream');

  String _eventData = 'Waiting for data...';

  @override
  void initState() {
    super.initState();
    eventChannel.receiveBroadcastStream().listen((dynamic event) {
      setState(() {
        _eventData = event.toString();
      });
    }, onError: (dynamic error) {
      setState(() {
        _eventData = 'Error: ${error.message}';
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Event Channel Demo'),
      ),
      body: Center(
        child: Text(_eventData),
      ),
    );
  }
}

Step 3: Add Native Code for Android

Navigate to android/app/src/main/java/com/kotlincodes/event_channel_demo/MainActivity.kt. Update it to handle the event channel:

package com.kotlincodes.event_channel_demo

import android.os.Handler
import android.os.Looper
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.kotlincodes.event_channel_demo/stream"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setStreamHandler(object : EventChannel.StreamHandler {
            private var handler: Handler? = null
            private var runnable: Runnable? = null

            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                handler = Handler(Looper.getMainLooper())
                runnable = object : Runnable {
                    private var counter = 0
                    override fun run() {
                        events?.success("Event: ${++counter}")
                        handler?.postDelayed(this, 1000) // Send data every second
                    }
                }
                handler?.post(runnable!!)
            }

            override fun onCancel(arguments: Any?) {
                handler?.removeCallbacks(runnable!!)
            }
        })
    }
}
 

Step 4: Add Native Code for iOS

For iOS, navigate to ios/Runner/AppDelegate.swift and modify it:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        let eventChannel = FlutterEventChannel(name: "com.kotlincodes.event_channel_demo/stream",
                                               binaryMessenger: controller.binaryMessenger)

        eventChannel.setStreamHandler(EventStreamHandler())

        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

class EventStreamHandler: NSObject, FlutterStreamHandler {
    private var timer: Timer?
    private var counter = 0

    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
            self.counter += 1
            events("Event: (self.counter)")
        }
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        timer?.invalidate()
        timer = nil
        return nil
    }
}

Step 5: Run the App

  • Ensure you have an Android emulator or iOS simulator running, or connect a physical device.
  • Run the app using: flutter run
  • You should see real-time updates displayed on the screen as the event channel streams data.

Source Code

The complete source code for this tutorial can be found on GitHub. Feel free to explore and build upon it to suit your app’s needs.


Conclusion

Event channels in Flutter enable you to stream real-time data from native layers into your app. Whether it’s sensor updates or system events, this integration opens up new possibilities for your app’s functionality. Start exploring event channels and bring dynamic updates to your Flutter projects! 🚀