- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在尝试使用 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.js
和 ios/runner/ether.js
以供分别是 Android 和 iOS。
添加 LiquidCore作为应用程序级别的依赖项 build.gradle
implementation 'com.github.LiquidPlayer:LiquidCore:0.5.0'
对于 iOS,我使用了 JavaScriptCore这是 SDK 的一部分。
在我的例子中,我需要创建一个基于我传入 JS 函数的助记符(查找 BIP39)的钱包。为此,我创建了一个平台 channel ,它将助记符(基本上是字符串类型)作为参数传递,完成后将返回一个 JSON 对象。
Future<dynamic> getWalletFromMnemonic({@required String mnemonic}) {
return platform.invokeMethod('getWalletFromMnemonic', [mnemonic]);
}
在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;
}
在 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/
我正在尝试从flutter应用程序构建apk,但出现此错误: Note: /mnt/Software/Linux/Flutter/flutter/.pub-cache/hosted/pub.dartl
我有一个名为 X 的较大应用程序,还有另一个名为 Y 的较小应用程序。他们现在彼此分开,并且工作正常。我想将应用程序 Y 集成到 X 中。我想将 Y 的代码放入 X 项目中,但它们应该有不同的 Mai
在android Studio中选择Create New Flutter Project,出现如下4个选项。 Flutter 应用程序 Flutter 插件 Flutter 包 flutter 模块
我看到我的 flutter 项目生成了一个文件 ios/Flutter/Flutter.podspec ,这个文件有什么用? 如果它与生成的 Flutter.framework 有关? 我应该将它包含
我尝试过的 在包含flutter SDK的位置添加/编辑.bash_profile.rtf文件。 导出PATH = / Users / temur / Documents / Projects / F
Flutter 日志会打印数千个详细/垃圾邮件日志。 我正在尝试调试一个复杂的应用程序,但是打印太冗长了,以至于我很难找到我自己打印的东西。 有没有办法禁用详细? 就像是: Logger.level.
在flutter 1.22更新之后,我在Lineargradient colors属性中遇到错误,这给我一个错误,即未定义名称colors参数。.在Android中更新flutter和flutter插
在下面的代码 widget.hintText 中给出错误,我试图将日期选择器作为单独的组件,并在从其他文件调用它时动态传递提示文本值。 import 'package:date_field/date_
在下面的代码 widget.hintText 中给出错误,我试图将日期选择器作为单独的组件,并在从其他文件调用它时动态传递提示文本值。 import 'package:date_field/date_
Flutter 1.0 发布后,我正在按照步骤搭建 Flutter 开发环境。 在步骤中(如所附屏幕截图所示),它说要更新 $PATH 两次,一次使用 flutter 工具的路径 export PAT
我有一个用 flutter 编写的移动应用程序,我想将其转换为 flutter_web 应用程序(集成 flutter_web 尚不可用)。我目前遇到包裹问题。 我已按照本网站中列出的说明进行操作 h
如何向我的 Flutter 路由添加自定义转换?这是我目前的路线结构。 class MyApp extends StatelessWidget { // This widget is the
我正在尝试通过 URL 在 webview 中显示网页。我试过 flutter_webview_plugin 插件,但是当我在浏览器上运行项目时它不起作用。 在 flutter web applica
我正在使用 animatedContainer 在按下按钮时显示 listView.builder()。这是一个要显示的简单子(monad)列表,但问题是我不知道 ListView 构建器的高度会传递
我目前正在我的应用程序中制作渐变背景动画......我正在使用 lottie 动画的帮助下这样做!我试图将它封装在一个容器中并成功地做到了。但是有一个问题,尽管我将高度更改为大于 2000 的东西,但
美好的一天! 我无法弄清楚如何使用 google 标签管理器设置 flutter。我找到了 this package包括标签管理器 api。但是我不知道如何正确配置它。 (在网络上我只需要复制粘贴一个
我的购物车模型如下 class Cart { String description; double unitCost; double amount; int quantity; S
在 Flutter 应用程序中,我想为在线托管的资源(图像、视频等)实现缓存。 我希望它能在原生平台 (Android/iOS)(例如使用文件系统)和网络(例如使用 IndexedDB)上运行。 Fl
我写了一个页面,在顶部一切都很好,应该是这样。在底部我有一个事件的历史。我的容器的宽度是自动确定的(取决于屏幕的宽度),而高度 - 不,在不同的设备上有不同的高度(底部的缩进是不同的)。是否可以自动确
我正在处理一个页面,其中有一些字段,例如 textfield 和 slider。在页面的末尾必须有一个用于进行下一步的按钮,该按钮被包裹在 Align 中以在页面之间具有固定位置。 另一方面,resi
我是一名优秀的程序员,十分优秀!