插件定义1创建一个Flutter的插件移动端闲话编程Contents插件定义 ............................................................................................... 1创建插件工程定义接口Platform实现 ......................................................................................... 2Example ............................................................................................... 4最近需要在中实现加解密和,但搜索了一下貌似网络上没有现成的库可以用,因此尝试手写了一个的插件,实现两个功能:加解密(插件定义创建插件工程其实貌似也可以在项目中直接调用相关的实现,考虑到把这一部分剥离出来可以单独维护和造福后人,还是选择创建一个。首先需要创建一个插件的工程,通过如下的命令:flutter create --org com.riguz --template=plugin encryptions这样会生成一个项目,值得注意的是,这里会使用,会使用。但对于我这种没有基础的人来说看着太麻烦了,我尝试了一些之后放弃了。于是需要切换成。这里有一个小的方法可以只修改的部分:cd encryptionsrm -rf ios examples/iosflutter create -i swift --org com.riguz .删除的目录后执行这个命令,可以重新生成的工程,基于的。定义Dart接口首先定义出我们要暴露的接口。举个例子,对于加密的函数,我们可以这样写:class Encryptions { static const MethodChannel _channel = const MethodChannel('encryptions'); static Future<Uint8List> aesEncrypt( Uint8List key, Uint8List iv, Uint8List value) async { return await _channel .invokeMethod("aesEncrypt", {"key": key, "iv": iv, "value": Platform实现2value}); }这里有几点值得注意的:是用来调用原生接口,后面各个平台会注册同名的。调用原生方法通过方法名参数调用,参数的对应列表参见官方文档。这里我们希望的是中的类型,所以用参数通过的传递到原生接口,原生代码通过参数名取得参数值Platform实现ios首先需要先一下cd encryptions/example; flutter build ios --no-codesign在中打开项目,有一个的类,在这个里面实现即可:public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { let args = call.arguments as! [String: Any]; switch call.method { case "aesEncrypt", "aesDecrypt": let key = args["key"] as! FlutterStandardTypedData; let iv = args["iv"] as! FlutterStandardTypedData; let value = args["value"] as! FlutterStandardTypedData; do { let cipher = try handleAes(key: key.data, iv: iv.data, value: value.data, method: call.method); result(cipher); } catch { result(nil); }; // ... }}因为需要使用,需要在中调用原生代码,试了一些办法都不行,后来发现其实比较简单,直接在中有一个文件中加入引用,就可以直接调用了#import "EncryptionsPlugin.h"#import "argon2.h"func argon2i(password: Data, salt: Data)-> Data { var outputBytes = [UInt8](repeating: 0, count: hashLength); password.withUnsafeBytes { passwordBytes in salt.withUnsafeBytes { saltBytes in argon2i_hash_raw(iterations, memory, parallelism, Platform实现3passwordBytes, password.count, saltBytes, salt.count, &outputBytes, hashLength); } } return Data(bytes: UnsafePointer<UInt8>(outputBytes), count: hashLength);}Android在中打开工程(第一次打开是需要的,cd encryptions/example; flutter build apk,也类似)。中实现起来会简单一点,这里只说一下如何调用原生代码:首先在中加入额外的步骤:externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" }}然后在中指定编译步骤,我这里需要编译一个的库,以及一个调用的库。add_library( argon2 SHARED argon2/src/argon2.c argon2/src/core.c argon2/src/blake2/blake2b.c argon2/src/encoding.c argon2/src/ref.c argon2/src/thread.c)add_library( argon2-binding SHARED argon2_binding.cpp)target_include_directories( argon2 PRIVATE argon2/include)target_include_directories( argon2-binding Example4 PRIVATE argon2/include)find_library( log-lib log)target_link_libraries( native-lib ${log-lib})target_link_libraries( argon2-binding argon2 ${log-lib})然后就通过调用到的方法:public final class Argon2 { static { System.loadLibrary("argon2-binding"); } // ... private native byte[] argon2iInternal(int iterations, int memory, int parallelism, final byte[] password, final byte[] salt, int hashLength); private native byte[] argon2dInternal(int iterations, int memory, int parallelism, final byte[] password, final byte[] salt, int hashLength);}详细的代码不再累述。Example在工程中,用调用一下这些接口,然后可以分别在和中运行起来,看一下不同平台是否都支持。不清楚是否有自动化的测试方法。 Example5如果想了解更多,这里是详细的代码。参考