Build a Flutter plugin that provides native interop for other Flutter apps to use
Scaffolds and configures Flutter plugin packages, handling standard method channels, FFI integrations, and federated plugin architectures. It configures platform-specific native code environments, implements Android v2 embedding lifecycle interfaces, and establishes platform interface packages.
Use the following decision tree to determine the plugin architecture and template:
dart:ffi?
--template=plugin_ffi.
dart:ffi and Method Channels?
--template=plugin (Non-FFI). You must configure FFI manually within the standard plugin structure.Gather Plugin Requirements STOP AND ASK THE USER:
com.example)?android,ios,web,linux,macos,windows)?Generate the Plugin Package Execute the Flutter CLI command based on the user's parameters.
Standard Plugin Example:
flutter create --org com.example --template=plugin --platforms=android,ios,macos -a kotlin -i swift my_plugin
FFI Plugin Example:
flutter create --template=plugin_ffi my_ffi_plugin
Configure Federated Plugin Architecture (If Applicable)
If the user requested a federated plugin, configure the pubspec.yaml of the app-facing package to endorse the platform implementations.
# App-facing pubspec.yaml
flutter:
plugin:
platforms:
android:
default_package: my_plugin_android
windows:
default_package: my_plugin_windows
dependencies:
my_plugin_android: ^1.0.0
my_plugin_windows: ^1.0.0
For the platform implementation packages, define the implements key:
# Platform implementation pubspec.yaml (e.g., my_plugin_windows)
flutter:
plugin:
implements: my_plugin
platforms:
windows:
pluginClass: MyPlugin
Prepare Native Environments for Editing Before modifying native code, you MUST build the example app to resolve dependencies and generate necessary files.
cd my_plugin/example
flutter build apk --config-only # For Android
flutter build ios --no-codesign --config-only # For iOS
flutter build windows # For Windows
Implement Android v2 Embedding Lifecycle
Modify the Android plugin class (e.g., android/src/main/kotlin/com/example/my_plugin/MyPlugin.kt). Extract logic from registerWith() into a private method shared with onAttachedToEngine(). Implement ActivityAware or ServiceAware if context is needed.
package com.example.my_plugin
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
class MyPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
setupChannel(flutterPluginBinding.binaryMessenger)
}
// Shared private method for v1 and v2 embedding compatibility
private fun setupChannel(messenger: BinaryMessenger) {
channel = MethodChannel(messenger, "my_plugin")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
// Handle Activity attachment
}
override fun onDetachedFromActivityForConfigChanges() {}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {}
override fun onDetachedFromActivity() {}
}
Validate and Fix Run the plugin tests and analyzer to ensure the generated code is valid.
cd my_plugin
flutter analyze
flutter test
If the analyzer reports missing dependencies or unresolved native symbols, verify that step 4 (building the example app) was executed successfully. Fix any missing imports in the native code blocks.
--template=plugin_ffi. If both are required, use --template=plugin.flutter build <platform>) at least once before attempting to edit or analyze native Android (build.gradle), iOS (.xcworkspace), or Windows (.sln) files.lib/<package_name>.dart).FlutterPlugin). Do not rely solely on the deprecated PluginRegistry.Registrar..android or .ios directories inside a Flutter module; only edit the native code inside the plugin's android/ or ios/ directories.