Flutter网络发现与探测插件ping_discover_network_plus的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter网络发现与探测插件ping_discover_network_plus的使用

简介

ping_discover_network_plus 是一个用于 Dart/Flutter 的库,允许通过 ping IP 子网来发现网络中的设备。它可以在本地网络中查找打印机(例如,在端口 9100 上)和其他任何设备和服务。该库已在 Android 和 iOS 平台上进行了测试。

[pub.dev页面] | [文档]

开始使用

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  ping_discover_network_plus: ^latest_version

然后运行 flutter pub get 来安装包。

示例代码

下面是一个完整的示例应用程序,展示了如何使用 ping_discover_network_plus 插件来发现本地网络中的设备。

完整示例Demo

import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:ping_discover_network_plus/ping_discover_network_plus.dart';
import 'package:wifi_info_plugin_plus/wifi_info_plugin_plus.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  String localIp = '';
  List<String> devices = [];
  bool isDiscovering = false;
  int found = -1;
  TextEditingController portController = TextEditingController(text: '80');

  void discover(BuildContext ctx) async {
    final scaffoldMessage = ScaffoldMessenger.of(context);

    setState(() {
      isDiscovering = true;
      devices.clear();
      found = -1;
    });

    String ip;
    try {
      ip = (await WifiInfoPlugin.wifiDetails)?.ipAddress ?? 'NO IP DETECTED';
      log('local ip:\t$ip');
    } catch (e) {
      const snackBar = SnackBar(
          content: Text('WiFi is not connected', textAlign: TextAlign.center));
      scaffoldMessage.showSnackBar(snackBar);
      return;
    }
    setState(() {
      localIp = ip;
    });

    final String subnet = ip.substring(0, ip.lastIndexOf('.'));
    int port = 80;
    try {
      port = int.parse(portController.text);
    } catch (e) {
      portController.text = port.toString();
    }
    log('subnet:\t$subnet, port:\t$port');

    final stream = NetworkAnalyzer.discover(subnet, port);

    stream.listen((NetworkAddress addr) {
      if (addr.exists) {
        log('Found device: ${addr.ip}');
        setState(() {
          devices.add(addr.ip);
          found = devices.length;
        });
      }
    })
      ..onDone(() {
        setState(() {
          isDiscovering = false;
          found = devices.length;
        });
      })
      ..onError((dynamic e) {
        const snackBar = SnackBar(
            content: Text('Unexpected exception', textAlign: TextAlign.center));
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Discover Local Network'),
      ),
      body: Builder(
        builder: (BuildContext context) {
          return Container(
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                TextField(
                  controller: portController,
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(
                    labelText: 'Port',
                    hintText: 'Port',
                  ),
                ),
                const SizedBox(height: 10),
                Text('Local ip: $localIp',
                    style: const TextStyle(fontSize: 16)),
                const SizedBox(height: 15),
                ElevatedButton(
                    onPressed: isDiscovering ? null : () => discover(context),
                    child: Text(isDiscovering ? 'Discovering...' : 'Discover')),
                const SizedBox(height: 15),
                found >= 0
                    ? Text('Found: $found device(s)',
                        style: const TextStyle(fontSize: 16))
                    : Container(),
                Expanded(
                  child: ListView.builder(
                    itemCount: devices.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Column(
                        children: <Widget>[
                          Container(
                            height: 60,
                            padding: const EdgeInsets.only(left: 10),
                            alignment: Alignment.centerLeft,
                            child: Row(
                              children: <Widget>[
                                const Icon(Icons.devices),
                                const SizedBox(width: 10),
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: <Widget>[
                                      Text(
                                        '${devices[index]}:${portController.text}',
                                        style: const TextStyle(fontSize: 16),
                                      ),
                                    ],
                                  ),
                                ),
                                const Icon(Icons.chevron_right),
                              ],
                            ),
                          ),
                          const Divider(),
                        ],
                      );
                    },
                  ),
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

关键功能

  • 获取本地IP地址:使用 wifi_info_plugin_plus 获取设备的本地IP地址。
  • 发现网络设备:使用 NetworkAnalyzer.discoverNetworkAnalyzer.discover2 方法来发现指定子网和端口上的设备。
  • UI交互:提供了一个简单的用户界面,允许用户输入端口号并启动发现过程,结果显示在列表中。

注意事项

  • 设备需要连接到Wi-Fi网络。
  • 发现过程可能会花费一些时间,具体取决于网络规模和超时设置。
  • 可以根据需要调整超时时间和端口号。

希望这个示例能帮助你更好地理解和使用 ping_discover_network_plus 插件!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter网络发现与探测插件ping_discover_network_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络发现与探测插件ping_discover_network_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用 ping_discover_network_plus 插件进行网络发现和探测的示例代码。这个插件允许你在 Flutter 应用中执行网络设备的发现和 ping 操作。

首先,确保你的 Flutter 项目中已经添加了 ping_discover_network_plus 插件。你可以在 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  ping_discover_network_plus: ^最新版本号  # 替换为当前最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,在你的 Dart 文件中,你可以按照以下示例代码使用 ping_discover_network_plus 插件:

import 'package:flutter/material.dart';
import 'package:ping_discover_network_plus/ping_discover_network_plus.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> devices = [];
  bool isScanning = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Network Discovery'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () async {
                  setState(() {
                    isScanning = true;
                    devices.clear();
                  });
                  
                  try {
                    // 开始扫描网络
                    await for (var device in discoverNetworkDevices()) {
                      setState(() {
                        devices.add(device.ip);
                      });
                    }
                  } catch (e) {
                    print('Error scanning network: $e');
                  } finally {
                    setState(() {
                      isScanning = false;
                    });
                  }
                },
                child: Text(isScanning ? 'Scanning...' : 'Start Scanning'),
              ),
              SizedBox(height: 20),
              Expanded(
                child: ListView.builder(
                  itemCount: devices.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text('Device: ${devices[index]}'),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  // 使用ping_discover_network_plus的discoverNetworkDevices函数扫描网络
  Stream<NetworkDevice> discoverNetworkDevices() {
    return NetworkDiscovery().discoverDevices(
      timeout: Duration(seconds: 1), // 设置ping超时时间
      count: 4, // 设置发送的ICMP请求数量
    );
  }
}

在这个示例中,我们创建了一个简单的 Flutter 应用,其中包含一个按钮用于启动网络扫描。扫描到的设备 IP 地址会显示在下方的列表中。

解释

  1. 依赖导入:我们导入了 ping_discover_network_plus 插件。
  2. 状态管理:使用 StatefulWidget 来管理扫描状态和发现的设备列表。
  3. 扫描按钮:点击按钮时,调用 discoverNetworkDevices 函数开始扫描网络。
  4. 设备显示:扫描到的设备 IP 地址通过 ListView.builder 显示在屏幕上。
  5. 网络扫描discoverNetworkDevices 函数返回一个 Stream<NetworkDevice>,它使用 NetworkDiscovery().discoverDevices 方法来扫描网络。

请注意,ping_discover_network_plus 插件可能需要特定的权限,特别是在 Android 和 iOS 上。确保在 AndroidManifest.xmlInfo.plist 文件中添加了必要的网络权限。

这个示例应该能帮助你快速上手 ping_discover_network_plus 插件的使用。如果你有更具体的需求或问题,欢迎进一步提问!

回到顶部