Skip to content

WuKongIM/WuKongEasySDK-Flutter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

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.0.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)
);

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

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: ${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}");
});

Step 4: Connect to Server

try {
  await easySDK.connect();
  print("πŸŽ‰ Connected to WuKongIM server!");
} catch (e) {
  print("πŸ’₯ Connection failed: $e");
  // Handle connection error
}

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 ID: ${result.messageId}");
  print("Message Sequence: ${result.messageSeq}");
} catch (e) {
  print("❌ Failed to send message: $e");
}

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

πŸ“– 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

Channel Types

Type Value Description
WuKongChannelType.person 1 1-on-1 private chat
WuKongChannelType.group 2 Group chat

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
}

🚨 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: ${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
  }
}

πŸ’‘ 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

About

WuKongIM Easy SDK for Flutter

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages