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上使用该插件前,需要安装必要的依赖项:wireguardwireguard-tools

在Ubuntu/Debian系统上,可以使用以下命令安装依赖:

sudo apt install wireguard wireguard-tools openresolv

对于其他Linux发行版,请参考WireGuard安装指南

注意事项

如果系统中未安装openresolv,可能会导致包含DNS字段的配置文件无法连接。更多相关信息可以查看此问题

初始化

当调用wireguard.initialize时,应用会请求用户密码([sudo] password for <user>:)。这是因为WireGuard必须以root权限运行才能创建和管理隧道。无论是调试模式还是发布模式,都需要这样做。

注意:切勿以root模式运行应用(例如sudo ./executablesudo 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';
    }
  }
}
1 回复

更多关于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';
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!