gpt4 book ai didi

dart - 在 Flutter 中使用 JS 库

转载 作者:IT老高 更新时间:2023-10-28 12:35:21 25 4
gpt4 key购买 nike

我正在尝试使用 Ether JS在我的 Flutter 应用程序中。我知道它没有得到直接支持,甚至现有的实现也没有得到很好的记录。

有什么方法可以在我的 Android 和 iOS 的 Flutter 应用程序中使用这个库?也欢迎任何其他替代建议。

我试过js.dart但无法弄清楚如何使用它。我什至不确定这是否是这种情况下的正确选择。

我也试过Flutter WebView Plugin .

plugin.evalJavascript(
'function add(a,b){return a+b;}add(2,3);'
).then((s) {
print(s);
}

这个函数正确地返回 5 作为响应。但是我不明白如何像这样使用 EtherJS 库。

我是 Flutter、Dart 和 JS 的菜鸟。任何帮助将不胜感激。

最佳答案

我最终通过使用 rmtmckenzie 建议的平台 channel 解决了这个问题。在这answer .

我下载了 JS 文件并将其保存到 android/app/src/main/res/raw/ether.jsios/runner/ether.js 以供分别是 Android 和 iOS。

安装依赖项

安卓

添加 LiquidCore作为应用程序级别的依赖项 build.gradle

implementation 'com.github.LiquidPlayer:LiquidCore:0.5.0'

iOS

对于 iOS,我使用了 JavaScriptCore这是 SDK 的一部分。

平台 channel

在我的例子中,我需要创建一个基于我传入 JS 函数的助记符(查找 BIP39)的钱包。为此,我创建了一个平台 channel ,它将助记符(基本上是字符串类型)作为参数传递,完成后将返回一个 JSON 对象。

Future<dynamic> getWalletFromMnemonic({@required String mnemonic}) {
return platform.invokeMethod('getWalletFromMnemonic', [mnemonic]);
}

Android 实现 (Java)

MainActivity.java在这一行之后添加这个

GeneratedPluginRegistrant.registerWith(this);

String CHANNEL = "UNIQUE_CHANNEL_NAME";

new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.equals("getWalletFromMnemonic")) {
ArrayList<Object> args = (ArrayList<Object>) methodCall.arguments;
String mnemonic = (String) args.get(0);

JSObject walletFromMnemonic = getWalletFromMnemonic(mnemonic);
if (walletFromMnemonic == null) {
result.error("Could not create", "Wallet generation failed", null);
return;
}

String privateKey = walletFromMnemonic.property("privateKey").toString();
String address = walletFromMnemonic.property("address").toString();

HashMap<String, String> map = new HashMap<>();
map.put("privateKey", privateKey);
map.put("address", address);

JSONObject obj = new JSONObject(map);

result.success(obj.toString());

} else {
result.notImplemented();
}
}
}
);

声明以下方法执行与JS库交互并将结果返回到平台 channel 的实际操作。

@Nullable
@VisibleForTesting
private JSObject getWalletFromMnemonic(String mnemonic) {
JSContext jsContext = getJsContext(getEther());
JSObject wallet = getWalletObject(jsContext);

if (wallet == null) {
return null;
}

if (!wallet.hasProperty("fromMnemonic")) {
return null;
}

JSFunction walletFunction = wallet.property("fromMnemonic").toObject().toFunction();
return walletFunction.call(null, mnemonic).toObject();
}

@Nullable
@VisibleForTesting
private JSObject getWalletObject(JSContext context) {
JSObject jsEthers = context.property("ethers").toObject();
if (jsEthers.hasProperty("Wallet")) {
return jsEthers.property("Wallet").toObject();
}
return null;
}

@VisibleForTesting
String getEther() {
String s = "";
InputStream is = getResources().openRawResource(R.raw.ether);
try {
s = IOUtils.toString(is);
} catch (IOException e) {
s = null;
e.printStackTrace();
} finally {
IOUtils.closeQuietly(is);
}
return s;
}

@VisibleForTesting
JSContext getJsContext(String code) {
JSContext context = new JSContext();
context.evaluateScript(code);
return context;
}

iOS 实现 (Swift)

override application 方法内的 AppDelegate.swift 中添加以下行。

final let methodChannelName: String = "UNIQUE_CHANNEL_NAME"
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel.init(name: methodChannelName, binaryMessenger: controller)

methodChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: FlutterResult)-> Void in
if call.method == "getWalletFromMnemonic" {
guard let mnemonic = call.arguments as? [String] else {
return
}

if let wallet = self.getWalletFromMnemonic(mnemonic: mnemonic[0]) {
result(wallet)
} else {
result("Invalid")
}
}
})

添加与 JavaScriptCore 交互的逻辑。

private func getWalletFromMnemonic(mnemonic: String) -> Dictionary<String, String>? {
let PRIVATE_KEY = "privateKey"
let ADDRESS = "address"

guard let jsContext = self.initialiseJS(jsFileName: "ether") else { return nil }
guard let etherObject = jsContext.objectForKeyedSubscript("ethers") else { return nil }
guard let walletObject = etherObject.objectForKeyedSubscript("Wallet") else { return nil }


guard let walletFromMnemonicObject = walletObject.objectForKeyedSubscript("fromMnemonic") else {
return nil
}

guard let wallet = walletFromMnemonicObject.call(withArguments: [mnemonic]) else { return nil }
guard let privateKey = wallet.forProperty(PRIVATE_KEY)?.toString() else { return nil }
guard let address = wallet.forProperty(ADDRESS)?.toString() else { return nil }

var walletDictionary = Dictionary<String, String>()
walletDictionary[ADDRESS] = address
walletDictionary[PRIVATE_KEY] = privateKey

return walletDictionary
}

private func initialiseJS(jsFileName: String) -> JSContext? {
let jsContext = JSContext()
guard let jsSourcePath = Bundle.main.path(forResource: jsFileName, ofType: "js") else {
return nil
}
do {
let jsSourceContents = try String(contentsOfFile: jsSourcePath)
jsContext!.evaluateScript(jsSourceContents)
return jsContext!
} catch {
print(error.localizedDescription)
}
return nil
}

关于dart - 在 Flutter 中使用 JS 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52330102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com