Flutter点对点通信插件flutter_p2p_plus的使用

Flutter点对点通信插件flutter_p2p_plus的使用

获取开始

必要权限

在AndroidManifest.xml文件中添加以下权限:

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

请求权限

为了扫描设备和连接到设备,需要请求位置权限:

Future<bool> _checkPermission() async {
  if (!await FlutterP2pPlus.isLocationPermissionGranted()) {
    await FlutterP2pPlus.requestLocationPermission();
    return false;
  }
  return true;
}

注册与注销WiFi事件

为了接收连接状态变化或设备变化(如发现的设备等)的通知,你需要订阅wifiEvents并注册插件以接收原生事件。

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    _register();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _register();
    } else if (state == AppLifecycleState.paused) {
      _unregister();
    }
  }

  List<StreamSubscription> _subscriptions = [];

  void _register() async {
    if (!await _checkPermission()) {
      return;
    }
    _subscriptions.add(FlutterP2pPlus.wifiEvents.stateChange!.listen((change) {
      // 处理WiFi状态变化
    }));

    _subscriptions.add(FlutterP2pPlus.wifiEvents.connectionChange!.listen((change) {
      // 处理连接状态变化
    }));

    _subscriptions.add(FlutterP2pPlus.wifiEvents.thisDeviceChange!.listen((change) {
      // 处理本机设备变化
    }));

    _subscriptions.add(FlutterP2pPlus.wifiEvents.peersChange!.listen((change) {
      // 处理发现的设备
    }));

    _subscriptions.add(FlutterP2pPlus.wifiEvents.discoveryChange!.listen((change) {
      // 处理发现状态变化
    }));

    FlutterP2pPlus.register();  // 注册到原生事件流
  }

  void _unregister() {
    _subscriptions.forEach((subscription) => subscription.cancel()); // 取消订阅
    FlutterP2pPlus.unregister(); // 取消注册
  }
}

发现设备

注册后,只需调用FlutterP2pPlus.discoverDevices()方法来发现设备。

List<WifiP2pDevice> _peers = [];

void _register() async {
  /// ...

  _subscriptions.add(FlutterP2pPlus.wifiEvents.peersChange!.listen((change) {
    setState(() {
      _peers = change.devices;
    });
  }));

  /// ...
}

void _discover() {
  FlutterP2pPlus.discoverDevices();
}

连接到设备

调用FlutterP2pPlus.connect(device)并监听FlutterP2pPlus.wifiEvents.connectionChange

bool _isConnected = false;
bool _isHost = false;
String _deviceAddress = "";

void _register() async {
  // ...

  _subscriptions.add(FlutterP2pPlus.wifiEvents.connectionChange!.listen((change) {
    setState(() {
      _isConnected = change.networkInfo.isConnected;
      _isHost = change.wifiP2pInfo.isGroupOwner;
      _deviceAddress = change.wifiP2pInfo.groupOwnerAddress;
    });
  }));

  // ...
}

断开当前P2P组

调用FlutterP2pPlus.removeGroup()

void _disconnect() async {
  FlutterP2pPlus.removeGroup();
}

在设备之间传输数据

连接到设备后,可以在客户端和主机之间异步传输数据。

主机端

// 打开端口并接受连接

P2pSocket? _socket;
void _openPortAndAccept(int port) async {
  var socket = await FlutterP2pPlus.openHostPort(port);
  setState(() {
    _socket = socket;
  });

  var buffer = "";
  socket?.inputStream.listen((data) {
    var msg = String.fromCharCodes(data.data);
    buffer += msg;

    if (data.dataAvailable == 0) {
      snackBar("Data Received from ${_isHost ? "Client" : "Host"}: $buffer");
      socket.writeString("Successfully received: $buffer");
      buffer = "";
    }
  });

  debugPrint("_openPort done");
  _isOpen = await FlutterP2pPlus.acceptPort(port) ?? false;
  debugPrint("_accept done: $_isOpen");
}

客户端端

// 连接到端口并创建一个套接字

P2pSocket? _socket;
_connectToPort(int port) async {
  var socket = await FlutterP2pPlus.connectToHost(
    _deviceAddress, // 见上方“连接到设备”
    port,
    timeout: 100000, // 超时时间(默认为500毫秒)
  );

  setState(() {
    _socket = socket;
  });

  _socket?.inputStream.listen((data) {
    var msg = utf8.decode(data.data);
    snackBar("Received from ${_isHost ? "Host" : "Client"} $msg");
  });

  debugPrint("_connectToPort done");
}

更多关于Flutter点对点通信插件flutter_p2p_plus的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter点对点通信插件flutter_p2p_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_p2p_plus 是一个用于在 Flutter 中实现点对点(P2P)通信的插件。它允许设备之间直接通信,而无需通过中央服务器。这对于需要在本地网络中直接交换数据的应用程序非常有用。

以下是使用 flutter_p2p_plus 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_p2p_plus 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_p2p_plus: ^0.0.1  # 请使用最新版本

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

2. 初始化插件

在你的 Dart 代码中,首先需要初始化 flutter_p2p_plus 插件:

import 'package:flutter_p2p_plus/flutter_p2p_plus.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterP2pPlus.initialize();
  runApp(MyApp());
}

3. 发现设备

使用 flutter_p2p_plus 插件,你可以发现附近的设备。以下是一个简单的示例:

void discoverPeers() async {
  try {
    List<Peer> peers = await FlutterP2pPlus.discoverPeers();
    for (var peer in peers) {
      print('Discovered peer: ${peer.deviceName}');
    }
  } catch (e) {
    print('Failed to discover peers: $e');
  }
}

4. 连接到设备

发现设备后,你可以选择连接到某个设备:

void connectToPeer(Peer peer) async {
  try {
    await FlutterP2pPlus.connect(peer);
    print('Connected to ${peer.deviceName}');
  } catch (e) {
    print('Failed to connect to peer: $e');
  }
}

5. 发送和接收数据

连接成功后,你可以发送和接收数据。以下是一个简单的示例:

void sendMessage(String message) async {
  try {
    await FlutterP2pPlus.sendMessage(message);
    print('Message sent: $message');
  } catch (e) {
    print('Failed to send message: $e');
  }
}

void receiveMessage() async {
  try {
    String message = await FlutterP2pPlus.receiveMessage();
    print('Message received: $message');
  } catch (e) {
    print('Failed to receive message: $e');
  }
}

6. 断开连接

当你不再需要与设备通信时,可以断开连接:

void disconnect() async {
  try {
    await FlutterP2pPlus.disconnect();
    print('Disconnected from peer');
  } catch (e) {
    print('Failed to disconnect: $e');
  }
}

7. 处理权限

在使用 flutter_p2p_plus 插件时,确保你已经在 AndroidManifest.xmlInfo.plist 中请求了必要的权限。

Android

AndroidManifest.xml 中添加以下权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />

iOS

Info.plist 中添加以下权限:

<key>NSBonjourServices</key>
<array>
    <string>_flutterp2p._tcp</string>
</array>
<key>NSLocalNetworkUsageDescription</key>
<string>We need access to the local network to discover and connect to other devices.</string>

8. 完整示例

以下是一个完整的示例,展示了如何使用 flutter_p2p_plus 插件进行点对点通信:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterP2pPlus.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: P2PExample(),
    );
  }
}

class P2PExample extends StatefulWidget {
  [@override](/user/override)
  _P2PExampleState createState() => _P2PExampleState();
}

class _P2PExampleState extends State<P2PExample> {
  List<Peer> peers = [];
  Peer? connectedPeer;

  void discoverPeers() async {
    try {
      List<Peer> discoveredPeers = await FlutterP2pPlus.discoverPeers();
      setState(() {
        peers = discoveredPeers;
      });
    } catch (e) {
      print('Failed to discover peers: $e');
    }
  }

  void connectToPeer(Peer peer) async {
    try {
      await FlutterP2pPlus.connect(peer);
      setState(() {
        connectedPeer = peer;
      });
      print('Connected to ${peer.deviceName}');
    } catch (e) {
      print('Failed to connect to peer: $e');
    }
  }

  void sendMessage(String message) async {
    try {
      await FlutterP2pPlus.sendMessage(message);
      print('Message sent: $message');
    } catch (e) {
      print('Failed to send message: $e');
    }
  }

  void receiveMessage() async {
    try {
      String message = await FlutterP2pPlus.receiveMessage();
      print('Message received: $message');
    } catch (e) {
      print('Failed to receive message: $e');
    }
  }

  void disconnect() async {
    try {
      await FlutterP2pPlus.disconnect();
      setState(() {
        connectedPeer = null;
      });
      print('Disconnected from peer');
    } catch (e) {
      print('Failed to disconnect: $e');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter P2P Example'),
      ),
      body: Column(
        children: [
          ElevatedButton(
            onPressed: discoverPeers,
            child: Text('Discover Peers'),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: peers.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(peers[index].deviceName),
                  onTap: () => connectToPeer(peers[index]),
                );
              },
            ),
          ),
          if (connectedPeer != null) ...[
            ElevatedButton(
              onPressed: () => sendMessage('Hello, ${connectedPeer!.deviceName}!'),
              child: Text('Send Message'),
            ),
            ElevatedButton(
              onPressed: receiveMessage,
              child: Text('Receive Message'),
            ),
            ElevatedButton(
              onPressed: disconnect,
              child: Text('Disconnect'),
            ),
          ],
        ],
      ),
    );
  }
}
回到顶部