自定義 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 改動目錄為 ios\Classes\hello.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環境, 框架會自動區分, 你只需要編寫原生代碼就行, 目錄 example\lib\main.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, 看是否FQ成功, 成功提示如下:

pinggoogle 后在執行發包命令, 你就會看到如下, 說明就成功了, 這時去pub.dev 去搜索你的插件就能搜到了。

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

5. 有問題歡迎留言


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM