Proposed Pull Request Change

title description services ms.date ms.topic author ms.author ms.service ms.subservice ms.custom
Migrating from Twilio Conversations Chat to Azure Communication Services Chat iOS Guide describes how to migrate iOS apps from Twilio Conversations Chat to Azure Communication Services Chat SDK. azure-communication-services 08/28/2024 include RinaRish ektrishi azure-communication-services chat ['mode-other', 'sfi-ropc-nochange']
📄 Document Links
GitHub View on GitHub Microsoft Learn View on Microsoft Learn
Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
+0 -0
+0 -0
--- title: Migrating from Twilio Conversations Chat to Azure Communication Services Chat iOS description: Guide describes how to migrate iOS apps from Twilio Conversations Chat to Azure Communication Services Chat SDK. services: azure-communication-services ms.date: 08/28/2024 ms.topic: include author: RinaRish ms.author: ektrishi ms.service: azure-communication-services ms.subservice: chat ms.custom: - mode-other - sfi-ropc-nochange --- ## Prerequisites - **Azure Account:** Make sure that your Azure account is active. New users can create a free account at [Microsoft Azure](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn). - **Communication Services Resource:** Set up a [Communication Services Resource](../../quickstarts/create-communication-resource.md?tabs=windows&pivots=platform-azp) via your Azure portal and note your connection string. - **Azure CLI:** Follow the instructions to [Install Azure CLI on Windows](/cli/azure/install-azure-cli-windows?tabs=azure-cli). - **User Access Token:** Generate a user access token to instantiate the call client. You can create one using the Azure CLI as follows: ```console az communication identity token issue --scope voip --connection-string "yourConnectionString" ``` For more information, see [Use Azure CLI to Create and Manage Access Tokens](../../quickstarts/identity/access-tokens.md?pivots=platform-azcli). ## Installation ### Install the libraries To start the migration from Twilio Conversations Chat, the first step is to install the Azure Communication Services Chat SDK for iOS to your project. You can configure these parameters using `CocoaPods`. 1. Create a Podfile for your application. Open the terminal, navigate to the project folder, and run: `pod init` 2. Add the following code to the Podfile and save (make sure that "target" matches the name of your project): ``` pod 'AzureCommunicationChat', '~> 1.3.5' ``` 3. Set up the `.xcworkspace` project: ```shell pod install ``` 4. Open the `.xcworkspace` created by the pod install with Xcode. ### Authenticating to the SDK To use the Azure Communication Services Chat SDK, you need to authenticate using an access token. #### Twilio The following code snippets presume the availability of a valid access token for Twilio Services. ```swift static func getTokenUrlFromDefaults(identity: String, password: String) -> URL? { // Get token service absolute URL from settings guard let tokenServiceUrl = UserDefaults.standard.string(forKey: "ACCESS_TOKEN_SERVICE_URL"), !tokenServiceUrl.isEmpty else { return nil } return constructLoginUrl(tokenServiceUrl, identity: identity, password: password) } ``` #### Azure Communication Services The following code snippets require a valid access token to initiate a `CallClient`. You need a valid token. For more information, see [Create and Manage Access Tokens](../../quickstarts/identity/access-tokens.md). ```swift // Create an instance of CallClient let callClient = CallClient() // A reference to the call agent, it will be initialized later var callAgent: CallAgent? // Embed the token in a CommunicationTokenCredential object let userCredential = try? CommunicationTokenCredential(token: "<USER_TOKEN>") // Create a CallAgent that will be used later to initiate or receive calls callClient.createCallAgent(userCredential: userCredential) { callAgent, error in if error != nil { // Raise the error to the user and return } self.callAgent = callAgent } ``` ### Initialize Chat Client #### Twilio The following code snippet initializes the chat client in Twilio. ```swift func fetchAccessTokenAndInitializeClient() { let identity = "user_identity" // Replace with actual user identity let urlString = "http://localhost:3000/token?identity=\(identity)" guard let url = URL(string: urlString) else { return } let task = URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { print("Error fetching token: \(String(describing: error))") return } do { if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let token = json["token"] as? String { self.initializeConversationsClient(withToken: token) } } catch { print("Error parsing token JSON: \(error)") } } task.resume() } ```m = TwilioVideoSDK.connect(options: connectOptions, delegate: self) ``` #### Azure Communication Services To create a chat client, use your Communication Services endpoint and the access token generated as part of the prerequisite steps. Replace `<ACS_RESOURCE_ENDPOINT>` with the endpoint of your Azure Communication Services resource. Replace `<ACCESS_TOKEN>` with a valid Communication Services access token. ```swift let endpoint = "<ACS_RESOURCE_ENDPOINT>" let credential = try CommunicationTokenCredential( token: "<ACCESS_TOKEN>" ) let options = AzureCommunicationChatClientOptions() let chatClient = try ChatClient( endpoint: endpoint, credential: credential, withOptions: options ) ``` ## Object model The following classes and interfaces handle some of the major features of the Azure Communication Services Chat SDK for iOS. | Name | Description | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ChatClient` | This class is needed for the chat function. You instantiate it with your subscription information, and use it to create, get, delete threads, and subscribe to chat events. | | `ChatThreadClient` | This class is needed for the chat thread function. You get an instance via `ChatClient`, and use it to send, receive, update, and delete messages. You can also use it to add, remove, get users, and send typing notifications and read receipts. | ### Start a chat thread #### Twilio The following code snippet enables you to create a new chat thread. ```swift // the unique name of the conversation you create private let uniqueConversationName = "general" // For the quickstart, this will be the view controller weak var delegate: QuickstartConversationsManagerDelegate? // MARK: Conversations variables private var client: TwilioConversationsClient? private var conversation: TCHConversation? private(set) var messages: [TCHMessage] = [] private var identity: String? func conversationsClient(_ client: TwilioConversationsClient, synchronizationStatusUpdated status: TCHClientSynchronizationStatus) { guard status == .completed else { return } checkConversationCreation { (_, conversation) in if let conversation = conversation { self.joinConversation(conversation) } else { self.createConversation { (success, conversation) in if success, let conversation = conversation { self.joinConversation(conversation) } } } } ``` #### Azure Communication Services The response returned from creating a chat thread is `CreateChatThreadResult`. It contains a `chatThread` property, which is the `ChatThreadProperties` object. This object contains the `threadId`, which you can use to get a `ChatThreadClient` for performing operations on the created thread: add participants, send message, and so on. Replace the comment `<CREATE A CHAT THREAD>` with the following code snippet: ```swift let request = CreateChatThreadRequest( topic: "Quickstart", participants: [ ChatParticipant( id: CommunicationUserIdentifier("<USER_ID>"), displayName: "Jack" ) ] ) var threadId: String? chatClient.create(thread: request) { result, _ in switch result { case let .success(result): threadId = result.chatThread?.id case .failure: fatalError("Failed to create thread.") } semaphore.signal() } semaphore.wait() ``` Replace `<USER_ID>` with a valid Communication Services user ID. You're using a semaphore here to wait for the completion handler before continuing. In later steps, use the `threadId` from the response returned to the completion handler. ### Get a chat thread client #### Twilio The following code snippet shows how to get a chat thread client in Twilio. ```swift func conversationsClient(_ client: TwilioConversationsClient, synchronizationStatusUpdated status: TCHClientSynchronizationStatus) { guard status == .completed else { return } checkConversationCreation { (_, conversation) in if let conversation = conversation { self.joinConversation(conversation) } else { self.createConversation { (success, conversation) in if success, let conversation = conversation { self.joinConversation(conversation) } } } } } ``` #### Azure Communication Services The `createClient` method returns a `ChatThreadClient` for a thread that already exists. You can use it to perform operations on the created thread: add participants, send message, and so on. The `threadId` is the unique ID of the existing chat thread. Replace the comment `<GET A CHAT THREAD CLIENT>` with the following code: ```swift let chatThreadClient = try chatClient.createClient(forThread: threadId!) ``` ### Send a message to a chat thread Unlike Twilio, Azure Communication Services doesn't have separate function to send text message or media. #### Twilio Send a regular text message in Twilio. ```swift func sendMessage(_ messageText: String, completion: @escaping (TCHResult, TCHMessage?) -> Void) { let messageOptions = TCHMessageOptions().withBody(messageText) conversation?.sendMessage(with: messageOptions, completion: { (result, message) in completion(result, message) }) } ``` Send media in Twilio: ```swift / The data for the image you would like to send let data = Data() // Prepare the message and send it self.conversation.prepareMessage .addMedia(data: data, contentType: "image/jpeg", filename: "image.jpg", listener: .init(onStarted: { // Called when upload of media begins. print("Media upload started") }, onProgress: { bytes in // Called as upload progresses, with the current byte count. print("Media upload progress: \(bytes)") }, onCompleted: { sid in // Called when upload is completed, with the new mediaSid if successful. // Full failure details will be provided through sendMessage's completion. print("Media upload completed") }, onFailed: { error in // Called when upload is completed, with the new mediaSid if successful. // Full failure details will be provided through sendMessage's completion. print("Media upload failed with error: \(error)") })) .buildAndSend { result, message in if !result.isSuccessful { print("Creation failed: \(String(describing: result.error))") } else { print("Creation successful") } } ``` #### Azure Communication Services Use the `send` method to send a message to a thread identified by `threadId`. Use `SendChatMessageRequest` to describe the message request: - Use `content` to provide the chat message content. - Use `senderDisplayName` to specify the display name of the sender. - Use `type` to specify the message type, such as `text` or `html`. - Use `metadata` optionally to include any information you want to send along with the message. This field provides a mechanism for developers to extend chat message functionality and add custom information for your use case. For example, when sharing a file link in the message, you might want to add `hasAttachment:true` in metadata so that recipient's application can parse that and display accordingly. The response returned from sending a message is`SendChatMessageResult`. It contains an ID, which is the unique ID of the message. Replace the comment `<SEND A MESSAGE>` with the following code snippet: ```swift let message = SendChatMessageRequest( content: "Hello!", senderDisplayName: "Jack", type: .text, metadata: [ "hasAttachment": "true", "attachmentUrl": "https://contoso.com/files/attachment.docx" ] ) var messageId: String? chatThreadClient.send(message: message) { result, _ in switch result { case let .success(result): print("Message sent, message id: \(result.id)") messageId = result.id case .failure: print("Failed to send message") } semaphore.signal() } semaphore.wait() ``` ### Receive chat messages from a chat thread Unlike Twilio, Azure Communication Services doesn't have a separate function to receive text message or media. #### Twilio The following code snippet shows how to receive a text message in Twilio. ```swift // Called whenever a conversation we've joined receives a new message func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, messageAdded message: TCHMessage) { messages.append(message) // Changes to the delegate should occur on the UI thread DispatchQueue.main.async { if let delegate = self.delegate { delegate.reloadMessages() delegate.receivedNewMessage() } } } ``` Receive media in Twilio: ```swift conversationsClient.getTemporaryContentUrlsForMedia(message.attachedMedia) { result, mediaSidToUrlMap in guard result.isSuccessful else { print("Couldn't get temporary urls with error: \(String(describing: result.error))") return } for (sid, url) in sidToUrlMap { print("\(sid) -> \(url)") } } ``` #### Azure Communication Services With real-time signaling, you can subscribe to listen for new incoming messages and update the current messages in memory accordingly. Azure Communication Services supports a [list of events that you can subscribe to](../../concepts/chat/concepts.md#real-time-notifications). Replace the comment `<RECEIVE MESSAGES>` with the following code. After enabling notifications, try sending new messages to see the `ChatMessageReceivedEvents`. ```swift chatClient.startRealTimeNotifications { result in switch result { case .success: print("Real-time notifications started.") case .failure: print("Failed to start real-time notifications.") } semaphore.signal() } semaphore.wait() chatClient.register(event: .chatMessageReceived, handler: { response in switch response { case let .chatMessageReceivedEvent(event): print("Received a message: \(event.message)") default: return } }) ``` Alternatively you can retrieve chat messages by polling the `listMessages` method at specified intervals. See the following code snippet for `listMessages`. ```swift chatThreadClient.listMessages { result, _ in switch result { case let .success(messagesResult): guard let messages = messagesResult.pageItems else { print("No messages returned.") return } for message in messages { print("Received message with id: \(message.id)") } case .failure: print("Failed to receive messages") } semaphore.signal() } semaphore.wait() ``` ### Push notifications Similar to Twilio, Azure Communication Services support push notifications. Push notifications notify clients of incoming messages in a chat thread if the mobile app isn't running in the foreground. Currently sending chat push notifications with Notification Hub is supported for iOS SDK in version 1.3.0. For more information, see [Enable Push Notification in your chat app](../../tutorials/add-chat-push-notifications.md).
Success! Branch created successfully. Create Pull Request on GitHub
Error: