How to Create a Flutter Plugin

Tutorial 4 of 5

1. Introduction

This tutorial aims to guide you through the process of creating your very own Flutter plugin, which can be shared and used by other developers in the Flutter community.

By the end of this tutorial, you'll learn:

  • How to set up a Flutter plugin project
  • How to write Dart code for the plugin
  • How to write platform-specific code for Android and iOS

Prerequisites:

  • Basic knowledge of Dart programming language
  • Basic knowledge of Android (Java/Kotlin) and iOS (Objective-C/Swift) development
  • Flutter SDK installed on your machine
  • Android Studio or VS Code installed

2. Step-by-Step Guide

2.1 Setup a Flutter Plugin Project

To create a new Flutter Plugin, you can use the flutter create --template=plugin command. This will set up a new Flutter project with a special directory structure.

$ flutter create --template=plugin hello

This will create a directory called "hello" with all the basic files you need for a plugin.

2.2 Write Dart Code for the Plugin

Go to lib/hello.dart. This is where you will write your plugin's Dart code.

import 'dart:async';

import 'package:flutter/services.dart';

class Hello {
  static const MethodChannel _channel = const MethodChannel('hello');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

Here, we define a Hello class with a static method platformVersion. This method communicates with the platform-specific code using a MethodChannel.

2.3 Write Platform-Specific Code

Let's write the Android version of the plugin.

2.3.1 Android

Go to android/src/main/java/com/example/hello/HelloPlugin.java.

package com.example.hello;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

public class HelloPlugin implements FlutterPlugin, MethodCallHandler {
  private MethodChannel channel;

  @Override
  public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "hello");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }
}

This Java code handles the getPlatformVersion method call and returns the Android version.

3. Code Examples

Here are some practical examples:

// Call the getPlatformVersion method from your Flutter code
void getPlatformVersion() async {
  String version = await Hello.platformVersion;
  print(version);
}

This Dart code calls the platformVersion method and prints the platform version.

4. Summary

In this tutorial, we've learned how to set up a Flutter plugin project, write Dart code for the plugin, and write platform-specific code for Android.

Next, you could learn how to write the iOS code for the plugin, and how to publish the plugin to the Flutter Package Manager.

Additional resources:

5. Practice Exercises

  1. Add a new method to the plugin that returns the device model.
  2. Write the Android and iOS code for the new method.
  3. Call the new method from your Flutter code.

Solutions:

  1. Add a new method to the Dart code:
static Future<String> get deviceModel async {
  final String model = await _channel.invokeMethod('getDeviceModel');
  return model;
}
  1. Write the Android and iOS code:
if (call.method.equals("getDeviceModel")) {
  result.success(android.os.Build.MODEL);
}
  1. Call the new method from your Flutter code:
void getDeviceModel() async {
  String model = await Hello.deviceModel;
  print(model);
}