socket_io_native_client
Highlight: This plugin implements the official Socket.IO library for Android and iOS, providing better control over socket connections. It also solves the issue of listening to messages emitted in a room, which was not possible with other Socket.IO packages.
A Flutter plugin for Socket.IO client with native platform support for Android and iOS.
Features
- Native Platform Implementation: Built with official Socket.IO libraries for Android and iOS—not a Dart wrapper. Delivers superior performance and full access to native capabilities.
- Background Threading: Native code runs on background threads, keeping the Flutter main thread free and responsive. No UI freezing or jank during socket operations.
- Server Version Independent: Works seamlessly with any Socket.IO server version. No version mismatch issues or compatibility constraints.
- Enhanced Room Support: Solves the limitation of other Socket.IO packages—listen to messages emitted in rooms directly, enabling true room-based real-time communication.
- Real-time Communication: Full Socket.IO client implementation with event-driven architecture
- Comprehensive Configuration: Extensive platform-specific options for iOS and Android with fine-grained control over connection behavior
- Connection Management: Automatic reconnection strategies, configurable reconnection attempts, and connection status monitoring
- Event Handling: Listen to custom events and emit data to the server with automatic serialization
- Advanced Customization: Fine-tune Socket.IO behavior with numerous configuration options unavailable in other packages
- Chat Support: Built-in support for real-time messaging applications with room-based communication patterns
Installation
Add this to your package's pubspec.yaml file:
dependencies:
socket_io_native_client: ^1.1.0
Compatibility
- Dart: 3.6.0+
- Flutter: 3.27.0+
- Android: minSdk 21, Java 11+
- iOS: 15.0+
Platform Setup
Android
Important: For HTTP connections (non-HTTPS), you must add the following to your android/app/src/main/AndroidManifest.xml file in the <application> tag:
<application
android:usesCleartextTraffic="true"
... >
...
</application>
This is essential for connecting to Socket.IO servers over HTTP (like http://localhost:3001 during development).
No additional setup required for the plugin itself. The plugin will automatically configure the native Socket.IO Android library.
iOS
No additional setup required. The plugin will automatically configure the native Socket.IO iOS library.
Usage
Basic Connection
Note: SocketIoNative implements a singleton pattern. Multiple calls to SocketIoNative() will return the same instance, ensuring only one Socket.IO connection exists throughout your app.
import 'package:socket_io_native_client/socket_io_native_client.dart';
class MySocketService {
final SocketIoNative _socket = SocketIoNative(); // Always returns the same instance
Future<void> connect() async {
await _socket.connect(
'http://localhost:3001',
onSocketIdReceived: (socketId) {
print('Connected with ID: $socketId');
},
extraOptions: SocketConnectionOptions(
transports: ['websocket'],
reconnection: true,
reconnectionAttempts: 10,
timeout: 10000,
),
);
}
}
Listening to Events
// Listen to custom events
await _socket.on('message', (data) {
print('Received message: $data');
});
// Listen to connection status changes
_socket.statusStream.listen((status) {
switch (status) {
case ConnectionStatus.connected:
print('Socket connected');
break;
case ConnectionStatus.disconnected:
print('Socket disconnected');
break;
case ConnectionStatus.connecting:
print('Socket connecting...');
break;
case ConnectionStatus.error:
print('Socket error occurred');
break;
}
});
Emitting Events
// Send a simple message
await _socket.emit('message', 'Hello Server!');
// Send complex data
await _socket.emit('user_action', {
'action': 'join_room',
'room': 'general',
'userId': 'user123',
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
Connection Callbacks
// Set up connection callbacks
_socket.onConnected(() {
print('Successfully connected to server');
});
_socket.onDisconnected(() {
print('Disconnected from server');
});
_socket.onError((reason) {
print('Connection error: $reason');
});
Advanced Configuration
await _socket.connect(
'https://your-server.com',
onSocketIdReceived: (socketId) => print('ID: $socketId'),
extraOptions: SocketConnectionOptions(
// Common options
path: '/socket.io/',
transports: ['websocket', 'polling'],
reconnection: true,
reconnectionAttempts: -1, // Infinite
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
randomizationFactor: 0.5,
timeout: 20000,
forceNew: true,
secure: true,
// Authentication
auth: {
'token': 'your-auth-token',
'userId': 'user123',
},
// Query parameters
query: {
'version': '1.0',
'platform': 'flutter',
},
// iOS-specific options
extraIOSConfig: ExtraIOSSocketOptions(
log: true,
compress: true,
forceWebsockets: true,
extraHeaders: {
'Authorization': 'Bearer token',
'Custom-Header': 'value',
},
),
// Android-specific options
androidConfig: ExtraAndroidSocketOptions(
extraHeaders: {
'Authorization': ['Bearer token'],
'Custom-Header': ['value'],
},
),
),
);
Chat Application Example
class ChatService {
final SocketIoNative _socket = SocketIoNative();
String? _currentRoom;
Future<void> joinChat(String serverUrl, String username) async {
await _socket.connect(
serverUrl,
onSocketIdReceived: (socketId) {
print('Chat connected: $socketId');
},
);
// Listen for incoming messages
await _socket.on('receive_message', (data) {
final message = ChatMessage.fromMap(data);
// Handle received message
onMessageReceived(message);
});
// Listen for room notifications
await _socket.on('room_notification', (data) {
print('Room update: $data');
});
}
Future<void> joinRoom(String roomName) async {
_currentRoom = roomName;
await _socket.emit('join_room', {
'room': roomName,
'username': 'current_user',
});
}
Future<void> sendMessage(String message) async {
if (_currentRoom != null) {
await _socket.emit('send_message', {
'room': _currentRoom,
'message': message,
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
}
}
void onMessageReceived(ChatMessage message) {
// Update UI with new message
}
Future<void> disconnect() async {
await _socket.off('receive_message');
await _socket.off('room_notification');
await _socket.disconnect();
_socket.dispose();
}
}
Singleton Pattern Usage
// These all return the same instance
final socket1 = SocketIoNative();
final socket2 = SocketIoNative();
print(identical(socket1, socket2)); // true
// Check if instance exists without creating one
if (SocketIoNative.instance != null) {
print('Socket instance already exists');
}
// Completely destroy the singleton (rarely needed)
SocketIoNative.destroyInstance(); // Disconnects and cleans up
final newSocket = SocketIoNative(); // Creates fresh instance
Cleanup
Always dispose of the socket service when done:
@override
void dispose() {
// Remove specific event listeners
_socket.off('message');
_socket.off('custom_event');
// Disconnect from server
_socket.disconnect();
// Clean up resources (or use destroyInstance for complete cleanup)
_socket.dispose();
super.dispose();
}
API Reference
SocketIoNative
| Method | Description |
|---|---|
connect(url, {onSocketIdReceived, extraOptions}) |
Connect to Socket.IO server |
on(eventName, callback) |
Listen to a specific event |
off(eventName) |
Stop listening to an event |
emit(eventName, data) |
Send an event to the server |
disconnect() |
Disconnect from server |
dispose() |
Clean up all resources |
onConnected(callback) |
Set callback for connection |
onDisconnected(callback) |
Set callback for disconnection |
onError(callback) |
Set callback for errors |
SocketConnectionOptions
Comprehensive configuration options for Socket.IO connection with platform-specific settings.
ConnectionStatus
Enum representing socket connection states:
connecting- Socket is attempting to connectconnected- Socket is successfully connecteddisconnected- Socket is disconnectederror- Socket encountered an error
Example App
The example app demonstrates:
- Real-time server connection
- 1-on-1 chat functionality
- Connection status monitoring
- Event emission and listening
- Proper resource cleanup
Run the example:
cd example
flutter run
Contributing
Contributions are welcome! Please read the contributing guidelines before submitting pull requests.
License
This project is licensed under the MIT License - see the LICENSE file for details.