自定义 Flutter 插件(flutter_3des_plugin)步骤,以及上传插件的那些坑。

本人掘金文章

开场白:

  • 目前截止 flutter github start 数已经 94.4K了,潜在的说明了这事以后App开发趋势。
  • 作为新起之秀,后劲足但是社区生态不够完善。还有许多的功能还没有相应的插件。
  • 很荣幸能为flutter社区做贡献, 插件地址 flutter_3des_plugin, github地址

步骤

1. 创建一个插件包

注:flutter 插件项目默认针对iOS代码使用Objective-CAndroid代码使用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) 插件包APIAndroid实现

  • android/src/main/java/com/yourcompany/​hello/HelloPlugin.java

3) 插件包APIios实现

  • ios/Classes/HelloPlugin.m

4) 一个依赖于该插件的Flutter应用程序,来说明如何使用它

  • example/

3. 实现package包, 编写业务代码 运行flutter build apk

使用Android Studio 或者 Vscode编辑Android代码, 编写代码之前,首先确保代码至少已经构建过一次(例如,cdhello/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. 先来看错误有哪些:
// 错误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...
  1. 解决; 先不管报哪类错, 跟着下面步骤执行命令就对了
  • 第一步 用命令行(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, 看是否翻墙成功, 成功提示如下:

pinggoogle 后在执行发包命令, 你就会看到如下, 说明就成功了, 这时去pub.dev 去搜索你的插件就能搜到了。

Package has 2 warnings. Upload anyway (y/n)? y
Uploading...
Successfully uploaded package.

5. 有问题欢迎留言

原文地址:https://www.cnblogs.com/ljx20180807/p/13155070.html