Flutter账本管理插件ledger_flutter_plus的使用
Flutter账本管理插件ledger_flutter_plus的使用
概述
Ledger Nano设备是管理您加密货币和NFT的理想硬件钱包。这个Flutter插件使您可以轻松找到附近的Ledger设备,连接它们并通过USB和/或BLE签署交易。
支持的设备
BLE | USB | |
---|---|---|
Android | ✔️ | ✔️ |
iOS | ✔️ | ❌ |
WEB | ✔️ | ✔️ |
开始使用
安装
通过pub.dev安装此软件包的最新版本:
ledger_flutter_plus: ^latest-version
您可能需要安装其他Ledger App插件以支持不同的区块链。请参阅下面的“自定义Ledger App插件”部分。
例如,添加Algorand支持:
ledger_cardano: ^latest-version
设置
创建一个新的LedgerOptions
实例并将其传递给Ledger
构造函数。
final options = LedgerOptions(
maxScanDuration: const Duration(milliseconds: 5000),
);
final ledgerUsb = Ledger.usb();
final ledgerBle = Ledger.ble(
onPermissionRequest: (state) {},
);
Android
在AndroidManifest.xml
中添加以下权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--bibo01 : hardware option-->
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
<!-- required for API 18 - 30 -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- API 31+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
iOS
在您的应用程序的Info.plist
文件中添加以下条目:
iOS13及以上
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses bluetooth to find, connect and sign transactions with your Ledger Nano X</string>
iOS12及以下
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses bluetooth to find, connect and sign transactions with your Ledger Nano X</string>
使用
扫描附近设备
您可以使用scan()
方法扫描附近的Ledger设备。这将返回一个Stream
,当发现新设备时可以监听。
final subscription = ledger.scan().listen((device) => print(device));
扫描会在maxScanDuration
过去后停止或调用stop()
方法。
await ledger.stop();
权限
Ledger Flutter插件使用蓝牙低能耗(Bluetooth Low Energy),这需要处理iOS和Android上的某些权限。插件每次需要权限时都会发送回调。只需覆盖onPermissionRequest
并让permission_handler
包处理其余的工作即可。
final ledger = Ledger(
options: options,
onPermissionRequest: (status) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
if (status != BleStatus.ready) {
return false;
}
return statuses.values.where((status) => status.isDenied).isEmpty;
},
);
断开连接
使用disconnect()
方法关闭与Ledger设备建立的连接。
await ledger.disconnect(device);
处置
始终使用dispose()
方法关闭所有连接并处置任何潜在的监听器以避免资源泄漏。
await ledger.dispose();
LedgerException
每个方法都可能抛出一个LedgerException
,其中包含消息、原因和潜在的错误代码。
try {
await channel.ledger.connect(device);
} on LedgerException catch (ex) {
await channel.ledger.disconnect(device);
}
自定义Ledger App插件
1. 创建新的LedgerApp
创建一个新的类(例如EthereumLedgerApp
)并扩展自LedgerApp
。
class EthereumLedgerApp extends LedgerApp {
EthereumLedgerApp(super.ledger);
[@override](/user/override)
Future<List<String>> getAccounts(LedgerDevice device) async {
throw UnimplementedError();
}
[@override](/user/override)
Future<Uint8List> signTransaction(
LedgerDevice device,
Uint8List transaction,
) {
throw UnimplementedError();
}
[@override](/user/override)
Future<List<Uint8List>> signTransactions(
LedgerDevice device,
List<Uint8List> transactions,
) async {
throw UnimplementedError();
}
}
2. 定义Ledger操作
为每个APDU命令创建一个新的操作类(例如EthereumPublicKeyOperation
)并扩展自LedgerOperation
。
class AlgorandPublicKeyOperation extends LedgerOperation<List<String>> {
final int accountIndex;
AlgorandPublicKeyOperation({
this.accountIndex = 0,
});
[@override](/user/override)
Future<Uint8List> write(ByteDataWriter writer, int index, int mtu) async {
writer.writeUint8(0x80); // ALGORAND_CLA
writer.writeUint8(0x03); // PUBLIC_KEY_INS
writer.writeUint8(0x00); // P1_FIRST
writer.writeUint8(0x00); // P2_LAST
writer.writeUint8(0x04); // ACCOUNT_INDEX_DATA_SIZE
writer.writeUint32(accountIndex); // Account index as bytearray
return writer.toBytes();
}
[@override](/user/override)
Future<List<String>> read(ByteDataReader reader, int index, int mtu) async {
return [
Address(publicKey: reader.read(reader.remainingLength)).encodedAddress,
];
}
}
3. 实现LedgerApp
最后一步是使用Ledger客户端在连接的Ledger上执行所需的操作。实现LedgerApp
所需的各个方法。
[@override](/user/override)
Future<List<String>> getAccounts(LedgerDevice device) async {
return ledger.sendOperation<List<String>>(
device,
AlgorandPublicKeyOperation(accountIndex: accountIndex),
);
}
示例完整Demo
import 'package:flutter/material.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Ledger Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final options = LedgerOptions(
maxScanDuration: const Duration(milliseconds: 5000),
);
final ledger = Ledger.ble(
onPermissionRequest: (state) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
if (state != BleStatus.ready) {
return false;
}
return statuses.values.where((status) => status.isDenied).isEmpty;
},
);
void _startScanning() {
final subscription = ledger.scan().listen((device) {
print('Found device: $device');
});
}
void _stopScanning() async {
await ledger.stop();
}
void _disconnect() async {
await ledger.disconnect(null);
}
void _dispose() async {
await ledger.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ledger Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _startScanning,
child: Text('Start Scanning'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _stopScanning,
child: Text('Stop Scanning'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _disconnect,
child: Text('Disconnect'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _dispose,
child: Text('Dispose'),
),
],
),
),
);
}
}
更多关于Flutter账本管理插件ledger_flutter_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter账本管理插件ledger_flutter_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 ledger_flutter_plus
插件的示例代码,该插件可以用于账本管理。假设你已经将 ledger_flutter_plus
添加到你的 Flutter 项目中,并且已经完成了相关的配置。
首先,确保在你的 pubspec.yaml
文件中添加了依赖:
dependencies:
flutter:
sdk: flutter
ledger_flutter_plus: ^最新版本号 # 请替换为实际的最新版本号
然后运行 flutter pub get
来获取依赖。
接下来,我们将编写一个简单的 Flutter 应用来演示如何使用 ledger_flutter_plus
插件。
示例代码
main.dart
import 'package:flutter/material.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Ledger Flutter Plus Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LedgerDemoPage(),
);
}
}
class LedgerDemoPage extends StatefulWidget {
@override
_LedgerDemoPageState createState() => _LedgerDemoPageState();
}
class _LedgerDemoPageState extends State<LedgerDemoPage> {
late Ledger ledger;
@override
void initState() {
super.initState();
// 初始化 Ledger 实例
ledger = Ledger();
// 这里可以添加其他初始化代码,比如连接硬件设备等
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ledger Flutter Plus Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
try {
// 执行一些 Ledger 操作,例如获取版本信息
String version = await ledger.getVersion();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Ledger Version: $version'),
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${e.message}'),
backgroundColor: Colors.red,
),
);
}
},
child: Text('Get Ledger Version'),
),
// 可以添加更多按钮来演示其他 Ledger 功能
],
),
),
);
}
@override
void dispose() {
// 清理资源,比如关闭 Ledger 连接等
ledger.dispose();
super.dispose();
}
}
注意事项
- 硬件连接:确保你的 Ledger 设备已经通过 USB 连接到你的开发机器,并且已经解锁和选择了相应的应用。
- 权限处理:在真实应用中,你可能需要处理更多的权限请求和错误处理,比如请求用户允许 USB 设备访问。
- 插件方法:
ledger_flutter_plus
插件提供了许多方法来与 Ledger 设备交互,比如签名交易、获取公钥等。上述示例中只演示了获取版本信息的方法,你可以查阅插件的官方文档来了解更多方法。
官方文档
为了获取更详细的信息和使用案例,请参考 ledger_flutter_plus
插件的官方文档或 GitHub 仓库。
这个示例代码提供了一个基本的框架,你可以在此基础上扩展以满足你的具体需求。