chat_call_core 0.3.6+3 copy "chat_call_core: ^0.3.6+3" to clipboard
chat_call_core: ^0.3.6+3 copied to clipboard

Chat Call Core ADVN

Chat Call Core #

Tổng quan #

Chat Call Core là một thư viện giao tiếp toàn diện cho các ứng dụng Flutter, cung cấp khả năng gọi video/âm thanh mạnh mẽ. Nó tích hợp nhiều công nghệ để tạo ra trải nghiệm gọi điện liền mạch trên các nền tảng khác nhau với các triển khai khác nhau cho Android (Firebase) và iOS (VoIP).

Kiến trúc #

Hệ thống sử dụng kiến trúc đa tầng để xử lý cuộc gọi:

  1. Tầng thông báo: Sử dụng Firebase Cloud Messaging (FCM) trên Android và thông báo VoIP trên iOS
  2. Tầng Call Kit: Sử dụng FlutterCallkitIncoming để hiển thị giao diện gọi điện native
  3. Tầng kết nối: Sử dụng LiveKit cho giao tiếp thời gian thực
  4. Tầng UI: Các thành phần UI Flutter tùy chỉnh cho màn hình cuộc gọi

Các thành phần chính #

Call Page (call_page.dart) #

Thành phần UI chính hiển thị giao diện cuộc gọi với:

  • Luồng video cho người tham gia
  • Điều khiển cuộc gọi (tắt tiếng, chuyển đổi camera, loa, v.v.)
  • Quản lý trạng thái cuộc gọi
  • Bộ đếm thời gian cuộc gọi

Call Bloc (call_bloc.dart) #

Quản lý trạng thái cho cuộc gọi sử dụng mẫu BLoC:

  • Xử lý việc tạo/tham gia phòng gọi
  • Quản lý cập nhật trạng thái cuộc gọi
  • Xử lý các sự kiện cuộc gọi

Socket Manager (socket_manager.dart) #

Quản lý kết nối WebSocket cho giao tiếp thời gian thực:

  • Xử lý duy trì kết nối
  • Quản lý sự hiện diện của người dùng
  • Xử lý các sự kiện nhắn tin
  • Xử lý tín hiệu cuộc gọi

Call Helper (call_helper.dart) #

Tiện ích cốt lõi điều phối toàn bộ luồng cuộc gọi:

  • Khởi tạo FCM và các trình nghe cuộc gọi
  • Xử lý các sự kiện cuộc gọi từ Firebase/VoIP
  • Quản lý trạng thái cuộc gọi
  • Điều phối giữa hệ thống thông báo và UI

Luồng cuộc gọi #

Luồng cuộc gọi đến #

  1. Nhận thông báo:

    • Android: Nhận thông báo FCM với chi tiết cuộc gọi
    • iOS: Nhận thông báo VoIP
  2. Kích hoạt Call Kit:

    • NotificationHelper.isNotifyCall() xác định xem thông báo có phải là cuộc gọi không
    • FlutterCallkitIncoming.showCallkitIncoming() được kích hoạt để hiển thị giao diện cuộc gọi native
  3. Xử lý hành động người dùng:

    • handleListenerStatusEvent() xử lý hành động của người dùng (chấp nhận/từ chối)
    • Trạng thái cuộc gọi được cập nhật tương ứng
  4. Kết nối cuộc gọi:

    • Khi chấp nhận cuộc gọi, ứng dụng kết nối với phòng LiveKit
    • connectRoomLiveKit() thiết lập kết nối media
    • Giao diện cuộc gọi được hiển thị và người tham gia được kết nối

Luồng cuộc gọi đi #

  1. Khởi tạo cuộc gọi:

    • CallRoomEvent được gửi đi để tạo phòng
    • Máy chủ trả về token phòng và ID cuộc gọi
  2. Tín hiệu cuộc gọi:

    • Trạng thái cuộc gọi được gửi đến người nhận qua FCM/VoIP
    • Thiết bị của người nhận hiển thị giao diện cuộc gọi đến
  3. Kết nối phòng:

    • Người dùng local kết nối với phòng LiveKit
    • Luồng media được phát
    • UI cập nhật để hiển thị trạng thái đã kết nối

Kết thúc cuộc gọi #

  1. Kích hoạt ngắt kết nối:

    • Người dùng kết thúc cuộc gọi hoặc xảy ra lỗi kết nối
    • disconnectRoom() được gọi với trạng thái thích hợp
  2. Cập nhật trạng thái:

    • sendUpdateStatusFinish() thông báo cho máy chủ về việc kết thúc cuộc gọi
    • removeCallHandle() dọn dẹp call kit
  3. Dọn dẹp phòng:

    • Phòng LiveKit bị ngắt kết nối
    • UI trở về trạng thái trước đó

Quản lý trạng thái #

Hệ thống sử dụng mô hình máy trạng thái cho trạng thái cuộc gọi:

  • actionCallIncoming: Cuộc gọi đang đến nhưng chưa được trả lời
  • actionCallStart: Cuộc gọi đã bắt đầu và đang kết nối
  • actionCallAccept: Cuộc gọi đã được chấp nhận
  • actionCallDecline: Cuộc gọi đã bị từ chối
  • actionCallEnd: Cuộc gọi đã kết thúc
  • actionCallError: Đã xảy ra lỗi trong cuộc gọi

Sự khác biệt giữa các nền tảng #

Android #

  • Sử dụng Firebase Cloud Messaging cho thông báo
  • Xử lý thông báo nền qua trình xử lý nền Firebase
  • Hiển thị giao diện cuộc gọi native qua FlutterCallkitIncoming

iOS #

  • Sử dụng thông báo VoIP cho cuộc gọi đến
  • Sử dụng ReplayKit cho chia sẻ màn hình
  • Có xử lý vị trí camera cụ thể

Đề xuất phát triển #

Cải thiện cấu trúc mã #

  1. Tách biệt các mối quan tâm:

    • Tách mã đặc thù cho từng nền tảng thành các lớp riêng biệt
    • Tạo các giao diện rõ ràng cho mỗi thành phần
  2. Giảm mã trùng lặp:

    • Tạo tiện ích dùng chung cho các chức năng chung
    • Triển khai xử lý lỗi nhất quán
  3. Quản lý trạng thái:

    • Đơn giản hóa chuyển đổi trạng thái
    • Triển khai mô hình máy trạng thái rõ ràng hơn

Cải thiện tính năng #

  1. Khả năng phục hồi mạng:

    • Cải thiện xử lý kết nối lại
    • Thêm chỉ báo trạng thái mạng tốt hơn
  2. Chất lượng cuộc gọi:

    • Triển khai chất lượng luồng thích ứng
    • Thêm thống kê để giám sát chất lượng cuộc gọi
  3. UI/UX:

    • Đơn giản hóa giao diện gọi điện
    • Thêm tính năng trợ năng

Đơn giản hóa mã #

  1. Cấu trúc lại Call Helper:

    • Chia thành các lớp nhỏ hơn, tập trung
    • Sử dụng dependency injection để dễ kiểm thử hơn
  2. Dọn dẹp CallBloc:

    • Tách các sự kiện và trạng thái thành các tệp khác nhau
    • Sử dụng sealed classes để có tính an toàn kiểu tốt hơn
  3. Đơn giản hóa logic kết nối:

    • Tạo dịch vụ kết nối riêng biệt
    • Triển khai chiến lược thử lại với hệ số tăng theo cấp số nhân

Workflow Test Call #

Workflow tự động gửi log kết quả test call qua Microsoft Teams #

Để theo dõi và báo cáo kết quả kiểm thử cuộc gọi một cách tự động thông qua Microsoft Teams, thực hiện theo các bước sau:

1. Cài đặt Webhook trong Microsoft Teams

  1. Tạo Incoming Webhook:
    • Mở Microsoft Teams và truy cập kênh cần nhận thông báo
    • Chọn ... bên cạnh kênh > Connectors
    • Tìm và chọn Incoming Webhook > Configure
    • Đặt tên cho webhook, tải lên icon (tùy chọn) và chọn Create
    • Sao chép URL webhook được tạo ra

2. Tích hợp trong mã nguồn

// file: lib/core/utils/teams_logger.dart
import 'dart:convert';
import 'package:http/http.dart' as http;

class TeamsLogger {
  final String webhookUrl;
  
  TeamsLogger({required this.webhookUrl});
  
  Future<bool> logCallTest({
    required String testId,
    required String scenario,
    required String deviceA,
    required String deviceB,
    required bool success,
    String? errorMessage,
    Map<String, dynamic>? additionalData,
  }) async {
    final timestamp = DateTime.now().toIso8601String();
    
    final payload = {
      'type': 'MessageCard',
      'context': 'http://schema.org/extensions',
      'themeColor': success ? '00FF00' : 'FF0000',
      'summary': 'Kết quả test cuộc gọi: $testId',
      'sections': [
        {
          'activityTitle': 'Test Call: $testId',
          'activitySubtitle': timestamp,
          'facts': [
            {'name': 'ID Test', 'value': testId},
            {'name': 'Kịch bản', 'value': scenario},
            {'name': 'Thiết bị gọi', 'value': deviceA},
            {'name': 'Thiết bị nhận', 'value': deviceB},
            {'name': 'Kết quả', 'value': success ? '✅ PASS' : '❌ FAIL'},
            if (errorMessage != null) {'name': 'Lỗi', 'value': errorMessage},
          ],
          'text': additionalData != null ? 'Chi tiết: ${jsonEncode(additionalData)}' : null,
        }
      ]
    };

    try {
      final response = await http.post(
        Uri.parse(webhookUrl),
        headers: {'Content-Type': 'application/json'},
        body: jsonEncode(payload),
      );
      
      return response.statusCode >= 200 && response.statusCode < 300;
    } catch (e) {
      print('Lỗi gửi log đến Teams: $e');
      return false;
    }
  }
}

3. Cấu hình trong Call Helper

// Thêm vào call_helper.dart
import 'package:your_app/core/utils/teams_logger.dart';

class CallHelper {
  // ... existing code ...
  
  static TeamsLogger? _teamsLogger;
  
  static void initTeamsLogging(String webhookUrl) {
    _teamsLogger = TeamsLogger(webhookUrl: webhookUrl);
  }
  
  // Cập nhật hàm xử lý sự kiện cuộc gọi
  void handleCallEvent(CallEvent event) {
    // ... existing code ...
    
    // Log event to Teams
    _logCallEventToTeams(event);
  }
  
  void _logCallEventToTeams(CallEvent event) {
    if (_teamsLogger == null) return;
    
    final callId = event.callId;
    final deviceA = event.callerId;
    final deviceB = event.receiverId;
    final success = event.status == CallStatus.connected;
    final errorMessage = event.error?.message;
    
    _teamsLogger!.logCallTest(
      testId: 'CALL-${DateTime.now().millisecondsSinceEpoch}',
      scenario: 'Call from $deviceA to $deviceB',
      deviceA: deviceA,
      deviceB: deviceB,
      success: success,
      errorMessage: errorMessage,
      additionalData: {
        'callDuration': event.duration,
        'callType': event.callType,
        'networkInfo': _getNetworkInfo(),
        'appState': _getAppState(),
      },
    );
  }
  
  Map<String, dynamic> _getNetworkInfo() {
    // Implement to collect network information
    return {
      'connectionType': 'WiFi', // or 'Cellular'
      'signalStrength': 'Good',
      // Add other network metrics
    };
  }
  
  String _getAppState() {
    // Return current app state: 'foreground', 'background', or 'killed'
    return 'foreground';
  }
}

4. Cách sử dụng

// Trong phương thức khởi tạo ứng dụng
void initializeApp() {
  // ... other initialization code ...
  
  // Khởi tạo logging cho Teams
  final teamsWebhookUrl = 'https://outlook.office.com/webhook/your-webhook-url';
  CallHelper.initTeamsLogging(teamsWebhookUrl);
}

// Trong test case
void runTestCase() {
  // Set up device A and B
  // Make call from A to B
  // Verify call is connected
  // Each call event will automatically log to Microsoft Teams
}

5. Tích hợp vào CI/CD

Quy trình này có thể được tích hợp vào hệ thống CI/CD để tự động hóa quá trình kiểm thử:

  1. Thêm script test trong file CI config (ví dụ: .github/workflows/test.yml)
  2. Cấu hình webhook URL từ biến môi trường bảo mật
  3. Chạy bộ test cases tự động và gửi kết quả về Teams

6. Giám sát và phân tích

Các thông báo trong Microsoft Teams có thể được sử dụng để:

  • Theo dõi tình trạng kiểm thử theo thời gian thực
  • Tạo báo cáo tổng hợp về các vấn đề gặp phải
  • Thông báo cho team khi có sự cố xuất hiện

Cách này giúp tự động hóa việc kiểm thử cuộc gọi và đảm bảo tất cả các thành viên trong team đều nhận được thông báo kịp thời về các vấn đề phát sinh.