Flutter allows you to write cross-platform mobile apps using Dart, but sometimes you need to access native Android features—like camera, Bluetooth, or platform-specific APIs—that Flutter doesn’t support out of the box.
This is where Flutter plugins come in. A plugin is a Dart package that uses platform-specific code (like Java/Kotlin on Android) through platform channels to bridge communication between Flutter and native code.
In this guide, you’ll learn:
- How to create a Flutter plugin
- Write Android-specific logic in Java/Kotlin
- Use MethodChannel for communication
- Use the plugin in a Flutter app
🧰 Step 1: Create the Plugin Project
Run this command in terminal:
flutter create --template=plugin --platforms=android flutter_custom_plugin
Explanation:
This creates a new Flutter plugin project named flutter_custom_plugin
. The plugin will include platform code for Android. You’ll see:
/lib/flutter_custom_plugin.dart
– Dart interface/android/src/main/java/...
– Native Android code
📦 Step 2: Understand Project Structure
flutter_custom_plugin/lib/flutter_custom_plugin.dart
: Contains plugin API exposed to Flutter apps.flutter_custom_plugin/android/src/main/java/com/example/flutter_custom_plugin/FlutterCustomPlugin.java
: Native Android implementation using Java (or Kotlin).pubspec.yaml
: Plugin metadata and supported platforms.
You can switch to Kotlin by adding --android-language kotlin
to your create command.
📡 Step 3: Define MethodChannel in Dart
lib/flutter_custom_plugin.dart
import 'package:flutter/services.dart';
class FlutterCustomPlugin {
static const MethodChannel _channel = MethodChannel('flutter_custom_plugin');
static Future<String?> getPlatformVersion() async {
final String? version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
}
Explanation:
We define a static MethodChannel
named 'flutter_custom_plugin'
. The invokeMethod()
call sends a message to the platform side and waits for a response. Here we’re requesting getPlatformVersion
from the Android side.
📱 Step 4: Implement Android Platform Code
android/src/main/java/com/example/flutter_custom_plugin/FlutterCustomPlugin.java
package com.example.flutter_custom_plugin;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class FlutterCustomPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler {
private MethodChannel channel;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_custom_plugin");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
Explanation:
This Java class implements FlutterPlugin and MethodCallHandler. When getPlatformVersion
is invoked from Dart, it returns the current Android OS version. If the method isn’t recognized, notImplemented()
is called.
🧪 Step 5: Use the Plugin in a Flutter App
- Add the plugin to your
pubspec.yaml
:
dependencies:
flutter_custom_plugin:
path: ../flutter_custom_plugin
- Call it in your main app:
import 'package:flutter/material.dart';
import 'package:flutter_custom_plugin/flutter_custom_plugin.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: PluginHome(),
);
}
}
class PluginHome extends StatefulWidget {
@override
_PluginHomeState createState() => _PluginHomeState();
}
class _PluginHomeState extends State<PluginHome> {
String _platformVersion = 'Unknown';
@override
void initState() {
super.initState();
getPlatformVersion();
}
Future<void> getPlatformVersion() async {
final version = await FlutterCustomPlugin.getPlatformVersion();
setState(() {
_platformVersion = version ?? 'Failed to get version';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Flutter Plugin Example")),
body: Center(child: Text('Running on: $_platformVersion')),
);
}
}
Explanation:
We call our plugin’s getPlatformVersion()
function inside initState()
and display the Android OS version using a Text
widget.
🔄 Testing the Plugin
- Run the example app using
flutter run
. - You should see the OS version returned from native Android code.
- If using Kotlin, ensure your plugin class uses
override fun
in a similar structure.
🧠 Final Thoughts
Creating a custom Flutter plugin with Android support allows you to:
- Extend Flutter apps with native functionality
- Interact with Java/Kotlin APIs
- Reuse platform-specific libraries in Dart apps
Key Concepts Recap:
- Use
MethodChannel
to bridge Dart and native Android - Plugins let Flutter call Java/Kotlin functions
- Platform plugins follow the structure defined by
FlutterPlugin
Have you tried writing your own Flutter plugin yet?
Drop your ideas, doubts, or sample use cases in the comments—we’d love to help or feature your plugin!