A lightweight, easy-to-use Flutter SDK for WuKongIM that enables real-time messaging functionality in your Flutter applications within minutes.
- π Quick Integration: Get started in under 5 minutes
- π Auto Reconnection: Built-in intelligent reconnection with exponential backoff
- π± Cross Platform: Works seamlessly on iOS, Android, Web, and Desktop
- π― Type Safe: Full Dart type safety with null safety support
- π§ Easy to Use: Simple and intuitive API design
- π¦ Lightweight: Minimal dependencies (only 2 external packages)
- π¨ Event-Driven: Reactive programming with event listeners
- π Secure: WebSocket with authentication support
- π Real-time: Instant message delivery and status updates
- Flutter 3.0.0 or higher
- Dart 3.0.0 or higher
- A running WuKongIM server
Add this to your package's pubspec.yaml
file:
dependencies:
wukong_easy_sdk: ^1.0.0
Then run:
flutter pub get
import 'package:wukong_easy_sdk/wukong_easy_sdk.dart';
// Create configuration
final config = WuKongConfig(
serverUrl: "ws://your-wukongim-server.com:5200", // Your WuKongIM server URL
uid: "user123", // Unique user identifier
token: "your_auth_token", // Authentication token
deviceId: "device_001", // Optional: Device identifier
deviceFlag: WuKongDeviceFlag.app, // Optional: Device type (app/web)
);
// Get SDK instance and initialize
final easySDK = WuKongEasySDK.getInstance();
await easySDK.init(config);
// Listen for connection events
easySDK.addEventListener(WuKongEvent.connect, (ConnectResult result) {
print("β
Connected successfully!");
print("Server version: ${result.serverVersion}");
print("Time difference: ${result.timeDiff}ms");
});
easySDK.addEventListener(WuKongEvent.disconnect, (DisconnectInfo info) {
print("β Disconnected: ${info.reason} (Code: ${info.code})");
});
// Listen for incoming messages
easySDK.addEventListener(WuKongEvent.message, (Message message) {
print("π¨ New message from ${message.fromUid}:");
print("Content: ${message.payload}");
print("Channel: ${message.channelId}");
});
// Listen for errors
easySDK.addEventListener(WuKongEvent.error, (WuKongError error) {
print("π¨ Error: ${error.message}");
});
try {
await easySDK.connect();
print("π Connected to WuKongIM server!");
} catch (e) {
print("π₯ Connection failed: $e");
// Handle connection error
}
// Create message payload
final messagePayload = {
"type": 1, // Message type (1 = text)
"content": "Hello from Flutter!", // Message content
"timestamp": DateTime.now().millisecondsSinceEpoch,
};
try {
final result = await easySDK.send(
channelId: "friend_user_id", // Target user/channel ID
channelType: WuKongChannelType.person, // Channel type (person/group)
payload: messagePayload, // Message data
);
print("β
Message sent successfully!");
print("Message ID: ${result.messageId}");
print("Message Sequence: ${result.messageSeq}");
} catch (e) {
print("β Failed to send message: $e");
}
@override
void dispose() {
// Remove event listeners
easySDK.removeEventListener(WuKongEvent.connect, connectListener);
easySDK.removeEventListener(WuKongEvent.message, messageListener);
// Disconnect and dispose
easySDK.disconnect();
easySDK.dispose();
super.dispose();
}
Here's a complete example of integrating WuKong Easy SDK in a Flutter app:
import 'package:flutter/material.dart';
import 'package:wukong_easy_sdk/wukong_easy_sdk.dart';
class ChatPage extends StatefulWidget {
@override
_ChatPageState createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
late WuKongEasySDK easySDK;
bool isConnected = false;
List<String> messages = [];
// Event listener references
WuKongEventListener<ConnectResult>? connectListener;
WuKongEventListener<Message>? messageListener;
WuKongEventListener<DisconnectInfo>? disconnectListener;
@override
void initState() {
super.initState();
_initializeSDK();
}
Future<void> _initializeSDK() async {
easySDK = WuKongEasySDK.getInstance();
// Configure SDK
final config = WuKongConfig(
serverUrl: "ws://localhost:5200",
uid: "flutter_user",
token: "your_token_here",
);
await easySDK.init(config);
_setupEventListeners();
// Connect to server
try {
await easySDK.connect();
} catch (e) {
print("Connection failed: $e");
}
}
void _setupEventListeners() {
connectListener = (ConnectResult result) {
setState(() {
isConnected = true;
});
_addMessage("Connected to server!");
};
messageListener = (Message message) {
_addMessage("${message.fromUid}: ${message.payload}");
};
disconnectListener = (DisconnectInfo info) {
setState(() {
isConnected = false;
});
_addMessage("Disconnected: ${info.reason}");
};
easySDK.addEventListener(WuKongEvent.connect, connectListener!);
easySDK.addEventListener(WuKongEvent.message, messageListener!);
easySDK.addEventListener(WuKongEvent.disconnect, disconnectListener!);
}
void _addMessage(String message) {
setState(() {
messages.add(message);
});
}
Future<void> _sendMessage(String content) async {
if (!isConnected) return;
try {
await easySDK.send(
channelId: "test_channel",
channelType: WuKongChannelType.person,
payload: {"type": 1, "content": content},
);
_addMessage("You: $content");
} catch (e) {
_addMessage("Failed to send: $e");
}
}
@override
void dispose() {
// Clean up event listeners
if (connectListener != null) {
easySDK.removeEventListener(WuKongEvent.connect, connectListener!);
}
if (messageListener != null) {
easySDK.removeEventListener(WuKongEvent.message, messageListener!);
}
if (disconnectListener != null) {
easySDK.removeEventListener(WuKongEvent.disconnect, disconnectListener!);
}
easySDK.disconnect();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WuKong Chat'),
backgroundColor: isConnected ? Colors.green : Colors.red,
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(messages[index]),
);
},
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
onSubmitted: _sendMessage,
decoration: InputDecoration(
hintText: 'Type a message...',
),
),
),
],
),
),
],
),
);
}
}
The main SDK class implementing the singleton pattern.
Method | Description | Returns |
---|---|---|
getInstance() |
Get the singleton SDK instance | WuKongEasySDK |
Method | Parameters | Description | Returns |
---|---|---|---|
init(config) |
WuKongConfig config |
Initialize SDK with configuration | Future<void> |
connect() |
None | Connect to WuKongIM server | Future<void> |
disconnect() |
None | Disconnect from server | void |
send() |
See Send Parameters | Send a message | Future<SendResult> |
addEventListener() |
WuKongEvent event, Function listener |
Add event listener | void |
removeEventListener() |
WuKongEvent event, Function listener |
Remove event listener | void |
dispose() |
None | Clean up all resources | void |
Property | Type | Description |
---|---|---|
isConnected |
bool |
Whether connected to server |
isConnecting |
bool |
Whether currently connecting |
isInitialized |
bool |
Whether SDK is initialized |
Future<SendResult> send({
required String channelId, // Target channel/user ID
required WuKongChannelType channelType, // Channel type
required dynamic payload, // Message payload
String? clientMsgNo, // Optional: Client message number
Map<String, dynamic>? header, // Optional: Message headers
String? topic, // Optional: Message topic
dynamic setting, // Optional: Message settings
})
Event | Trigger | Data Type |
---|---|---|
WuKongEvent.connect |
Connection established | ConnectResult |
WuKongEvent.disconnect |
Connection lost | DisconnectInfo |
WuKongEvent.message |
Message received | Message |
WuKongEvent.error |
Error occurred | WuKongError |
Type | Value | Description |
---|---|---|
WuKongChannelType.person |
1 | 1-on-1 private chat |
WuKongChannelType.group |
2 | Group chat |
class ConnectResult {
final String? serverKey; // Server encryption key (optional)
final String? salt; // Encryption salt (optional)
final int timeDiff; // Time difference with server (ms)
final int reasonCode; // Connection reason code
final int? serverVersion; // Server version (optional)
final int? nodeId; // Server node ID (optional)
}
class Message {
final String messageId; // Unique message ID
final int messageSeq; // Message sequence number
final String fromUid; // Sender user ID
final String channelId; // Channel/conversation ID
final int channelType; // Channel type
final dynamic payload; // Message content
final int timestamp; // Message timestamp
final MessageHeader header; // Message headers
}
class SendResult {
final String messageId; // Generated message ID
final int messageSeq; // Message sequence number
}
The SDK provides specific exception types for different error scenarios:
try {
await easySDK.send(
channelId: "user123",
channelType: WuKongChannelType.person,
payload: {"type": 1, "content": "Hello!"},
);
} catch (e) {
if (e is WuKongNotConnectedException) {
print("β Not connected to server");
// Show connection error to user
} else if (e is WuKongConfigurationException) {
print("βοΈ Configuration error: ${e.message}");
// Fix configuration issues
} else if (e is WuKongProtocolException) {
print("π Protocol error: ${e.message}");
// Handle protocol-level errors
} else if (e is WuKongNetworkException) {
print("π Network error: ${e.message}");
// Handle network connectivity issues
} else if (e is WuKongAuthenticationException) {
print("π Authentication failed: ${e.message}");
// Handle authentication errors
} else if (e is WuKongConnectionTimeoutException) {
print("β° Connection timeout: ${e.message}");
// Handle timeout scenarios
} else {
print("π₯ Unexpected error: $e");
// Handle other errors
}
}
Always store references to your event listeners for proper cleanup:
class _ChatPageState extends State<ChatPage> {
late WuKongEasySDK easySDK;
WuKongEventListener<Message>? messageListener;
WuKongEventListener<ConnectResult>? connectListener;
@override
void initState() {
super.initState();
easySDK = WuKongEasySDK.getInstance();
_setupListeners();
}
void _setupListeners() {
messageListener = (Message message) {
if (mounted) {
setState(() {
// Handle message safely
});
}
};
connectListener = (ConnectResult result) {
if (mounted) {
// Handle connection
}
};
easySDK.addEventListener(WuKongEvent.message, messageListener!);
easySDK.addEventListener(WuKongEvent.connect, connectListener!);
}
@override
void dispose() {
// Always clean up listeners
if (messageListener != null) {
easySDK.removeEventListener(WuKongEvent.message, messageListener!);
}
if (connectListener != null) {
easySDK.removeEventListener(WuKongEvent.connect, connectListener!);
}
super.dispose();
}
}
class ConnectionManager {
static bool _isConnected = false;
static bool get isConnected => _isConnected;
static Future<void> ensureConnection() async {
final sdk = WuKongEasySDK.getInstance();
if (!sdk.isConnected) {
try {
await sdk.connect();
_isConnected = true;
} catch (e) {
_isConnected = false;
throw e;
}
}
}
static Future<void> sendMessage(String channelId, dynamic payload) async {
await ensureConnection();
final sdk = WuKongEasySDK.getInstance();
await sdk.send(
channelId: channelId,
channelType: WuKongChannelType.person,
payload: payload,
);
}
}
// Recommended message payload structure
final messagePayload = {
"type": 1, // Message type (1=text, 2=image, etc.)
"content": "Hello, World!", // Message content
"timestamp": DateTime.now().millisecondsSinceEpoch,
"extra": { // Optional extra data
"mentions": ["user123"], // Mentioned users
"reply_to": "message_id_123", // Reply to message
}
};
This SDK includes a complete example application demonstrating all features:
cd example
flutter run
The example app includes:
- β Connection management with visual status
- β Real-time messaging interface
- β Event logging and debugging
- β Error handling demonstrations
- β Modern Material Design 3 UI
flutter test
flutter analyze
dart doc
Platform | Status | Notes |
---|---|---|
Android | β Supported | Android 5.0+ (API 21+) |
iOS | β Supported | iOS 11.0+ |
Web | β Supported | Modern browsers with WebSocket support |
macOS | β Supported | macOS 10.14+ |
Windows | β Supported | Windows 10+ |
Linux | β Supported | Modern Linux distributions |
This project is licensed under the MIT License - see the LICENSE file for details.
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.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
- π Documentation: API Reference
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π WuKongIM: Official Website
See CHANGELOG.md for a detailed list of changes and version history.
Made with β€οΈ by the WuKongIM team