Tạo ứng dụng chat voice sử dụng Twilio SDK

Tạo ứng dụng chat voice sử dụng Twilio SDK

Lời giới thiệu

Như đã đề cập ở bài viết trước, hôm nay chúng tôi sẽ hướng dẫn bạn xây dựng 1 ứng dụng iOS chat voice sử dụng Twilio Video SDK.

Tổng quan, Twilio Video nổi tiếng là 1 nền tảng cung cấp rất nhiều dịch vụ để xây dựng các trải nghiệm về video: chat video(voice) thời gian thực, chia sẻ màn hình. Trên thế giới, nó nhận được khá nhiều đánh giá tích cực từ người dùng.

https://www.g2.com/products/twilio/reviews

https://www.trustradius.com/products/twilio-video/reviews

Trong bài viết này, chúng ta sẽ thử sử dụng Video API để xây dụng 1 ứng dụng chat voice.

Tạo 1 dự án trên Twilio

Tạo 1 tài khoản trên Twillo

Mở trang console

Tạo 1 dự án tên “TwilioDemoChat” hay bất kỳ tên nào mà bạn muốn tại link

Sau khi tạo dự án, sẽ hiện ra trang chào mừng

Chọn “Other” và di chuyển đến trang dashboard để hoàn thành bước tạo dự án.

Lưu ACCOUNT SID  và AUTH TOKEN  vào 1 file để sau này sử dụng.

Tạo API Key

Tham khảo

Tạo 1 api key mới và lưu giữ cẩn thận, bởi vì nó chỉ hiển thị đúng 1 LẦN duy nhất.

Tạo Access Tokens

Tại đường dẫn này tạo 2 access token mới, bởi vì chúng ta sẽ test với 2 user cùng kết nối tới cùng 1 room tên là “TwilioDemoChatRoom” and có các định danh sau “TwilioDemoChatRoomUser1” và “TwilioDemoChatRoomUser2”, sau đó bấm vào nút “Generate Access Token” để lấy access token, lưu chúng lại để sử dụng cho iOS app.

CHÚ Ý: Ở môi trường release, bước này sẽ được phía server đảm nhiệm, nó sẽ tạo ra từng access token cho từng user sử dụng ở mỗi room, 1 access token  là 1 chứng thực ngắn hạn để xác nhận user tới server Twilio.

 

Tạo ứng dụng voice chat trên iOS

Hướng dẫn

Tạo 1 dự án mới tên là “TwilioDemoChat”

Cấu hình CocoaPods

Tạo 1 file rỗng đặt tên là PodFile đặt tại thư mục gốc của dự án, sau đó dán đoạn code sau vào :

platform :ios,'11.0'
use_frameworks!

def install_pods
  pod 'TwilioVideo'
  pod 'MBProgressHUD'
end

target 'TwilioDemoChat' do
  install_pods
end

Mở ứng dụng Terminal  chạy dòng lệnh sau ở thư mục gốc dự án để cài đặt TwilioVideo SDK:

pod install

Bởi vì ứng dụng chúng ta cần sử dụng micro để chat voice nên chúng ta cần thêm quyền hạn sử dụng micro vào file info.plist

NSMicrophoneUsageDescription
Ứng dụng demo này sử dụng micro để chat thoại

 Áp dụng Twilio

Trước tiên chúng ta tạo 1 controller để xử lý việc tham gia room tên là TwilioController.swift

import UIKit
import TwilioVideo
import MBProgressHUD

let TWILIO_TEST_ROOM = "TwilioDemoChatRoom"

let TWILIO_ACCESS_TOKEN_1 = "access_token_tạo_ra_từ_bước_Tạo_Access_Token"
let TWILIO_ACCESS_TOKEN_2 = "access_token_tạo_ra_từ_bước_Tạo_Access_Token"

let kTwilioController = TwilioController.shared

public enum RoomStatus{
    case Connected
    case Disconnected
    case ParticipantConnected
    case ParticipantDisconnected
    case Error
}

public typealias RoomStatusUpdatedHandler = (RoomStatus) -> (Void)

class TwilioController: NSObject {
    static let shared = TwilioController()
    
    var room:Room? = nil
    var connected = false
    var roomStatusHandler:RoomStatusUpdatedHandler?
    
    private var localAudioTrack = LocalAudioTrack()

    //kết nối tới room được định nghĩa ở hằng số TWILIO_TEST_ROOM
    func  connectToRoom(handler:RoomStatusUpdatedHandler?) {
        roomStatusHandler = handler 
        //thay đổi access token cho từng device
        let connectOptions = ConnectOptions(token: TWILIO_ACCESS_TOKEN_2) { (builder) in
            builder.roomName = TWILIO_TEST_ROOM
            
            //cấu hình âm thanh
            if let audioTrack = self.localAudioTrack {
                builder.audioTracks = [ audioTrack ]
            }
        }
        room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
    }
    
    func disconnectFromRoom()  {
        room?.disconnect()
    }
    
    // MARK: - các hàm nội bộ
    private func toastMessage(message:String){
        print("toastMessage \(message)")
        DispatchQueue.main.asyncAfter(deadline: .now() ) {
            let hud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true)
            hud.mode = .text
            hud.label.text = message
            hud.removeFromSuperViewOnHide = true
            hud.hide(animated: true, afterDelay: 2)
        }
    }
}

extension TwilioController : RoomDelegate{
    
    //sự kiện khi user đã kết nối tới room
    func roomDidConnect(room: Room) {
        connected = true
        roomStatusHandler?(.Connected)
    }
    
    //sự kiện khi user đã rời khỏi room
    func roomDidDisconnect(room: Room, error: Error?) {
        connected = false
        roomStatusHandler?(.Disconnected)
    }
    
    //sự kiện khi user không thể kết nối room, bởi vì lỗi timeout hay kết nối mạng...
    func roomDidFailToConnect(room: Room, error: Error) {
        connected = false
        roomStatusHandler?(.Error)
    }
    
    //sự kiện khi người khác tham gia room
    func participantDidConnect(room: Room, participant: RemoteParticipant) {
        let message = "participant \(participant.identity) connected"
        toastMessage(message: message)
        roomStatusHandler?(.ParticipantConnected)
    }
    
    //sự kiện khi người tham gia rời room
    func participantDidDisconnect(room: Room, participant: RemoteParticipant) {
        let message = "participant \(participant.identity) disconnected"
        toastMessage(message: message)
        roomStatusHandler?(.ParticipantDisconnected)
    }
}

Controller này chủ yếu có 2 hàm chính:

connectToRoom(): kết nối tới room cụ thể được chỉ định bởi hằng số TWILIO_TEST_ROOM và access token (TWILIO_ACCESS_TOKEN_1  hay TWILIO_ACCESS_TOKEN_2). Nếu bạn chạy trên thiết bị thì hãy set access token khác nhau cho từng thiết bị. Ngoài ra function này còn xử lý các sự kiện sau:

  • Connected: sự kiện khi user đã kết nối tới room
  • Disconnected: sự kiện khi user đã rời khỏi room
  • ParticipantConnected: sự kiện khi người khác tham gia room
  • ParticipantDisconnected: sự kiện khi người tham gia rời room
  • roomDidFailToConnect: sự kiện khi user không thể kết nối room, bởi vì lỗi timeout hay kết nối mạng…

disconnectFromRoom():  rời khỏi room

Sau đó chúng ta tạo 1 view controller tên là CallViewController có UI đơn giản nhu sau:

Trong file CallViewController.swift  chúng ta dán đoạn code sau vào:

import UIKit
import MBProgressHUD

class CallViewController: UIViewController {
    
    @IBOutlet weak var joinButton: UIButton!
    @IBOutlet weak var roomTxt: UITextField!
        
    //khi trạng thái tham gia room thay đổi, cập nhật tiêu đề tương ứng cho button tham gia
    private var joined = false{
        didSet{
            if joined {
                joinButton.setTitle("End call", for: .normal)
            }else{
                joinButton.setTitle("Join", for: .normal)
            }
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        roomTxt.text = TWILIO_TEST_ROOM
                
    }
    
    @IBAction func joinRoom(_ sender: Any) {
        if !joined{
            MBProgressHUD.showAdded(to: self.view, animated: true)
            kTwilioController.connectToRoom { (status) -> (Void) in
                if status == .Connected {
                    self.joined = true
                }
                if status == .Disconnected{
                    self.joined = false
                }
                MBProgressHUD.hide(for: self.view, animated: true)
            }
            
        }else{
            kTwilioController.disconnectFromRoom()
        }

    }
        
}

Đơn giản chúng ta có 1 textfield để hiển thị tên room kết nối (TwilioDemoChatRoom, và không thể chỉnh sửa được),  với 1  button để  Join hay End Call ( Tuỳ vào trạng thái tham gia room mà chúng ta cập nhật tiêu đề button cho phù hợp để gọi  hàm connectToRoom() hay disconnectFromRoom() ).

Bây giờ bạn hãy chạy dự án trên 2 thiết bị iOS (không hỗ trợ máy ảo) để xem nó hoạt động như thế nào.

Nhớ đổi access token cho từng thiết bị khi bắt đầu chạy dự án.

Tham khảo:

Twilio Video iOS Tutorial

Twilio Console