Integrating web socket in flutter

flutter pub add web_socket_channel
flutter pub add intl

Then you typically create a service folder and create a dart file like chat_screen.dart with below code

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart';
import 'dart:async';
import 'package:intl/intl.dart';

class ChatScreen extends StatefulWidget {
  const ChatScreen({super.key});

  @override
  ChatScreenState createState() => ChatScreenState();
}

class ChatScreenState extends State<ChatScreen> {
  final TextEditingController _controller = TextEditingController();
  late IOWebSocketChannel _channel;
  final List<Map<String, dynamic>> _messages = []; // Updated to store Map
  bool _isTryingToReconnect = false;

  int userId = 1; 
  int locationId = 2; 

  @override
  void initState() {
    super.initState();
    _initializeWebSocket();
  }

  void _initializeWebSocket() {
    String url = 'wss://puc.mywebsolutions.co.in:8092?userId=$userId&locationId=$locationId';
    _channel =
        IOWebSocketChannel.connect(url);
    _channel.stream.listen(
        (message) {
          setState(() {
            _messages.add(json.decode(message)); // Decode and add to messages
          });
        },
        onDone: _attemptReconnect,
        onError: (error) {
          _attemptReconnect();
        });
  }

  void _attemptReconnect() {
    if (!_isTryingToReconnect) {
      _isTryingToReconnect = true;
      Timer.periodic(const Duration(seconds: 3), (timer) {
        // Check if the WebSocket is closed
        if (_channel.closeCode != null) {
          print("Attempting to reconnect...");
          _initializeWebSocket();
        } else {
          print("WebSocket is open, stopping reconnection attempts.");
          timer.cancel();
          _isTryingToReconnect = false;
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Chat with Staff'),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemCount: _messages.length,
              itemBuilder: (context, index) {
                final messageData = _messages[index];
                // Using the _formatMessage method to format the message
                return _buildMessageBubble(messageData);
              },
            ),
          ),
          Padding(
  padding: const EdgeInsets.all(8.0),
  child: Row(
    children: [
      Expanded(
        child: TextField(
          controller: _controller,
          decoration: const InputDecoration(
              filled: true, labelText: 'Send a message'),
          onSubmitted: (value) {
            // This gets called when the user presses the Enter key
            if (value.trim().isNotEmpty) {
              _sendMessage(value.trim());
              _controller.clear(); // Clear the text field after sending
            }
          },
          textInputAction: TextInputAction.send, // Changes the Enter key to a Send icon
        ),
      ),
      IconButton(
        icon: const Icon(Icons.send),
        onPressed: () {
          if (_controller.text.trim().isNotEmpty) {
            _sendMessage(_controller.text.trim());
            _controller.clear(); // Clear the text field after sending
          }
        },
      ),
    ],
  ),
),

        ],
      ),
    );
  }

  void _sendMessage(String message) {
    if (message.isNotEmpty) {
      _channel.sink.add(json.encode({
        'text': message,
        'username':'flutter_user1',
        'locationId':locationId,
        'userId':1,
        'senderType':'flutterClient'
        // Add any additional data you need to send
      }));
      setState(() {
        // Simulate a message send by adding it to the message list
        _messages.add({
          'event': 'NewMessage',
          'data': {
            'text': message,            
            'username': 'flutter_user1',
            'user': {
              'name': 'You' // Replace with actual username if available
            }
          }
        });
      });
      _controller.clear(); // Clear the message input field
    }
  }

  Widget _buildMessageBubble(Map<String, dynamic> messageData) {
  final isSentByMe = messageData['data']['username'] == 'flutter_user1';
  final messageText = messageData['data']['text'] ?? 'No text';
  final messageTime = messageData['data']['time']; // Ensure this exists
  final senderName = isSentByMe ? 'Me' : (messageData['data']['username'] ?? 'Unknown');

  return Row(
    mainAxisAlignment: isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start,
    children: [
      Container(
        padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
        margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
        decoration: BoxDecoration(
          color: isSentByMe ? Colors.lightBlue : Colors.grey[300],
          borderRadius: BorderRadius.circular(16),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              '$senderName: $messageText',
              style: TextStyle(color: isSentByMe ? Colors.white : Colors.black),
            ),
            if (messageTime != null)
              Padding(
                padding: const EdgeInsets.only(top: 5),
                child: Text(
                  DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.parse(messageTime)),
                  style: TextStyle(
                    color: Colors.grey[600],
                    fontSize: 10,
                  ),
                ),
              ),
          ],
        ),
      ),
    ],
  );
}


  @override
  void dispose() {
    _channel.sink.close();
    super.dispose();
  }
}

and include this class in main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:livechat/chatnew.dart';
import 'package:livechat/services/notification_service.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Required for async main
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // Initialize Firebase
  NotificationService().init();
  runApp(const MyApp());
  initNotifications();
}

void initNotifications() {
  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
  
  final InitializationSettings initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    
  );
  flutterLocalNotificationsPlugin.initialize(initializationSettings);
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Chat App',
      home: ChatScreen(),
    );
  }
}

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *