wukong_easy_sdk 1.1.0 copy "wukong_easy_sdk: ^1.1.0" to clipboard
wukong_easy_sdk: ^1.1.0 copied to clipboard

A lightweight Flutter SDK for WuKongIM that enables real-time chat functionality in 5 minutes.

WuKong Easy SDK for Flutter #

pub package License: MIT Flutter

A lightweight, easy-to-use Flutter SDK for WuKongIM that enables real-time messaging functionality in your Flutter applications within minutes.

✨ Features #

  • 🚀 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

📋 Requirements #

📦 Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  wukong_easy_sdk: ^1.1.0

Then run:

flutter pub get

🚀 Quick Start #

Step 1: Import the SDK #

import 'package:wukong_easy_sdk/wukong_easy_sdk.dart';

Step 2: Initialize the SDK #

// 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/pc)
  debugLogging: false,                               // Optional: disabled by default
);

// Get SDK instance and initialize
final easySDK = WuKongEasySDK.getInstance();
await easySDK.init(config);

Diagnostic logging is opt-in. When enabled, the SDK logs protocol stages and whether a request ID is present, but never the ID itself, authentication parameters, message payloads, or raw WebSocket frames. You can route those diagnostics into your own logging system:

final config = WuKongConfig(
  serverUrl: "wss://your-wukongim-server.com/ws",
  uid: "user123",
  token: "your_auth_token",
  debugLogging: true,
  logHandler: (message) => yourLogger.debug(message),
);

Step 3: Set up Event Listeners #

// 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 (Code: ${info.code})");
  // Do not write info.reason to logs; map it to trusted user-facing copy.
});

// Listen for incoming messages
easySDK.addEventListener(WuKongEvent.message, (Message message) {
  print("📨 New message received");
  // Decode and render message.payload only in a trusted UI; do not log it.
});

// Listen for errors
easySDK.addEventListener(WuKongEvent.error, (WuKongError error) {
  print("🚨 SDK error (Code: ${error.code.name})");
  // Keep error.message and error.data out of production logs.
});

Step 4: Connect to Server #

try {
  await easySDK.connect();
  print("🎉 Connected to WuKongIM server!");
} catch (e) {
  print("💥 Connection failed");
  // Handle the error without logging the raw exception.
}

Step 5: Send Messages #

// 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 Sequence: ${result.messageSeq}");
  // Keep the server-provided result.messageId out of application logs.
} catch (e) {
  print("❌ Failed to send message");
  // Report only a fixed category or other explicitly safe metadata.
}

Step 6: Clean Up (Important!) #

@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();
}

📚 Usage #

Complete Example #

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");
      // Do not interpolate the raw exception into application logs.
    }
  }

  void _setupEventListeners() {
    connectListener = (ConnectResult result) {
      setState(() {
        isConnected = true;
      });
      _addMessage("Connected to server!");
    };

    messageListener = (Message message) {
      _addMessage("New message received");
      // Decode message.payload and render it only in the trusted chat UI.
    };

    disconnectListener = (DisconnectInfo info) {
      setState(() {
        isConnected = false;
      });
      _addMessage("Disconnected");
      // Map info.reason to trusted user-facing copy instead of logging it.
    };

    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");
      // Keep the raw exception out of logs and user-visible diagnostics.
    }
  }

  @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...',
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

📖 API Reference #

WuKongEasySDK #

The main SDK class implementing the singleton pattern.

Static Methods

Method Description Returns
getInstance() Get the singleton SDK instance WuKongEasySDK

Instance Methods

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

Properties

Property Type Description
isConnected bool Whether connected to server
isConnecting bool Whether currently connecting
isInitialized bool Whether SDK is initialized

Send Parameters

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
})

Events #

Event Trigger Data Type
WuKongEvent.connect Connection established ConnectResult
WuKongEvent.disconnect Connection lost DisconnectInfo
WuKongEvent.message Message received Message
WuKongEvent.error Error occurred WuKongError
WuKongEvent.sendAck Received message send acknowledgment SendResult
WuKongEvent.reconnecting SDK is attempting to reconnect ReconnectingInfo
WuKongEvent.customEvent Received custom event from server EventNotification

Channel Types #

Type Value Description
WuKongChannelType.person 1 1-on-1 private chat
WuKongChannelType.group 2 Group chat
WuKongChannelType(value) Custom Custom channel type

Data Models #

ConnectResult

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)
}

Message

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
}

SendResult

class SendResult {
  final String messageId;       // Generated message ID
  final int messageSeq;         // Message sequence number
  final int reasonCode;         // Reason code (see WuKongReasonCode)
}

EventNotification

class EventNotification {
  final String id;              // Unique event ID
  final String type;            // Event type
  final int timestamp;          // Event timestamp
  final dynamic data;           // Event data
  final MessageHeader? header;  // Optional message header
}

ReconnectingInfo

class ReconnectingInfo {
  final int attempt;            // Current reconnection attempt count
  final int delay;              // Delay before next attempt (ms)
}

🚨 Error Handling #

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");
    // Fix configuration issues
  } else if (e is WuKongProtocolException) {
    print("🔌 Protocol error");
    // Handle protocol-level errors
  } else if (e is WuKongNetworkException) {
    print("🌐 Network error");
    // Handle network connectivity issues
  } else if (e is WuKongAuthenticationException) {
    print("🔐 Authentication failed");
    // Handle authentication errors
  } else if (e is WuKongConnectionTimeoutException) {
    print("⏰ Connection timeout");
    // Handle timeout scenarios
  } else {
    print("💥 Unexpected error");
    // Handle other errors
  }
}

Exception messages, disconnect reasons, and message payloads may contain server- or user-controlled data. Do not write them directly to production logs; map them to fixed categories and explicitly safe metadata first.

💡 Best Practices #

1. Event Listener Management #

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();
  }
}

2. Connection State Management #

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,
    );
  }
}

3. Message Payload Structure #

// 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
  }
};

📱 Example Application #

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

🔧 Development #

Running Tests #

flutter test

Code Analysis #

flutter analyze

Building Documentation #

dart doc

🌍 Platform Support #

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

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

🤝 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📞 Support #

📊 Changelog #

See CHANGELOG.md for a detailed list of changes and version history.


Made with ❤️ by the WuKongIM team

3
likes
150
points
225
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight Flutter SDK for WuKongIM that enables real-time chat functionality in 5 minutes.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, uuid, web_socket_channel

More

Packages that depend on wukong_easy_sdk