一、创建插件项目
- 创建基础插件
bash
# 创建插件项目
flutter create --template=plugin --org=com.example my_flutter_plugin
# 进入项目
cd my_flutter_plugin
-
项目结构
my_flutter_plugin/
├── lib/
│ └── my_flutter_plugin.dart # Dart主文件
├── android/ # Android实现
├── ios/ # iOS实现
├── example/ # 示例项目
├── pubspec.yaml # 依赖配置
└── README.md # 说明文档
二、编写插件代码
- Dart接口文件 (lib/my_flutter_plugin.dart)
dart
import 'dart:async';
import 'package:flutter/services.dart';
class MyFlutterPlugin {
static const MethodChannel _channel =
MethodChannel('my_flutter_plugin');
/// 获取平台版本
static Future<String> getPlatformVersion() async {
final String version =
await _channel.invokeMethod('getPlatformVersion');
return version;
}
/// 自定义方法示例
static Future<bool> showToast(String message) async {
try {
await _channel.invokeMethod('showToast', {'msg': message});
return true;
} catch (e) {
print('Error: $e');
return false;
}
}
}
- Android实现 (android/src/main/kotlin/.../MyFlutterPlugin.kt)
kotlin
package com.example.my_flutter_plugin
import android.content.Context
import android.widget.Toast
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class MyFlutterPlugin: FlutterPlugin, MethodChannel.MethodCallHandler {
private lateinit var channel: MethodChannel
private lateinit var context: Context
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
context = flutterPluginBinding.applicationContext
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "my_flutter_plugin")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"getPlatformVersion" -> {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
}
"showToast" -> {
val msg = call.argument<String>("msg")
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
result.success(true)
}
else -> result.notImplemented()
}
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
- iOS实现 (ios/Classes/MyFlutterPlugin.m)
objective-c
#import "MyFlutterPlugin.h"
#import <UIKit/UIKit.h>
@implementation MyFlutterPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"my_flutter_plugin"
binaryMessenger:[registrar messenger]];
MyFlutterPlugin* instance = [[MyFlutterPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else if ([@"showToast" isEqualToString:call.method]) {
NSString *message = call.arguments[@"msg"];
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:nil
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIViewController *rootViewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
[rootViewController presentViewController:alert animated:YES completion:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[alert dismissViewControllerAnimated:YES completion:nil];
});
result(@YES);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
三、配置pubspec.yaml
yaml
name: my_flutter_plugin
description: 一个简单的Flutter插件示例,显示Toast和获取平台版本
version: 1.0.0
homepage: https://github.com/yourusername/my_flutter_plugin
repository: https://github.com/yourusername/my_flutter_plugin.git
environment:
sdk: ">=2.19.0 <4.0.0"
flutter: ">=3.7.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
plugin:
platforms:
android:
package: com.example.my_flutter_plugin
pluginClass: MyFlutterPlugin
ios:
pluginClass: MyFlutterPlugin
四、编写示例项目
- 修改 example/lib/main.dart
dart
import 'package:flutter/material.dart';
import 'package:my_flutter_plugin/my_flutter_plugin.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
@override
void initState() {
super.initState();
initPlatformState();
}
Future<void> initPlatformState() async {
String platformVersion;
try {
platformVersion = await MyFlutterPlugin.getPlatformVersion();
} catch (e) {
platformVersion = 'Failed to get platform version.';
}
setState(() {
_platformVersion = platformVersion;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin Example App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('平台版本: $_platformVersion\n'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
MyFlutterPlugin.showToast('Hello from Flutter!');
},
child: Text('显示Toast'),
),
],
),
),
),
);
}
}
- 运行测试
bash
cd example
flutter run
五、发布前检查
markdown
# My Flutter Plugin
一个简单的Flutter插件,用于显示Toast和获取平台版本。
## 功能
- 获取当前设备平台版本
- 显示原生Toast/Alert提示
## 安装
在 `pubspec.yaml` 中添加:
```yaml
dependencies:
my_flutter_plugin: ^1.0.0
使用示例
dart
import 'package:my_flutter_plugin/my_flutter_plugin.dart';
// 获取平台版本
String version = await MyFlutterPlugin.getPlatformVersion();
// 显示Toast
await MyFlutterPlugin.showToast('Hello World!');
### 2. 添加LICENSE文件
在项目根目录创建 `LICENSE` 文件(建议使用MIT许可证)
### 3. 代码格式检查
```bash
flutter analyze
dart format .
六、发布到pub.dev
- 注册pub.dev账号
· 访问 https://pub.dev
· 使用Google账号登录
· 获取API Token
- 本地登录
bash
# 在终端登录
dart pub login
- 预发布检查
bash
# 检查是否有错误
flutter pub publish --dry-run
- 正式发布
bash
# 发布插件
flutter pub publish
发布过程:
- 终端会显示验证信息
- 打开浏览器确认
- 等待上传完成
- 收到确认邮件
七、发布后操作
- 验证发布
访问:https://pub.dev/packages/my_flutter_plugin
- 更新版本
修改 pubspec.yaml 中的版本号:
yaml
version: 1.0.1 # 小版本更新
version: 1.1.0 # 功能更新
version: 2.0.0 # 大版本更新
重新发布:
bash
flutter pub publish
- 标记不推荐使用(如需弃用)
bash
dart pub deactivate my_flutter_plugin
八、常见问题解决
- 发布失败:403错误
· 检查是否已登录:dart pub login
· 确认包名是否已存在
· 检查网络连接
- 版本冲突
· 确保每次发布版本号递增
· 使用语义化版本控制:主版本.次版本.修订号
- 插件无法导入
· 发布后等待5-10分钟同步
· 清理Flutter缓存:flutter clean
- 平台特定错误
bash
# 重新生成iOS文件
cd example/ios
pod install
# 重新生成Android文件
flutter clean
flutter pub get
九、最佳实践
-
命名规范
· 包名:小写字母+下划线
· 方法名:清晰易懂的动词
· 版本号:遵循语义化版本 -
文档完善
· 提供完整的使用示例
· 添加API文档注释
· 说明平台限制 -
测试覆盖
bash# 运行测试 flutter test -
持续维护
· 及时回复issue
· 定期更新依赖
· 保持向后兼容
十、总结
发布Flutter插件只需简单几步:
- 创建插件项目
- 编写平台代码
- 配置pubspec.yaml
- 测试示例项目
- 发布到pub.dev
现在你已经成功发布了自己的Flutter插件!