开场白:
- 目前截止
flutter github start
数已经94.4K
了,潜在的说明了这事以后App
开发趋势。 - 作为新起之秀,后劲足但是社区生态不够完善。还有许多的功能还没有相应的插件。
- 很荣幸能为
flutter
社区做贡献, 插件地址flutter_3des_plugin
, github地址
步骤
1. 创建一个插件包
注:flutter
插件项目默认针对iOS
代码使用Objective-C
,Android
代码使用Java
。 除非你手动更改过(我的就是)
flutter create --org com.example --template=plugin hello
// 改变原生语言
flutter create --template=plugin -i swift -a kotlin hello
// 或者
flutter create --template=plugin -i objc -a java hello
2. 部分结构
1) 插件包的Dart API
lib/hello.dart
2) 插件包API
的Android
实现
android/src/main/java/com/yourcompany/hello/HelloPlugin.java
3) 插件包API
的ios
实现
ios/Classes/HelloPlugin.m
4) 一个依赖于该插件的Flutter
应用程序,来说明如何使用它
example/
3. 实现package包, 编写业务代码 运行flutter build apk
使用Android Studio
或者 Vscode
编辑Android
代码, 编写代码之前,首先确保代码至少已经构建过一次(例如,cd
到 hello/example
; 在 flutter build apk
)
1. 暴露出去的方法:目录为 根目录下的lib/hello.dart
class Flutter3desPlugin {
static const MethodChannel _channel =
const MethodChannel('hello');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
// 加密方法
static Future<String> encrypt(String key, String data) async{
return await _channel.invokeMethod('encrypt' , <String,dynamic>{'data':data,'key':key});
}
}
2. Android
改动的目录为 android/src/main/java/com/yourcompany/hello/HelloPlugin.java
里面的 onMethodCall
方法,如下,标红的部分是需要添加的
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
// 把 if 优雅的改成 switch 并添加 encrypt 条件, 这将对应你所暴露出去的方法名
switch (call.method) {
case "getPlatformVersion":
result.success("Android " + android.os.Build.VERSION.RELEASE);
break;
case "encrypt": // 方法映射
String body = call.argument("data");
String keys = call.argument("key");
String key = keys + keys.substring(0,16);
byte [] text = encrypt(hexStr2Bytes(key),hexStr2Bytes(body));
result.success(bytes2HexStr(text));
break;
default:
result.notImplemented();
break;
}
}
private static final String algorithm = "DESede";
// 方法的实现
public static byte[] encrypt(byte[] key, byte[] body) {
try {
SecretKey deskey = new SecretKeySpec(key, algorithm);
Cipher c1 = Cipher.getInstance(algorithm);
c1.init(Cipher.ENCRYPT_MODE, deskey);
return c1.doFinal(body);
} catch (java.security.NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException e2) {
e2.printStackTrace();
} catch (java.lang.Exception e3) {
e3.printStackTrace();
}
return null;
}
........... (此处省略其他方法的实现)
3. ios
改动目录为 iosClasseshello.m
里的 handleMethodCall
方法, 添加 encrypt
方法映射, 和java
部分类似; 标红的部分是需要添加的
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_3des_plugin"
binaryMessenger:[registrar messenger]];
Flutter3desPlugin* instance = [[Flutter3desPlugin 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([@"encrypt" isEqualToString:call.method]) { // 方法名映射, 注意和你所暴露出去的方法名一致
NSDictionary* argsMap=call.arguments;
NSString * data=argsMap[@"data"];
NSString * key=argsMap[@"key"];
NSString *batteryLevel = [self encrypt:data key:key];
if (batteryLevel) {
result(batteryLevel);
} else
{
result([FlutterError errorWithCode:@"UNAVAILABLE"
message:@"Battery info unavailable"
details:nil]);
}
} else {
result(FlutterMethodNotImplemented);
}
}
// 业务代码的实现
- (NSString *)encrypt:(NSString *)data key:(NSString *)key {
JKEncrypt * en = [[JKEncrypt alloc]init];
//加密
NSString * encryptStr = [en encrypt3DesData:data key:key];
return encryptStr;
}
@end
4. 再然后就是运行测试你的代码: 注 不用你区分是android
环境还是ios
环境, 框架会自动区分, 你只需要编写原生代码就行, 目录 examplelibmain.dart
import 'package:flutter_3des_plugin/flutter_3des_plugin.dart';
@override
void initState() {
super.initState();
encrypt();
}
// 3des 加密
encrypt () {
Flutter3desPlugin.encrypt(_key, _data).then((res) {
// TODO: res就是加密后的数据
setState(() {
_result = res;
});
});
}
4. 发布package
包,至 pub.dev
- 在发布之前,检查
pubspec.yaml、README.md
以及CHANGELOG.md
文件,以确保其内容的完整性和正确性 - 并在根目录下的
pubspec.yaml
文件顶部加上version, author, homepage
等字段, 执行下面命- 令后会有提示;成功的提示:执行完第二个命令并且授权谷歌登录后显示:Successfully uploaded package
.
flutter packages pub publish --dry-run --server=https://pub.dartlang.org;
flutter packages pub publish; 或者 flutter packages pub publish;
5. 若第四步行云流水没问题就不用往下看了。 接下来说发布的坑(坑的我身心疲惫)现在总结下终极方法;
- 先来看错误有哪些:
// 错误1, 一直卡着, 绝望.....
Waiting for your authorization...
Authorization received, processing...
It looks like accounts.google.com is having some trouble.
Pub will wait for a while before trying to connect again.
OS Error: Operation timed out, errno = 60, address = accounts.google.com, port = 53481
pub finished with exit code 69
// 错误2, 一直卡着
Package has 2 warnings. Upload anyway (y/n)? y
Uploading...
- 解决; 先不管报哪类错, 跟着下面步骤执行命令就对了
- 第一步 用命令行
(git,cmd)
打开你的项目根目录下,运行下面命令, 目的:解除国内镜像: 因为是发包到国外
(注: 以下命令只在当前终端端口有效, 你在别的窗口运行就都重置了)
unset FLUTTER_STORAGE_BASE_URL
- 第二步 设置本地代理
// windows端口号默认是1080. 除非你改过, mac的话1081
set http_proxy=http://127.0.0.1:1080
set https_proxy=http://127.0.0.1:1080
// 上面的没代理成功就换成下面的
export http_proxy=http://127.0.0.1:1080
export https_proxy=http://127.0.0.1:1080
- 第三部 设置终端代理, 这时你需要一个国外服务器........ (这很尴尬, 便宜的100一年吧);然后下载小飞机(
Shadowsock.exe)
。添加你的服务器, 系统代理模式选为 全局模式
测试你的终端代理设置成功没, 上几部的命令行里输入 curl -vv http://www.google.com
, 看是否翻墙成功, 成功提示如下:
ping
通 google
后在执行发包命令, 你就会看到如下, 说明就成功了, 这时去pub.dev
去搜索你的插件就能搜到了。
Package has 2 warnings. Upload anyway (y/n)? y
Uploading...
Successfully uploaded package.
5. 有问题欢迎留言