wifi_direct_plugin 0.0.4
wifi_direct_plugin: ^0.0.4 copied to clipboard
A comprehensive Flutter plugin for WiFi Direct (P2P) communication with real-time messaging, file transfer, and cross-platform support for Android and iOS.
WiFi Direct Plugin #
A comprehensive Flutter plugin for WiFi Direct (P2P) communication, enabling direct device-to-device connections without requiring internet access. Perfect for building offline chat applications, file sharing tools, and collaborative apps.
🚀 Features #
✨ Core Functionality #
- 📱 Cross-Platform Support: Android (WiFi Direct) & iOS (MultipeerConnectivity)
- 🔗 P2P Connection: Direct device-to-device communication without internet
- 💬 Real-time Messaging: Instant text message exchange
- 📁 File Transfer: Send any file type with progress tracking
- 📸 Image Sharing: Camera capture and gallery selection
- 🔄 Auto-Discovery: Automatic peer detection and connection
⚡ Advanced Features #
- 📊 Progress Tracking: Real-time upload/download progress for both sender and receiver
- 🔒 Data Integrity: MD5 checksum verification for file transfers
- 💾 Smart Storage: Automatic saving to Downloads folder with duplicate handling
- 🔄 Auto-Reconnection: Intelligent connection recovery mechanisms
- 🎯 Connection Management: Host/Client roles with seamless switching
- ⚠️ Error Handling: Comprehensive error detection and recovery
📱 Platform Support #
| Platform | Implementation | Minimum Version |
|---|---|---|
| Android | WiFi Direct (P2P) API | API 16+ (Android 4.1+) |
| iOS | MultipeerConnectivity | iOS 9.0+ |
| Flutter | EventChannel & MethodChannel | 3.0.0+ |
🏗️ Installation #
Add this to your package's pubspec.yaml file:
dependencies:
wifi_direct_plugin: ^0.0.1
Then run:
flutter pub get
⚙️ Setup #
Android Configuration #
Add the following permissions to your android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.wifi.direct" android:required="true" />
iOS Configuration #
Add the following to your ios/Runner/Info.plist:
<key>NSLocalNetworkUsageDescription</key>
<string>This app needs to access your local network for WiFi Direct communication</string>
<key>NSBonjourServices</key>
<array>
<string>_wifi-direct._tcp</string>
<string>_wifi-direct._udp</string>
</array>
🚀 Quick Start #
1. Initialize the Plugin #
import 'package:wifi_direct_plugin/wifi_direct_plugin.dart';
// Initialize WiFi Direct
bool success = await WifiDirectPlugin.initialize();
if (success) {
print('WiFi Direct initialized successfully!');
}
2. Start as Host (Server) #
// Start as host to create a group
bool started = await WifiDirectPlugin.startAsServer(
deviceName: "My Awesome Device"
);
if (started) {
print('Host started! Waiting for connections...');
}
3. Join as Client #
// Start as client and discover devices
await WifiDirectPlugin.startAsClient(deviceName: "Client Device");
await WifiDirectPlugin.startDiscovery();
// Listen for discovered peers
WifiDirectPlugin.peersStream.listen((peers) {
for (var peer in peers) {
print('Found device: ${peer.deviceName}');
}
});
// Connect to a device
await WifiDirectPlugin.connect(deviceAddress);
4. Send Messages and Files #
// Send text message
await WifiDirectPlugin.sendText("Hello, World!");
// Send file
await WifiDirectPlugin.sendFile("/path/to/document.pdf");
// Send image
await WifiDirectPlugin.sendImage("/path/to/photo.jpg");
5. Handle Incoming Data #
// Set up callbacks for received data
WifiDirectPlugin.onTextReceived = (text) {
print('Received message: $text');
};
WifiDirectPlugin.onFileReceived = (file) {
print('Received file: ${file.path}');
};
WifiDirectPlugin.onImageReceived = (image) {
print('Received image: ${image.path}');
};
// Track transfer progress
WifiDirectPlugin.onFileProgress = (fileName, progress) {
print('Receiving $fileName: ${(progress * 100).toInt()}%');
};
WifiDirectPlugin.onSendProgress = (fileName, progress) {
print('Sending $fileName: ${(progress * 100).toInt()}%');
};
🎯 Complete Example #
Here's a complete example of a simple chat application:
import 'package:flutter/material.dart';
import 'package:wifi_direct_plugin/wifi_direct_plugin.dart';
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _messageController = TextEditingController();
final List<String> _messages = [];
bool _isConnected = false;
@override
void initState() {
super.initState();
_initializeWifiDirect();
}
Future<void> _initializeWifiDirect() async {
await WifiDirectPlugin.initialize();
// Set up message receiver
WifiDirectPlugin.onTextReceived = (text) {
setState(() {
_messages.add('Received: $text');
});
};
// Listen for connection changes
WifiDirectPlugin.connectionStream.listen((info) {
setState(() {
_isConnected = info.isConnected;
});
});
}
Future<void> _sendMessage() async {
final message = _messageController.text.trim();
if (message.isNotEmpty && _isConnected) {
await WifiDirectPlugin.sendText(message);
setState(() {
_messages.add('Sent: $message');
_messageController.clear();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_isConnected ? 'Connected' : 'Disconnected'),
backgroundColor: _isConnected ? Colors.green : Colors.red,
),
body: Column(
children: [
// Connection buttons
if (!_isConnected) ...[
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () => WifiDirectPlugin.startAsServer(),
child: Text('Host'),
),
),
SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: () async {
await WifiDirectPlugin.startAsClient();
await WifiDirectPlugin.startDiscovery();
},
child: Text('Join'),
),
),
],
),
],
// Messages list
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_messages[index]),
);
},
),
),
// Message input
if (_isConnected)
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _messageController,
decoration: InputDecoration(
hintText: 'Type a message...',
border: OutlineInputBorder(),
),
onSubmitted: (_) => _sendMessage(),
),
),
SizedBox(width: 8),
IconButton(
onPressed: _sendMessage,
icon: Icon(Icons.send),
),
],
),
),
],
),
);
}
@override
void dispose() {
WifiDirectPlugin.dispose();
super.dispose();
}
}
📚 API Reference #
Core Methods #
| Method | Description | Returns |
|---|---|---|
initialize() |
Initialize WiFi Direct | Future<bool> |
startAsServer({String? deviceName}) |
Start as host/server | Future<bool> |
startAsClient({String? deviceName}) |
Start as client | Future<bool> |
startDiscovery() |
Begin peer discovery | Future<bool> |
stopDiscovery() |
Stop peer discovery | Future<bool> |
connect(String deviceAddress) |
Connect to peer | Future<bool> |
disconnect() |
Disconnect from peer | Future<bool> |
Messaging & Transfer #
| Method | Description | Returns |
|---|---|---|
sendText(String text) |
Send text message | Future<bool> |
sendFile(String filePath) |
Send file | Future<bool> |
sendImage(String imagePath) |
Send image | Future<bool> |
Event Streams #
| Stream | Description | Data Type |
|---|---|---|
peersStream |
Discovered peers | Stream<List<WifiDirectDevice>> |
connectionStream |
Connection status | Stream<WifiDirectConnectionInfo> |
Callbacks #
| Callback | Description | Parameters |
|---|---|---|
onTextReceived |
Text message received | String text |
onFileReceived |
File received | File file |
onImageReceived |
Image received | File image |
onFileProgress |
Receive progress | String fileName, double progress |
onSendProgress |
Send progress | String fileName, double progress |
🔧 Advanced Configuration #
Connection Management #
// Monitor connection state
WifiDirectPlugin.connectionStream.listen((info) {
print('Connected: ${info.isConnected}');
print('Is Group Owner: ${info.isGroupOwner}');
print('Group Owner Address: ${info.groupOwnerAddress}');
});
// Handle peer discovery
WifiDirectPlugin.peersStream.listen((peers) {
for (var peer in peers) {
print('Device: ${peer.deviceName} (${peer.deviceAddress})');
}
});
File Transfer with Progress #
// Track upload progress
WifiDirectPlugin.onSendProgress = (fileName, progress) {
print('Uploading $fileName: ${(progress * 100).toInt()}%');
};
// Track download progress
WifiDirectPlugin.onFileProgress = (fileName, progress) {
print('Downloading $fileName: ${(progress * 100).toInt()}%');
};
// Handle completed transfers
WifiDirectPlugin.onFileReceived = (file) async {
// Save to Downloads folder
String? savedPath = await FileService.saveFileToDownloads(
file,
file.path.split('/').last
);
print('File saved to: $savedPath');
};
🎨 UI Components #
The plugin includes pre-built UI components for quick integration:
- ConnectionInfo: Shows current connection status
- PeerList: Displays discovered devices
- FileProgress: Shows transfer progress
- MessageBubble: Chat message display
- InputArea: Message input with file/image buttons
⚠️ Important Notes #
Android Considerations #
- Permissions: Location permission is required for WiFi Direct discovery
- WiFi State: Device WiFi must be enabled
- Background: File transfers may be interrupted if app goes to background
- Device Compatibility: Some manufacturers may have WiFi Direct limitations
iOS Considerations #
- Proximity: Devices must be in close proximity for MultipeerConnectivity
- Privacy: Users will see connection prompts
- Background: Limited background execution capabilities
Performance Tips #
- File Size: Large files are automatically chunked for efficient transfer
- Network Quality: Transfer speed depends on WiFi Direct connection quality
- Memory: Plugin efficiently manages memory for large file transfers
- Battery: Continuous discovery can drain battery
🐛 Troubleshooting #
Common Issues #
Connection fails on Android:
- Ensure location permission is granted
- Check if WiFi is enabled
- Try restarting WiFi Direct discovery
iOS devices not discovering each other:
- Ensure devices are close to each other
- Check Bluetooth and WiFi are enabled
- Restart the app if needed
File transfer is slow:
- WiFi Direct speed varies by device and distance
- Close other network-intensive apps
- Ensure devices are close to each other
Permission errors:
- Check all required permissions are added to AndroidManifest.xml
- Request runtime permissions properly
- Test on different Android versions
🤝 Contributing #
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments #
- Flutter team for the excellent plugin architecture
- Android WiFi Direct API documentation
- iOS MultipeerConnectivity framework
- Open source community for inspiration and feedback
📞 Support #
- Examples: Check the
/examplefolder for complete sample apps
Made with ❤️ for the Flutter community