[{"data":1,"prerenderedAt":335},["ShallowReactive",2],{"news-item-\u002Fnews\u002Fvideochat-twilio":3},{"id":4,"title":5,"body":6,"category":320,"created by":323,"date":324,"description":325,"extension":326,"meta":327,"navigation":328,"path":329,"sections":330,"seo":331,"stem":332,"thumbnail":333,"__hash__":334},"content_en\u002Fnews\u002Fvideochat-twilio.md","Create voice chat app using Twilio SDK in iOS",{"type":7,"value":8,"toc":314},"minimark",[9,14,24,27,34,40,49,53,61,69,77,80,90,93,97,100,106,113,116,121,129,132,136,140,144,151,154,158,163,166,176,179,185,188,194,199,205,211,214,232,248,254,261,265,268,274,293,296,301,308],[10,11,13],"h2",{"id":12},"introduction","Introduction",[15,16,17,18,23],"p",{},"As described in ",[19,20,22],"a",{"href":21},"videochat-skyway","previous post",", today I will show you how to build a simple chat voice iOS app using Twilio Video SDK.",[15,25,26],{},"Overview, Twilio Video is a well known platform providing many  services to build experiences with video: real-time video, voice, and screen sharing. It received so much good response from customers globally.",[15,28,29],{},[19,30,31],{"href":31,"rel":32},"https:\u002F\u002Fwww.g2.com\u002Fproducts\u002Ftwilio\u002Freviews",[33],"nofollow",[15,35,36],{},[19,37,38],{"href":38,"rel":39},"https:\u002F\u002Fwww.trustradius.com\u002Fproducts\u002Ftwilio-video\u002Freviews",[33],[15,41,42,43,48],{},"In this post we will try using ",[19,44,47],{"href":45,"rel":46},"https:\u002F\u002Fwww.twilio.com\u002Fdocs\u002Fvideo",[33],"Video API"," to build a voice chat application.",[10,50,52],{"id":51},"create-an-project-in-twilio","Create an project in Twilio",[15,54,55,56],{},"Create an account at ",[19,57,60],{"href":58,"rel":59},"https:\u002F\u002Fwww.twilio.com\u002Ftry-twilio",[33],"Twillo",[15,62,63,64],{},"Go to ",[19,65,68],{"href":66,"rel":67},"https:\u002F\u002Fwww.twilio.com\u002Fconsole",[33],"console page",[15,70,71,72],{},"Create a new project name \"TwilioDemoChat\" or any name as you want at ",[19,73,76],{"href":74,"rel":75},"https:\u002F\u002Fwww.twilio.com\u002Fconsole\u002Fprojects\u002Fcreate",[33],"link",[15,78,79],{},"After created app, a welcome page will be shown",[81,82],"img",{"className":83,"alt":87,"src":88,"style":89},[84,85,86],"block","mx-auto","mb-4","","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F17150511\u002FScreen-Shot-2020-07-17-at-15.03.20-1024x528.png","width: 100%;",[15,91,92],{},"Choose \"Other\" and skip to dashboard to finish creating project step.",[81,94],{"className":95,"alt":87,"src":96,"style":89},[84,85,86],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F17150844\u002FScreen-Shot-2020-07-17-at-15.07.58-1024x396.png",[15,98,99],{},"Save ACCOUNT SID and AUTH TOKEN in somewhere so that you can use later.",[15,101,102],{},[103,104,105],"strong",{},"Create API Key",[15,107,108],{},[19,109,112],{"href":110,"rel":111},"https:\u002F\u002Fwww.twilio.com\u002Fconsole\u002Fvideo\u002Fproject\u002Fapi-keys\u002Fcreate",[33],"Reference",[15,114,115],{},"Create a new api key and save it securely in somewhere, because this just be shown in ONCE TIME.",[15,117,118],{},[103,119,120],{},"Create Access Tokens",[15,122,123,124,128],{},"Go to this ",[19,125,76],{"href":126,"rel":127},"https:\u002F\u002Fwww.twilio.com\u002Fconsole\u002Fvideo\u002Fproject\u002Ftesting-tools",[33]," to create  2 new access tokens. We are going to test with 2 users connect to the same room name \"TwilioDemoChatRoom\" and has client identifies are \"TwilioDemoChatRoomUser1\" and \"TwilioDemoChatRoomUser1\",  so that click on \"Generate Access Token\" to get access tokens for that room, save 2 access tokens so we can use in iOS side.",[15,130,131],{},"NOTE:In a production application, your back-end server will need to generate an Access Token for every user in your application. An Access Token is a short-lived credential used to authenticate your client-side application to Twilio.",[81,133],{"className":134,"alt":87,"src":135,"style":89},[84,85,86],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F17165611\u002FScreen-Shot-2020-07-17-at-16.55.26-1024x279.png",[81,137],{"className":138,"alt":87,"src":139,"style":89},[84,85,86],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F17165657\u002FScreen-Shot-2020-07-17-at-16.56.39-1024x240.png",[10,141,143],{"id":142},"implement-voice-chat-in-ios","Implement Voice Chat in iOS",[15,145,146],{},[19,147,150],{"href":148,"rel":149},"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Ftwilio-video-app-ios",[33],"Tutorial",[15,152,153],{},"Create a new project named \"TwilioDemoChat\"",[81,155],{"className":156,"alt":87,"src":157,"style":89},[84,85,86],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F17153400\u002FScreen-Shot-2020-07-17-at-15.33.09-1024x754.png",[15,159,160],{},[103,161,162],{},"Configure CocoaPods",[15,164,165],{},"Create a empty file named PodFile put in root project's directory and paste following commands:",[167,168,173],"pre",{"className":169,"code":171,"language":172},[170],"language-text","platform :ios,'11.0'\nuse_frameworks!\n\ndef install_pods\n  pod 'TwilioVideo'\n  pod 'MBProgressHUD'\nend\n\ntarget 'TwilioDemoChat' do\n  install_pods\nend\n","text",[174,175,171],"code",{"__ignoreMap":87},[15,177,178],{},"Open Terminal app then run following command at project's root directory to install TwilioVideo SDK:",[167,180,183],{"className":181,"code":182,"language":172},[170],"pod install\n",[174,184,182],{"__ignoreMap":87},[15,186,187],{},"Because our application need to use micro for voice chat so we need to add micro permission to info.plist",[167,189,192],{"className":190,"code":191,"language":172},[170],"NSMicrophoneUsageDescription\nThis sample uses a mic device for voice chat\n",[174,193,191],{"__ignoreMap":87},[15,195,196],{},[103,197,198],{},"Implement Twilio",[15,200,201,202],{},"First we need a controller to handle joining room,.. named ",[103,203,204],{},"TwilioController.swift",[167,206,209],{"className":207,"code":208,"language":172},[170],"import UIKit\nimport TwilioVideo\nimport MBProgressHUD\n\nlet TWILIO_TEST_ROOM = \"TwilioDemoChatRoom\"\nlet TWILIO_ACCESS_TOKEN_1 = \"access_token_generated_from_step_Create_Access_Tokens\"\nlet TWILIO_ACCESS_TOKEN_2 = \"access_token_generated_from_step_Create_Access_Tokens\"\n\nlet kTwilioController = TwilioController.shared\n\npublic enum RoomStatus{\n    case Connected\n    case Disconnected\n    case ParticipantConnected\n    case ParticipantDisconnected\n    case Error\n}\n\npublic typealias RoomStatusUpdatedHandler = (RoomStatus) -> (Void)\n\nclass TwilioController: NSObject {\n    static let shared = TwilioController()\n    \n    var room:Room? = nil\n    var connected = false\n    var roomStatusHandler:RoomStatusUpdatedHandler?\n    \n    private var localAudioTrack = LocalAudioTrack()\n\n    \u002F\u002Fconnect to room defined in TWILIO_TEST_ROOM\n    func  connectToRoom(handler:RoomStatusUpdatedHandler?) {\n        roomStatusHandler = handler\n        let connectOptions = ConnectOptions(token: TWILIO_ACCESS_TOKEN_2) { (builder) in\n            builder.roomName = TWILIO_TEST_ROOM\n            \n            \u002F\u002Fsetup local audio track\n            if let audioTrack = self.localAudioTrack {\n                builder.audioTracks = [ audioTrack ]\n            }\n        }\n        room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)\n    }\n    \n    func disconnectFromRoom()  {\n        room?.disconnect()\n    }\n    \n    \u002F\u002F MARK: - Private methods\n    private func toastMessage(message:String){\n        print(\"toastMessage \\(message)\")\n        DispatchQueue.main.asyncAfter(deadline: .now() ) {\n            let hud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true)\n            hud.mode = .text\n            hud.label.text = message\n            hud.removeFromSuperViewOnHide = true\n            hud.hide(animated: true, afterDelay: 2)\n        }\n    }\n}\n\nextension TwilioController : RoomDelegate{\n    \n    \u002F\u002Fevent when did connect to room\n    func roomDidConnect(room: Room) {\n        connected = true\n        roomStatusHandler?(.Connected)\n    }\n    \n    \u002F\u002Fevent when did disconnect to room\n    func roomDidDisconnect(room: Room, error: Error?) {\n        connected = false\n        roomStatusHandler?(.Disconnected)\n    }\n    \n    \u002F\u002Fevent when can't connect to room, because of timeout or network error..\n    func roomDidFailToConnect(room: Room, error: Error) {\n        connected = false\n        roomStatusHandler?(.Error)\n    }\n    \n    \u002F\u002Fevent when participant joined the room\n    func participantDidConnect(room: Room, participant: RemoteParticipant) {\n        let message = \"participant \\(participant.identity) connected\"\n        toastMessage(message: message)\n        roomStatusHandler?(.ParticipantConnected)\n    }\n    \n    \u002F\u002Fevent when participant left the room\n    func participantDidDisconnect(room: Room, participant: RemoteParticipant) {\n        let message = \"participant \\(participant.identity) disconnected\"\n        toastMessage(message: message)\n        roomStatusHandler?(.ParticipantDisconnected)\n    }\n}\n",[174,210,208],{"__ignoreMap":87},[15,212,213],{},"Mainly, this controller has 2 main functions:",[15,215,216,219,220,223,224,227,228,231],{},[103,217,218],{},"connectToRoom","(): connect to specific room defined as ",[103,221,222],{},"TWILIO_TEST_ROOM"," and specific access token (",[103,225,226],{},"TWILIO_ACCESS_TOKEN_1","  or ",[103,229,230],{},"TWILIO_ACCESS_TOKEN_2","), if you try running in physical devices, set different access token for each device. This function has callback to handle events like:",[233,234,235,239,242,245],"ul",{},[236,237,238],"li",{},"Connected: current user connected to room",[236,240,241],{},"Disconnected: current user disconnected from room",[236,243,244],{},"ParticipantConnected: other participant connected to room",[236,246,247],{},"ParticipantDisconnected: other participant disconnected from room",[15,249,250,253],{},[103,251,252],{},"disconnectFromRoom","(): simply disconnect from room",[15,255,256,257,260],{},"Then we create a sample view controller named ",[103,258,259],{},"CallViewController"," like following",[81,262],{"className":263,"alt":87,"src":264,"style":89},[84,85,86],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F07\u002F20110441\u002Ftwilio_chat.png",[15,266,267],{},"in CallViewController.swift we include following code",[167,269,272],{"className":270,"code":271,"language":172},[170],"import UIKit\nimport MBProgressHUD\n\nclass CallViewController: UIViewController {\n    \n    @IBOutlet weak var joinButton: UIButton!\n    @IBOutlet weak var roomTxt: UITextField!\n        \n    \u002F\u002Fwhen joined status update, update button title also\n    private var joined = false{\n        didSet{\n            if joined {\n                joinButton.setTitle(\"End call\", for: .normal)\n            }else{\n                joinButton.setTitle(\"Join\", for: .normal)\n            }\n        }\n    }\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        roomTxt.text = TWILIO_TEST_ROOM                \n    }\n    \n    @IBAction func joinRoom(_ sender: Any) {\n        if !joined{\n            MBProgressHUD.showAdded(to: self.view, animated: true)\n            kTwilioController.connectToRoom { (status) -> (Void) in\n                if status == .Connected {\n                    self.joined = true\n                }\n                if status == .Disconnected{\n                    self.joined = false\n                }\n                MBProgressHUD.hide(for: self.view, animated: true)\n            }\n            \n        }else{\n            kTwilioController.disconnectFromRoom()\n        }\n\n    }\n        \n}\n",[174,273,271],{"__ignoreMap":87},[15,275,276,277,280,281,284,285,288,289,292],{},"Simply, we have a textfield to display test room name(TwilioDemoChatRoom, ",[103,278,279],{},"not editable","), with a button to ",[103,282,283],{},"Join"," or ",[103,286,287],{},"End Call"," (we detect the room's status has changed to update button's title and call function ",[103,290,291],{},"connectToRoom()"," or disconnectFromRoom() properly).",[15,294,295],{},"Now you run project in 2 devices (simulator not supported)  to check how it works. Remember to change access token for each device when running.",[15,297,298],{},[103,299,300],{},"Refs:",[15,302,303],{},[19,304,307],{"href":305,"rel":306},"http:\u002F\u002Ftwilio.com\u002Fdocs\u002Fvideo\u002Fios-v1-getting-started",[33],"Twilio Video iOS Tutorial",[15,309,310],{},[19,311,313],{"href":66,"rel":312},[33],"Twilio Console",{"title":87,"searchDepth":315,"depth":315,"links":316},2,[317,318,319],{"id":12,"depth":315,"text":13},{"id":51,"depth":315,"text":52},{"id":142,"depth":315,"text":143},[321,322],"tech talk","mobile","Briswell Vietnam Co Ltd","2020-08-13","As described in previous post, today I will show you how to build a simple chat voice iOS app using Twilio Video SDK.","md",{},true,"\u002Fnews\u002Fvideochat-twilio",null,{"title":5,"description":325},"news\u002Fvideochat-twilio","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F08\u002F13161934\u002Ftwilio.png","cQNi9w9gm6NSN8sqot5u87le5uLL3J4-GrrK1ncVzKc",1786098562414]