Flutter插件ilkertestwg的介绍与使用指南
介绍
这是一个用于通过WireGuard隧道设置和控制VPN连接的Flutter插件。本文档将展示如何在Flutter应用中使用该插件。
ilkertestwg使用方法
初始化
首先,需要初始化一个WireGuard实例并指定有效的名称:
final wireguard = WireGuardFlutter.instance;
// 初始化接口
await wireguard.initialize(interfaceName: 'wg0');
配置数据
接下来,声明.conf
配置文件的数据:
const String conf = '''
[Interface]
PrivateKey = 0IZmHsxiNQ54TsUs0EQ71JNsa5f70zVf1LmDvON1CXc=
Address = 10.8.0.4/32
DNS = 1.1.1.1
[Peer]
PublicKey = 6uZg6T0J1bHuEmdqPx8OmxQ2ebBJ8TnVpnCdV8jHliQ=
PresharedKey = As6JiXcYcqwjSHxSOrmQT13uGVlBG90uXZWmtaezZVs=
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 0
Endpoint = 38.180.13.85:51820
''';
更多配置信息的详细说明可以参考WireGuard文档。
连接
在初始化完成后,可以通过以下方式连接:
await wireguard.startVpn(
serverAddress: address, // 例如 'demo.wireguard.com:51820'
wgQuickConfig: conf, // 配置文件
providerBundleIdentifier: 'com.example', // 应用的标识符
);
断开连接
连接后,可以使用以下方法断开连接:
await wireguard.stopVpn();
监听状态变化
可以通过监听状态变化来实时获取当前连接的状态:
wireguard.vpnStageSnapshot.listen((event) {
debugPrint("状态改变 $event");
});
或者通过以下方式获取当前状态:
final stage = await wireguard.stage();
debugPrint("当前状态: $stage");
可用的状态包括:
状态代码 | 描述 |
---|---|
connecting | 接口正在连接 |
connected | 接口已连接 |
disconnecting | 接口正在断开连接 |
disconnected | 接口已断开连接 |
waitingConnection | 等待用户交互 |
authenticating | 正在与服务器进行身份验证 |
reconnect | 正在重新连接接口 |
noConnection | 未建立任何连接 |
preparing | 准备连接中 |
denied | 连接被系统拒绝(通常因权限问题) |
exiting | 接口正在退出 |
支持的平台
以下是插件支持的平台及其版本要求:
平台 | Android | iOS | macOS | Windows | Linux |
---|---|---|---|---|---|
版本 | SDK 21+ | 15.0+ | 12+ | 7+ | Any |
Windows
在Windows上运行应用时,必须以管理员权限运行才能创建和操作隧道。可以通过以下命令从提升的命令提示符中调试应用:
flutter run
正常运行时,系统会请求以管理员权限运行应用。
Linux
安装依赖
在Linux上使用该插件前,需要安装必要的依赖项:wireguard
和 wireguard-tools
。
在Ubuntu/Debian系统上,可以使用以下命令安装依赖:
sudo apt install wireguard wireguard-tools openresolv
对于其他Linux发行版,请参考WireGuard安装指南。
注意事项
如果系统中未安装openresolv
,可能会导致包含DNS字段的配置文件无法连接。更多相关信息可以查看此问题。
初始化
当调用wireguard.initialize
时,应用会请求用户密码([sudo] password for <user>:
)。这是因为WireGuard必须以root权限运行才能创建和管理隧道。无论是调试模式还是发布模式,都需要这样做。
注意:切勿以root模式运行应用(例如sudo ./executable
或sudo flutter run
),否则连接将无法建立。
示例代码
以下是一个完整的示例代码,展示了如何使用插件:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wireguard_flutter/wireguard_flutter.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('WireGuard Example App'),
),
body: const MyApp(),
),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final wireguard = WireGuardFlutter.instance;
final WireguardService _wireguardService = WireguardService();
String _downloadCount = 'N/A';
String _uploadCount = 'N/A';
late String name;
[@override](/user/override)
void initState() {
super.initState();
_getWireGuardDataCounts();
wireguard.vpnStageSnapshot.listen((event) {
debugPrint("状态改变 $event");
if (mounted) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('状态改变: $event'),
));
}
});
name = 'my_wg_vpn';
}
Future<void> initialize() async {
try {
await wireguard.initialize(interfaceName: name);
debugPrint("初始化成功 $name");
} catch (error, stack) {
debugPrint("初始化失败: $error\n$stack");
}
}
void _getWireGuardDataCounts() async {
try {
final dataCounts = await _wireguardService.getDataCounts();
setState(() {
_downloadCount = dataCounts['download'].toString();
_uploadCount = dataCounts['upload'].toString();
});
} catch (e) {
print('获取数据统计失败: $e');
}
}
void startVpn() async {
try {
await wireguard.startVpn(
serverAddress: '167.235.55.239:51820',
wgQuickConfig: conf,
providerBundleIdentifier: 'com.billion.wireguardvpn.WGExtension',
);
} catch (error, stack) {
debugPrint("连接失败 $error\n$stack");
}
}
void disconnect() async {
try {
await wireguard.stopVpn();
} catch (e, str) {
debugPrint('断开失败 $e\n$str');
}
}
void getStatus() async {
debugPrint("获取状态中...");
final stage = await wireguard.stage();
debugPrint("当前状态: $stage");
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('当前状态: $stage'),
));
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints.expand(),
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 20),
TextButton(
onPressed: initialize,
style: ButtonStyle(
minimumSize: WidgetStateProperty.all<Size>(const Size(100, 50)),
padding: WidgetStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: WidgetStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'初始化',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: startVpn,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'连接',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: disconnect,
style: ButtonStyle(
minimumSize: WidgetStateProperty.all<Size>(const Size(100, 50)),
padding: WidgetStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: WidgetStateProperty.all<Color>(Colors.blueAccent),
overlayColor: WidgetStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'断开连接',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: getStatus,
style: ButtonStyle(
minimumSize: WidgetStateProperty.all<Size>(const Size(100, 50)),
padding: WidgetStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: WidgetStateProperty.all<Color>(Colors.blueAccent),
overlayColor: WidgetStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'获取状态',
style: TextStyle(color: Colors.white),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('下载速度: $_downloadCount'),
Text('上传速度: $_uploadCount'),
ElevatedButton(
onPressed: _getWireGuardDataCounts,
child: const Text('刷新数据统计'),
),
],
)
],
),
);
}
}
const String conf = '''
[Interface]
Address = 192.168.6.163/32
DNS = 1.1.1.1,8.8.8.8
PrivateKey = mBVsI8hk7a1JPJqXuVELOTnSSI2tL6Q4HamW5gxEgEk=
[Peer]
publickey=MKxF3963hjD/MLGSIcGRLaco/N5uDN/Dslt/k675Knc=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = indo7.vpnjantit.com:1024
''';
class WireguardService {
static const platform = MethodChannel('billion.group.wireguard_flutter/wgcontrol');
Future<Map<String, int>> getDataCounts() async {
try {
final Map<dynamic, dynamic> result = await platform.invokeMethod('getDataCounts');
return Map<String, int>.from(result);
} catch (e) {
throw '获取数据统计失败: $e';
}
}
}
更多关于Flutter插件ilkertestwg的介绍与使用指南的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在使用Flutter时,如果遇到一个未知功能的插件(例如 ilkertestwg
),并且其介绍为 undefined
,你可以通过以下步骤来探索和理解它的功能:
1. 查看插件的源代码
- 如果插件是开源的,你可以访问其GitHub仓库或其他代码托管平台,查看其源代码。
- 通过阅读
pubspec.yaml
文件,了解插件的依赖项和版本信息。 - 查看
lib
目录下的 Dart 文件,了解插件的核心功能和 API。
2. 查看插件的文档
- 即使插件的介绍为
undefined
,插件可能仍然包含一些文档或注释。 - 查看
README.md
文件,了解插件的基本用法和示例代码。 - 如果插件有示例项目(通常在
example
目录下),可以运行示例项目来观察插件的实际效果。
3. 查看插件的依赖项
- 在
pubspec.yaml
文件中,查看插件的依赖项,了解它可能依赖的其他插件或库。 - 通过依赖项,你可以推测插件可能的功能或用途。
4. 尝试使用插件
- 在你的 Flutter 项目中添加插件依赖:
dependencies: ilkertestwg: ^1.0.0 # 假设插件的版本为 1.0.0
- 运行
flutter pub get
来获取插件。 - 在代码中导入插件并尝试使用其提供的 API:
import 'package:ilkertestwg/ilkertestwg.dart';