创建插件项目
# 命令解读
# -i 指的是iOS平台选择什么语言 后接语言类型 objc/swift
# -a 指的是Android平台 后接语言类型 java/kotlin
flutter create --template=plugin -i objc -a java MyPlugin
cd MyPlugin/example
flutter run #试试项目能否跑🏃起来
等待命令执行完即可
目录结构大致如下:
.
├── CHANGELOG.md
├── LICENSE
├── MyPlugin.iml
├── README.md
├── android #安卓平台代码
├── example #demo例子🌰
├── ios #iOS平台代码
├── lib #插件通信代码
├── pubspec.lock
├── pubspec.yaml
└── test
开始编写插件代码
首先打开项目找到MyPlugin.dart
文件
import 'dart:async';
import 'package:flutter/services.dart';
class MyPlugin {
static const MethodChannel _channel = const MethodChannel('MyPlugin');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
//新增一个方法 用于发送字典即Map参数给iOS平台 返回值是泛型类型用于接收iOS发送过来的消息内容
static Future<dynamic> dartSendMessageToIOS(Map<String, dynamic> args) {
return _channel.invokeMethod("dartSendMessageToIOS", args);
}
}
其次找到example/main.dart
用于开发调试插件代码
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:MyPlugin/MyPlugin.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();
initDartSendMessage();
}
Future<void> initDartSendMessage() async {
String platformVersion;
dynamic args; //定义接收对应平台的返回值 (这里指iOS平台,Android端暂未实现)
try {
platformVersion = "";
args = await MyPlugin.dartSendMessageToIOS({
"floatNumber": 0.02,
"number": 666,
"str": "字符串",
"arr": ["item1", "item2", "item3"],
"dict": {"key": "value"}
});
print("iOS获取过来的数据如下:\n $args");
} on PlatformException {
platformVersion = "获取到版本号失败!!!";
}
if (!mounted) {
return;
}
setState(() {
_platformVersion = platformVersion;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await MyPlugin.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Text('Running on: $_platformVersion\n'),
),
),
);
}
}
关于通道(channel)的数据类型交互可参考flutter中文网的介绍
最后就是使用Xcode打开example/ios/Runner.xcodeproj
编辑本地库里的插件文件MyPlugin.m
#import "MyPlugin.h"
@implementation MyPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"MyPlugin"
binaryMessenger:[registrar messenger]];
MyPlugin* instance = [[MyPlugin 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 ([@"dartSendMessageToIOS" isEqualToString:call.method]){
//dart 发送一些参数给iOS,收到消息之后做一些事情
//dart传的参数字典也就是Map
NSDictionary *args = call.arguments;
NSLog(@"dart发送过来的数据:");
NSLog(@"floatNumber: %@",args[@"floatNumber"]);
NSLog(@"str: %@",args[@"str"]);
NSLog(@"arr: %@",args[@"arr"]);
NSLog(@"dict: %@",args[@"dict"]);
NSLog(@"dict[key]: %@",args[@"dict"][@"key"]);
//给flutter channel发送一些参数过去 dart收到会打印显示的
result(@{
@"float" : @(0.0666),
@"int" : @(1111),
@"strings" : @"哈哈哈哈,我是字符串了",
@"array" : @[@"iOS",@"Swift",@"Flutter"],
@"dict" : @{@"iOS":@"666"}
});
}else {
result(FlutterMethodNotImplemented);
}
}
@end
最后,运行代码查看效果
cd example
flutter run
附上一张控制台打印的效果图