Delen via


Quickstart: Deelnemen aan uw chat-app aan een Teams-vergadering

Ga aan de slag met Azure Communication Services door uw chatoplossing te verbinden met Microsoft Teams.

In deze quickstart leert u hoe u kunt chatten in een Teams-vergadering met behulp van de Azure Communication Services Chat SDK voor JavaScript.

Voorbeeldcode

Zoek de voltooide code voor deze quickstart op GitHub.

Vereisten

Deelnemen aan de vergaderingschat

Een Communication Services-gebruiker kan deelnemen aan een Teams-vergadering als anonieme gebruiker met behulp van de Calling SDK. Als u deelneemt aan de vergadering, worden ze ook toegevoegd als deelnemer aan de vergaderingschat, waar ze berichten kunnen verzenden en ontvangen met andere gebruikers in de vergadering. De gebruiker heeft geen toegang tot chatberichten die zijn verzonden voordat ze deelnemen aan de vergadering en ze kunnen geen berichten verzenden of ontvangen nadat de vergadering is beëindigd. Als u wilt deelnemen aan de vergadering en wilt chatten, kunt u de volgende stappen volgen.

Een nieuwe Node.js-toepassing maken

Open uw terminal of opdrachtvenster, maak een nieuwe map voor uw app en navigeer daar naartoe.

mkdir chat-interop-quickstart && cd chat-interop-quickstart

Voer npm init -y uit om een package.json-bestand te maken met de standaardinstellingen.

npm init -y

De chatpakketten installeren

Gebruik de npm install opdracht om de benodigde Communication Services SDK's voor JavaScript te installeren.

npm install @azure/communication-common --save

npm install @azure/communication-identity --save

npm install @azure/communication-chat --save

npm install @azure/communication-calling --save

De optie --save geeft de bibliotheek weer als afhankelijkheid in het package.json-bestand.

Stel het app-framework in

In deze quickstart wordt Webpack gebruikt om de toepassingsassets te bundelen. Voer de volgende opdracht uit om de npm-pakketten webpack, webpack-cli en webpack-dev-server npm te installeren en deze weer te geven als ontwikkelingsafhankelijkheden in uw package.json:

npm install webpack@5.89.0 webpack-cli@5.1.4 webpack-dev-server@4.15.1 --save-dev

Maak een index. html-bestand in de hoofdmap van uw project. We gebruiken dit bestand om een eenvoudige indeling te configureren waarmee de gebruiker kan deelnemen aan een vergadering en kan chatten.

De besturingselementen voor de gebruikersinterface van Teams toevoegen

Vervang de code in index.html door het volgende codefragment. Het tekstvak boven aan de pagina wordt gebruikt om de context van de Teams-vergadering in te voeren. De knop Deelnemen aan Teams-vergadering wordt gebruikt om deel te nemen aan de opgegeven vergadering. Onder aan de pagina wordt een pop-upvenster voor chatten weergegeven. Het kan worden gebruikt om berichten te verzenden op de vergaderingsthread en geeft in realtime alle berichten weer die op de thread worden verzonden terwijl de Communication Services-gebruiker lid is.

<!DOCTYPE html>
<html>
   <head>
      <title>Communication Client - Calling and Chat Sample</title>
      <style>
         body {box-sizing: border-box;}
         /* The popup chat - hidden by default */
         .chat-popup {
         display: none;
         position: fixed;
         bottom: 0;
         left: 15px;
         border: 3px solid #f1f1f1;
         z-index: 9;
         }
         .message-box {
         display: none;
         position: fixed;
         bottom: 0;
         left: 15px;
         border: 3px solid #FFFACD;
         z-index: 9;
         }
         .form-container {
         max-width: 300px;
         padding: 10px;
         background-color: white;
         }
         .form-container textarea {
         width: 90%;
         padding: 15px;
         margin: 5px 0 22px 0;
         border: none;
         background: #e1e1e1;
         resize: none;
         min-height: 50px;
         }
         .form-container .btn {
         background-color: #4CAF40;
         color: white;
         padding: 14px 18px;
         margin-bottom:10px;
         opacity: 0.6;
         border: none;
         cursor: pointer;
         width: 100%;
         }
         .container {
         border: 1px solid #dedede;
         background-color: #F1F1F1;
         border-radius: 3px;
         padding: 8px;
         margin: 8px 0;
         }
         .darker {
         border-color: #ccc;
         background-color: #ffdab9;
         margin-left: 25px;
         margin-right: 3px;
         }
         .lighter {
         margin-right: 20px;
         margin-left: 3px;
         }
         .container::after {
         content: "";
         clear: both;
         display: table;
         }
      </style>
   </head>
   <body>
      <h4>Azure Communication Services</h4>
      <h1>Calling and Chat Quickstart</h1>
          <input id="teams-link-input" type="text" placeholder="Teams meeting link"
        style="margin-bottom:1em; width: 400px;" />
        <p>Call state <span style="font-weight: bold" id="call-state">-</span></p>
      <div>
        <button id="join-meeting-button" type="button">
            Join Teams Meeting
        </button>
        <button id="hang-up-button" type="button" disabled="true">
            Hang Up
        </button>
      </div>
      <div class="chat-popup" id="chat-box">
         <div id="messages-container"></div>
         <form class="form-container">
            <textarea placeholder="Type message.." name="msg" id="message-box" required></textarea>
            <button type="button" class="btn" id="send-message">Send</button>
         </form>
      </div>
      <script src="./bundle.js"></script>
   </body>
</html>

De besturingselementen voor de gebruikersinterface van Teams inschakelen

Vervang de inhoud van het client.js-bestand door het volgende codefragment.

Vervang in het fragment

  • SECRET_CONNECTION_STRINGmet de verbindingsreeks van uw Communication Service
import { CallClient } from "@azure/communication-calling";
import { AzureCommunicationTokenCredential } from "@azure/communication-common";
import { CommunicationIdentityClient } from "@azure/communication-identity";
import { ChatClient } from "@azure/communication-chat";

let call;
let callAgent;
let chatClient;
let chatThreadClient;

const meetingLinkInput = document.getElementById("teams-link-input");
const callButton = document.getElementById("join-meeting-button");
const hangUpButton = document.getElementById("hang-up-button");
const callStateElement = document.getElementById("call-state");

const messagesContainer = document.getElementById("messages-container");
const chatBox = document.getElementById("chat-box");
const sendMessageButton = document.getElementById("send-message");
const messageBox = document.getElementById("message-box");

var userId = "";
var messages = "";
var chatThreadId = "";

async function init() {
  const connectionString = "<SECRET_CONNECTION_STRING>";
  const endpointUrl = connectionString.split(";")[0].replace("endpoint=", "");

  const identityClient = new CommunicationIdentityClient(connectionString);

  let identityResponse = await identityClient.createUser();
  userId = identityResponse.communicationUserId;
  console.log(`\nCreated an identity with ID: ${identityResponse.communicationUserId}`);

  let tokenResponse = await identityClient.getToken(identityResponse, ["voip", "chat"]);

  const { token, expiresOn } = tokenResponse;
  console.log(`\nIssued an access token that expires at: ${expiresOn}`);
  console.log(token);

  const callClient = new CallClient();
  const tokenCredential = new AzureCommunicationTokenCredential(token);

  callAgent = await callClient.createCallAgent(tokenCredential);
  callButton.disabled = false;
  chatClient = new ChatClient(endpointUrl, new AzureCommunicationTokenCredential(token));

  console.log("Azure Communication Chat client created!");
}

init();

const joinCall = (urlString, callAgent) => {
  const url = new URL(urlString);
  console.log(url);
  if (url.pathname.startsWith("/meet")) {
    // Short teams URL, so for now call meetingID and pass code API
    return callAgent.join({
      meetingId: url.pathname.split("/").pop(),
      passcode: url.searchParams.get("p"),
    });
  } else {
    return callAgent.join({ meetingLink: urlString }, {});
  }
};

callButton.addEventListener("click", async () => {
  // join with meeting link
  try {
    call = joinCall(meetingLinkInput.value, callAgent);
  } catch {
    throw new Error("Could not join meeting - have you set your connection string?");
  }

  // Chat thread ID is provided from the call info, after connection.
  call.on("stateChanged", async () => {
    callStateElement.innerText = call.state;

    if (call.state === "Connected" && !chatThreadClient) {
      chatThreadId = call.info?.threadId;
      chatThreadClient = chatClient.getChatThreadClient(chatThreadId);

      chatBox.style.display = "block";
      messagesContainer.innerHTML = messages;

      // open notifications channel
      await chatClient.startRealtimeNotifications();

      // subscribe to new message notifications
      chatClient.on("chatMessageReceived", (e) => {
        console.log("Notification chatMessageReceived!");

        // check whether the notification is intended for the current thread
        if (chatThreadId != e.threadId) {
          return;
        }

        if (e.sender.communicationUserId != userId) {
          renderReceivedMessage(e.message);
        } else {
          renderSentMessage(e.message);
        }
      });
    }
  });

  // toggle button and chat box states
  hangUpButton.disabled = false;
  callButton.disabled = true;

  console.log(call);
});

async function renderReceivedMessage(message) {
  messages += '<div class="container lighter">' + message + "</div>";
  messagesContainer.innerHTML = messages;
}

async function renderSentMessage(message) {
  messages += '<div class="container darker">' + message + "</div>";
  messagesContainer.innerHTML = messages;
}

hangUpButton.addEventListener("click", async () => {
  // end the current call
  await call.hangUp();
  // Stop notifications
  chatClient.stopRealtimeNotifications();

  // toggle button states
  hangUpButton.disabled = true;
  callButton.disabled = false;
  callStateElement.innerText = "-";

  // toggle chat states
  chatBox.style.display = "none";
  messages = "";
  // Remove local ref
  chatThreadClient = undefined;
});

sendMessageButton.addEventListener("click", async () => {
  let message = messageBox.value;

  let sendMessageRequest = { content: message };
  let sendMessageOptions = { senderDisplayName: "Jack" };
  let sendChatMessageResult = await chatThreadClient.sendMessage(
    sendMessageRequest,
    sendMessageOptions
  );
  let messageId = sendChatMessageResult.id;

  messageBox.value = "";
  console.log(`Message sent!, message id:${messageId}`);
});

Weergavenamen van de deelnemers aan de chatthread worden niet ingesteld door de Teams-client. De namen worden geretourneerd als null in de API voor het weergeven van deelnemers, in de participantsAdded gebeurtenis en in de participantsRemoved gebeurtenis. De weergavenamen van de chatdeelnemers kunnen worden opgehaald uit het remoteParticipants veld van het call object. Wanneer u een melding ontvangt over een wijziging in een rooster, kunt u deze code gebruiken om de naam op te halen van de gebruiker die is toegevoegd of verwijderd:

var displayName = call.remoteParticipants.find(p => p.identifier.communicationUserId == '<REMOTE_USER_ID>').displayName;

De code uitvoeren

Webpack-gebruikers kunnen de webpack-dev-server gebruiken om uw app te bouwen en uit te voeren. Voer de volgende opdracht uit om de toepassingshost op een lokale webserver te bundelen:

npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map

Open uw browser en ga naar http://localhost:8080/. Als het goed is, ziet u dat de app is gestart, zoals wordt weergegeven in de volgende schermopname:

Schermopname van de voltooide JavaScript-toepassing.

Voeg de koppeling naar de Teams-vergadering in het tekstvak in. Druk op Teams-vergadering deelnemen om deel te nemen aan de Teams-vergadering. Nadat de Communication Services-gebruiker is toegelaten tot de vergadering, kunt u chatten vanuit uw Communication Services-toepassing. Navigeer naar het vak onder aan de pagina om te beginnen met chatten. Ter vereenvoudiging toont de toepassing alleen de laatste twee berichten in de chat.

Notitie

Bepaalde functies worden momenteel niet ondersteund voor interoperabiliteitsscenario's met Teams. Meer informatie over de ondersteunde functies vindt u in teams-vergadermogelijkheden voor externe Teams-gebruikers

In deze quickstart leert u hoe u kunt chatten in een Teams-vergadering met behulp van de Azure Communication Services Chat SDK voor iOS.

Voorbeeldcode

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Vereisten

  • Een Azure-account met een actief abonnement. Gratis een account maken
  • Een Mac waarop Xcode wordt uitgevoerd, evenals een geldig ontwikkelaarscertificaat dat is geïnstalleerd in uw Sleutelhanger.
  • Een Teams implementatie.
  • Een toegangstoken voor gebruikers voor uw Azure Communication Service. U kunt ook de Azure CLI gebruiken en de opdracht uitvoeren met uw verbindingsreeks om een gebruiker en een toegangstoken te maken.
az communication user-identity token issue --scope voip chat --connection-string "yourConnectionString"

Zie Azure CLI gebruiken voor het maken en beheren van toegangstokens voor meer informatie.

Instellen

Het Xcode-project maken

Maak in Xcode een nieuw iOS-project en selecteer de sjabloon Single View-app (Toepassing met één weergave). In deze zelfstudie wordt gebruikgemaakt van het SwiftUI-framework, dus u moet de taal instellen op Swift en de gebruikersinterface op SwiftUI. Tijdens deze quickstart maakt u geen tests. U kunt Tests opnemen uitschakelen.

Schermafbeelding met het venster Nieuw project in Xcode.

CocoaPods installeren

Gebruik deze handleiding om CocoaPods op uw Mac te installeren.

Installeer het pakket en de afhankelijkheden met CocoaPods

  1. Als u een Podfile voor uw toepassing wilt maken, opent u de terminal en gaat u naar de projectmap en voert u pod init uit.

  2. Voeg de volgende code toe aan het Podfile onder het doel en sla deze op.

target 'Chat Teams Interop' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for Chat Teams Interop
  pod 'AzureCommunicationCalling'
  pod 'AzureCommunicationChat'
  
end
  1. Voer pod install uit.

  2. Open het .xcworkspace bestand met Xcode.

Toegang tot de microfoon aanvragen

Als u toegang wilt krijgen tot de microfoon van het apparaat, moet u de eigenschappenlijst van de app bijwerken met een NSMicrophoneUsageDescription. U stelt de gekoppelde waarde in op een string waarde die is opgenomen in het dialoogvenster dat het systeem gebruikt om toegang van de gebruiker aan te vragen.

Selecteer onder het doel het Info tabblad en voeg een tekenreeks toe voor 'Privacy - Beschrijving van microfoongebruik'

Schermopname van het toevoegen van microfoongebruik in Xcode.

Sandboxing van gebruikersscript uitschakelen

Sommige scripts in de gekoppelde bibliotheken schrijven bestanden tijdens het buildproces. Als u dit wilt toestaan, schakelt u de sandboxing van gebruikersscripts uit in Xcode. Zoek onder de build-instellingen naar sandbox en stel deze in op User Script Sandboxing No.

Schermopname van het uitschakelen van sandboxing van gebruikersscripts in Xcode.

Deelnemen aan de vergaderingschat

Een Communication Services-gebruiker kan deelnemen aan een Teams-vergadering als anonieme gebruiker met behulp van de Calling SDK. Zodra een gebruiker deelneemt aan de Teams-vergadering, kan hij of zij berichten verzenden en ontvangen met andere deelnemers aan de vergadering. De gebruiker heeft geen toegang tot chatberichten die zijn verzonden voordat hij deelneemt, en kan ook geen berichten verzenden of ontvangen wanneer ze niet in de vergadering zijn. Als u wilt deelnemen aan de vergadering en wilt chatten, kunt u de volgende stappen volgen.

Stel het app-framework in

Importeer de Azure Communication-pakketten door ContentView.swift het volgende codefragment toe te voegen:

import AVFoundation
import SwiftUI

import AzureCommunicationCalling
import AzureCommunicationChat

Voeg ContentView.swift het volgende fragment toe, net boven de struct ContentView: View declaratie:

let endpoint = "<ADD_YOUR_ENDPOINT_URL_HERE>"
let token = "<ADD_YOUR_USER_TOKEN_HERE>"
let displayName: String = "Quickstart User"

Vervang <ADD_YOUR_ENDPOINT_URL_HERE> door het eindpunt voor uw Communication Services-resource. Vervang <ADD_YOUR_USER_TOKEN_HERE> door het hierboven gegenereerde token via de Opdrachtregel van de Azure-client. Meer informatie over tokens voor gebruikerstoegang: Token voor gebruikerstoegang

Vervang Quickstart User door de weergavenaam die u in de chat wilt gebruiken.

Als u de status wilt opslaan, voegt u de volgende variabelen toe aan de ContentView struct:

  @State var message: String = ""
  @State var meetingLink: String = ""
  @State var chatThreadId: String = ""

  // Calling state
  @State var callClient: CallClient?
  @State var callObserver: CallDelegate?
  @State var callAgent: CallAgent?
  @State var call: Call?

  // Chat state
  @State var chatClient: ChatClient?
  @State var chatThreadClient: ChatThreadClient?
  @State var chatMessage: String = ""
  @State var meetingMessages: [MeetingMessage] = []

Nu gaan we de hoofdtekst var toevoegen om de UI-elementen vast te houden. In deze quickstart voegen we bedrijfslogica toe aan deze besturingselementen. Voeg de volgende code toe aan de ContentView struct:

var body: some View {
    NavigationView {
      Form {
        Section {
          TextField("Teams Meeting URL", text: $meetingLink)
            .onChange(of: self.meetingLink, perform: { value in
              if let threadIdFromMeetingLink = getThreadId(from: value) {
                self.chatThreadId = threadIdFromMeetingLink
              }
            })
          TextField("Chat thread ID", text: $chatThreadId)
        }
        Section {
          HStack {
            Button(action: joinMeeting) {
              Text("Join Meeting")
            }.disabled(
              chatThreadId.isEmpty || callAgent == nil || call != nil
            )
            Spacer()
            Button(action: leaveMeeting) {
              Text("Leave Meeting")
            }.disabled(call == nil)
          }
          Text(message)
        }
        Section {
          ForEach(meetingMessages, id: \.id) { message in
            let currentUser: Bool = (message.displayName == displayName)
            let foregroundColor = currentUser ? Color.white : Color.black
            let background = currentUser ? Color.blue : Color(.systemGray6)
            let alignment = currentUser ? HorizontalAlignment.trailing : .leading
            
            HStack {
              if currentUser {
                Spacer()
              }
              VStack(alignment: alignment) {
                Text(message.displayName).font(Font.system(size: 10))
                Text(message.content)
                  .frame(maxWidth: 200)
              }

              .padding(8)
              .foregroundColor(foregroundColor)
              .background(background)
              .cornerRadius(8)

              if !currentUser {
                Spacer()
              }
            }
          }
          .frame(maxWidth: .infinity)
        }

        TextField("Enter your message...", text: $chatMessage)
        Button(action: sendMessage) {
          Text("Send Message")
        }.disabled(chatThreadClient == nil)
      }

      .navigationBarTitle("Teams Chat Interop")
    }

    .onAppear {
      // Handle initialization of the call and chat clients
    }
  }

De ChatClient initialiseren

Instantiëren ChatClient en berichtenmeldingen inschakelen. We gebruiken realtime meldingen voor het ontvangen van chatberichten.

Nu de hoofdtekst is ingesteld, voegen we de functies toe om de installatie van de gespreks- en chatclients af te handelen.

Voeg in de onAppear functie de volgende code toe om de CallClient en ChatClient:

  if let threadIdFromMeetingLink = getThreadId(from: self.meetingLink) {
    self.chatThreadId = threadIdFromMeetingLink
  }
  // Authenticate
  do {
    let credentials = try CommunicationTokenCredential(token: token)
    self.callClient = CallClient()
    self.callClient?.createCallAgent(
      userCredential: credentials
    ) { agent, error in
      if let e = error {
        self.message = "ERROR: It was not possible to create a call agent."
        print(e)
        return
      } else {
        self.callAgent = agent
      }
    }
  
    // Start the chat client
    self.chatClient = try ChatClient(
      endpoint: endpoint,
      credential: credentials,
      withOptions: AzureCommunicationChatClientOptions()
    )
    // Register for real-time notifications
    self.chatClient?.startRealTimeNotifications { result in
      switch result {
      case .success:
        self.chatClient?.register(
          event: .chatMessageReceived,
          handler: receiveMessage
      )
      case let .failure(error):
        self.message = "Could not register for message notifications: " + error.localizedDescription
        print(error)
      }
    }
  } catch {
    print(error)
    self.message = error.localizedDescription
  }

De functie Deelnemen aan vergadering toevoegen

Voeg de volgende functie toe aan de ContentView struct om deel te nemen aan de vergadering.

  func joinMeeting() {
    // Ask permissions
    AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
      if granted {
        let teamsMeetingLink = TeamsMeetingLinkLocator(
          meetingLink: self.meetingLink
        )
        self.callAgent?.join(
          with: teamsMeetingLink,
          joinCallOptions: JoinCallOptions()
        ) {(call, error) in
          if let e = error {
            self.message = "Failed to join call: " + e.localizedDescription
            print(e.localizedDescription)
            return
          }

          self.call = call
          self.callObserver = CallObserver(self)
          self.call?.delegate = self.callObserver
          self.message = "Teams meeting joined successfully"
        }
      } else {
        self.message = "Not authorized to use mic"
      }
    }
  }

De ChatThreadClient initialiseren

We initialiseren de ChatThreadClient initialisatie nadat de gebruiker deelneemt aan de vergadering. Hiervoor moeten we de status van de vergadering van de gedelegeerde controleren en vervolgens de ChatThreadClient status initialiseren met de threadId wanneer deze aan de vergadering is toegevoegd.

Maak de connectChat() functie met de volgende code:

  func connectChat() {
    do {
      self.chatThreadClient = try chatClient?.createClient(
        forThread: self.chatThreadId
      )
      self.message = "Joined meeting chat successfully"
    } catch {
      self.message = "Failed to join the chat thread: " + error.localizedDescription
    }
  }

Voeg indien mogelijk de volgende helperfunctie toe aan de ContentView, die wordt gebruikt om de chatthread-id te parseren vanuit de koppeling naar de vergadering van het team. In het geval dat deze extractie mislukt, moet de gebruiker de chatthread-id handmatig invoeren met behulp van Graph-API's om de thread-id op te halen.

 func getThreadId(from teamsMeetingLink: String) -> String? {
  if let range = teamsMeetingLink.range(of: "meetup-join/") {
    let thread = teamsMeetingLink[range.upperBound...]
    if let endRange = thread.range(of: "/")?.lowerBound {
      return String(thread.prefix(upTo: endRange))
    }
  }
  return nil
}

Verzenden van berichten inschakelen

Voeg de sendMessage() functie toe aan ContentView. Deze functie gebruikt de ChatThreadClient functie om berichten van de gebruiker te verzenden.

func sendMessage() {
  let message = SendChatMessageRequest(
    content: self.chatMessage,
    senderDisplayName: displayName,
    type: .text
  )

  self.chatThreadClient?.send(message: message) { result, _ in
    switch result {
    case .success:
    print("Chat message sent")
    self.chatMessage = ""

    case let .failure(error):
    self.message = "Failed to send message: " + error.localizedDescription + "\n Has your token expired?"
    }
  }
}

Ontvangende berichten inschakelen

Voor het ontvangen van berichten implementeren we de handler voor ChatMessageReceived gebeurtenissen. Wanneer nieuwe berichten naar de thread worden verzonden, voegt deze handler de berichten toe aan de meetingMessages variabele, zodat ze in de gebruikersinterface kunnen worden weergegeven.

Voeg eerst de volgende struct toe aan ContentView.swift. De gebruikersinterface gebruikt de gegevens in de struct om onze chatberichten weer te geven.

struct MeetingMessage: Identifiable {
  let id: String
  let date: Date
  let content: String
  let displayName: String

  static func fromTrouter(event: ChatMessageReceivedEvent) -> MeetingMessage {
    let displayName: String = event.senderDisplayName ?? "Unknown User"
    let content: String = event.message.replacingOccurrences(
      of: "<[^>]+>", with: "",
      options: String.CompareOptions.regularExpression
    )
    return MeetingMessage(
      id: event.id,
      date: event.createdOn?.value ?? Date(),
      content: content,
      displayName: displayName
    )
  }
}

Voeg vervolgens de receiveMessage() functie toe aan ContentView. Dit wordt aangeroepen wanneer er een berichten gebeurtenis plaatsvindt. Houd er rekening mee dat u zich moet registreren voor alle gebeurtenissen die u via de methode in de switch chatClient?.register() instructie wilt verwerken.

  func receiveMessage(event: TrouterEvent) -> Void {
    switch event {
    case let .chatMessageReceivedEvent(messageEvent):
      let message = MeetingMessage.fromTrouter(event: messageEvent)
      self.meetingMessages.append(message)

      /// OTHER EVENTS
      //    case .realTimeNotificationConnected:
      //    case .realTimeNotificationDisconnected:
      //    case .typingIndicatorReceived(_):
      //    case .readReceiptReceived(_):
      //    case .chatMessageEdited(_):
      //    case .chatMessageDeleted(_):
      //    case .chatThreadCreated(_):
      //    case .chatThreadPropertiesUpdated(_):
      //    case .chatThreadDeleted(_):
      //    case .participantsAdded(_):
      //    case .participantsRemoved(_):

    default:
      break
    }
  }

Ten slotte moeten we de gemachtigde handler implementeren voor de oproepclient. Deze handler wordt gebruikt om de oproepstatus te controleren en de chatclient te initialiseren wanneer de gebruiker deelneemt aan de vergadering.

class CallObserver : NSObject, CallDelegate {
  private var owner: ContentView

  init(_ view: ContentView) {
    owner = view
  }

  func call(
    _ call: Call,
    didChangeState args: PropertyChangedEventArgs
  ) {
    owner.message = CallObserver.callStateToString(state: call.state)
    if call.state == .disconnected {
      owner.call = nil
      owner.message = "Left Meeting"
    } else if call.state == .inLobby {
      owner.message = "Waiting in lobby (go let them in!)"
    } else if call.state == .connected {
      owner.message = "Connected"
      owner.connectChat()
    }
  }

  private static func callStateToString(state: CallState) -> String {
    switch state {
    case .connected: return "Connected"
    case .connecting: return "Connecting"
    case .disconnected: return "Disconnected"
    case .disconnecting: return "Disconnecting"
    case .earlyMedia: return "EarlyMedia"
    case .none: return "None"
    case .ringing: return "Ringing"
    case .inLobby: return "InLobby"
    default: return "Unknown"
    }
  }
}

De chat verlaten

Wanneer de gebruiker de vergadering van het team verlaat, wissen we de chatberichten uit de gebruikersinterface en hangen we het gesprek op. De volledige code wordt hieronder weergegeven.

  func leaveMeeting() {
    if let call = self.call {
      self.chatClient?.unregister(event: .chatMessageReceived)
      self.chatClient?.stopRealTimeNotifications()

      call.hangUp(options: nil) { (error) in
        if let e = error {
          self.message = "Leaving Teams meeting failed: " + e.localizedDescription
        } else {
          self.message = "Leaving Teams meeting was successful"
        }
      }
      self.meetingMessages.removeAll()
    } else {
      self.message = "No active call to hangup"
    }
  }

Een chatgesprek in een Teams-vergadering ophalen voor een Communication Services-gebruiker

De details van de Teams-vergadering kunnen worden opgehaald met behulp van Graph-API's, zoals beschreven in de Graph-documentatie. De Communication Services Calling SDK accepteert een volledige koppeling naar Teams-vergaderingen of een vergaderings-id. Ze worden geretourneerd als onderdeel van de onlineMeeting resource, toegankelijk onder de joinWebUrl eigenschap

Met de Graph-API's kunt u ook de threadID. Het antwoord heeft een chatInfo object dat de threadID.

De code uitvoeren

Voer de toepassing uit.

Als u wilt deelnemen aan de Teams-vergadering, voert u de koppeling naar de vergadering van uw team in de gebruikersinterface in.

Nadat u deelneemt aan de vergadering van het team, moet u de gebruiker toelaten tot de vergadering in de klant van uw team. Zodra de gebruiker is toegelaten en lid is geworden van de chat, kunt u berichten verzenden en ontvangen.

Schermopname van de voltooide iOS-toepassing.

Notitie

Bepaalde functies worden momenteel niet ondersteund voor interoperabiliteitsscenario's met Teams. Meer informatie over de ondersteunde functies vindt u in teams-vergadermogelijkheden voor externe Teams-gebruikers

In deze quickstart leert u hoe u kunt chatten in een Teams-vergadering met behulp van de Azure Communication Services Chat SDK voor Android.

Voorbeeldcode

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Vereisten

Teams-interoperabiliteit inschakelen

Wanneer Communication Services-gebruikers als gastgebruiker deelnemen aan een Teams-vergadering, hebben ze alleen toegang tot de chat van de vergadering als ze deel uitmaken van de Teams-vergaderoproep. Raadpleeg de documentatie voor Teams-interop voor meer informatie over het toevoegen van Communication Services-gebruikers aan een Teams-vergaderoproep.

U moet lid zijn van de organisatie die eigenaar is van beide entiteiten om deze functie te kunnen gebruiken.

Deelnemen aan de vergaderingschat

Zodra Teams-interoperabiliteit is ingeschakeld, kan een Communication Services-gebruiker deelnemen aan de Teams-oproep als externe gebruiker met behulp van de Calling SDK. Als u deelneemt aan het gesprek, voegt u ze ook toe als deelnemer aan de vergaderingschat, waar ze berichten kunnen verzenden en ontvangen met andere gebruikers in het gesprek. De gebruiker heeft geen toegang tot chatberichten die zijn verzonden voordat ze deelnemen aan het gesprek. Als u wilt deelnemen aan de vergadering en wilt chatten, kunt u de volgende stappen volgen.

Chat toevoegen aan de teams-app voor bellen

Voeg op moduleniveau build.gradlede afhankelijkheid van de chat-SDK toe.

Belangrijk

Bekend probleem: wanneer u android chat en calling SDK samen in dezelfde toepassing gebruikt, werkt de functie voor realtime meldingen van de Chat SDK niet. U krijgt een probleem met afhankelijkheidsoplossing. Terwijl we aan een oplossing werken, kunt u de functie voor realtime meldingen uitschakelen door de volgende uitsluitingen toe te voegen aan de Chat SDK-afhankelijkheid in het bestand van build.gradle de app:

implementation ("com.azure.android:azure-communication-chat:2.0.3") {
    exclude group: 'com.microsoft', module: 'trouter-client-android'
}

De indeling van de Teams-gebruikersinterface toevoegen

Vervang de code in activity_main.xml door het volgende codefragment. Hiermee worden invoer toegevoegd voor de thread-id en voor het verzenden van berichten, een knop voor het verzenden van het getypte bericht en een eenvoudige chatindeling.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/teams_meeting_thread_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="128dp"
        android:ems="10"
        android:hint="Meeting Thread Id"
        android:inputType="textUri"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/teams_meeting_link"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="64dp"
        android:ems="10"
        android:hint="Teams meeting link"
        android:inputType="textUri"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/button_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/teams_meeting_thread_id">

        <Button
            android:id="@+id/join_meeting_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Join Meeting" />

        <Button
            android:id="@+id/hangup_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hangup" />

    </LinearLayout>

    <TextView
        android:id="@+id/call_status_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="40dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/recording_status_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ScrollView
        android:id="@+id/chat_box"
        android:layout_width="374dp"
        android:layout_height="294dp"
        android:layout_marginTop="40dp"
        android:layout_marginBottom="20dp"
        app:layout_constraintBottom_toTopOf="@+id/send_message_button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_layout"
        android:orientation="vertical"
        android:gravity="bottom"
        android:layout_gravity="bottom"
        android:fillViewport="true">

        <LinearLayout
            android:id="@+id/chat_box_layout"
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="bottom"
            android:layout_gravity="top"
            android:layout_alignParentBottom="true"/>
    </ScrollView>

    <EditText
        android:id="@+id/message_body"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="588dp"
        android:ems="10"
        android:inputType="textUri"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Type your message here..."
        tools:visibility="invisible" />

    <Button
        android:id="@+id/send_message_button"
        android:layout_width="138dp"
        android:layout_height="45dp"
        android:layout_marginStart="133dp"
        android:layout_marginTop="48dp"
        android:layout_marginEnd="133dp"
        android:text="Send Message"
        android:visibility="invisible"
        app:layout_constraintBottom_toTopOf="@+id/recording_status_bar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.428"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/chat_box" />

</androidx.constraintlayout.widget.ConstraintLayout>

De besturingselementen voor de gebruikersinterface van Teams inschakelen

Pakketten importeren en statusvariabelen definiëren

Voeg de volgende importbewerkingen toe aan de inhoud van MainActivity.java:

import android.graphics.Typeface;
import android.graphics.Color;
import android.text.Html;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.List;
import com.azure.android.communication.chat.ChatThreadAsyncClient;
import com.azure.android.communication.chat.ChatThreadClientBuilder;
import com.azure.android.communication.chat.models.ChatMessage;
import com.azure.android.communication.chat.models.ChatMessageType;
import com.azure.android.communication.chat.models.ChatParticipant;
import com.azure.android.communication.chat.models.ListChatMessagesOptions;
import com.azure.android.communication.chat.models.SendChatMessageOptions;
import com.azure.android.communication.common.CommunicationIdentifier;
import com.azure.android.communication.common.CommunicationUserIdentifier;
import com.azure.android.core.rest.util.paging.PagedAsyncStream;
import com.azure.android.core.util.AsyncStreamHandler;

Voeg de volgende variabelen toe aan de MainActivity klasse:

    // InitiatorId is used to differentiate incoming messages from outgoing messages
    private static final String InitiatorId = "<USER_ID>";
    private static final String ResourceUrl = "<COMMUNICATION_SERVICES_RESOURCE_ENDPOINT>";
    private String threadId;
    private ChatThreadAsyncClient chatThreadAsyncClient;
    
    // The list of ids corresponsding to messages which have already been processed
    ArrayList<String> chatMessages = new ArrayList<>();

Vervang <USER_ID> door de id van de gebruiker die de chat start. Vervang <COMMUNICATION_SERVICES_RESOURCE_ENDPOINT> door het eindpunt voor uw Communication Services-resource.

De ChatThreadClient initialiseren

Nadat u deelneemt aan de vergadering, instantieert u de ChatThreadClient chatonderdelen en maakt u deze zichtbaar.

Werk het einde van de MainActivity.joinTeamsMeeting() methode bij met de onderstaande code:

    private void joinTeamsMeeting() {
        ...
        EditText threadIdView = findViewById(R.id.teams_meeting_thread_id);
        threadId = threadIdView.getText().toString();
        // Initialize Chat Thread Client
        chatThreadAsyncClient = new ChatThreadClientBuilder()
                .endpoint(ResourceUrl)
                .credential(new CommunicationTokenCredential(UserToken))
                .chatThreadId(threadId)
                .buildAsyncClient();
        Button sendMessageButton = findViewById(R.id.send_message_button);
        EditText messageBody = findViewById(R.id.message_body);
        // Register the method for sending messages and toggle the visibility of chat components
        sendMessageButton.setOnClickListener(l -> sendMessage());
        sendMessageButton.setVisibility(View.VISIBLE);
        messageBody.setVisibility(View.VISIBLE);
        
        // Start the polling for chat messages immediately
        handler.post(runnable);
    }

Verzenden van berichten inschakelen

Voeg de sendMessage() methode toe aan MainActivity. Het maakt gebruik van het ChatThreadClient verzenden van berichten namens de gebruiker.

    private void sendMessage() {
        // Retrieve the typed message content
        EditText messageBody = findViewById(R.id.message_body);
        // Set request options and send message
        SendChatMessageOptions options = new SendChatMessageOptions();
        options.setContent(messageBody.getText().toString());
        options.setSenderDisplayName("Test User");
        chatThreadAsyncClient.sendMessage(options);
        // Clear the text box
        messageBody.setText("");
    }

Polling inschakelen voor berichten en weergeven in de toepassing

Belangrijk

Bekend probleem: omdat de functie voor realtime meldingen van de Chat SDK niet samenwerkt met de aanroepende SDK's, moeten we de GetMessages API met vooraf gedefinieerde intervallen peilen. In ons voorbeeld gebruiken we intervallen van 3 seconden.

We kunnen de volgende gegevens ophalen uit de berichtenlijst die door de GetMessages API wordt geretourneerd:

  • De text en html berichten in de thread sinds het samenvoegen
  • Wijzigingen in het threadrooster
  • Updates voor het threadonderwerp

Voeg aan de MainActivity klasse een handler en een uitvoerbare taak toe die met intervallen van drie seconden wordt uitgevoerd:

    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                retrieveMessages();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // Repeat every 3 seconds
            handler.postDelayed(runnable, 3000);
        }
    };

Houd er rekening mee dat de taak al is gestart aan het einde van de MainActivity.joinTeamsMeeting() methode die in de initialisatiestap is bijgewerkt.

Ten slotte voegen we de methode toe voor het opvragen van alle toegankelijke berichten in de thread, waarbij ze worden geparsereerd op berichttype en de html berichten text worden weergegeven:

    private void retrieveMessages() throws InterruptedException {
        // Initialize the list of messages not yet processed
        ArrayList<ChatMessage> newChatMessages = new ArrayList<>();
        
        // Retrieve all messages accessible to the user
        PagedAsyncStream<ChatMessage> messagePagedAsyncStream
                = this.chatThreadAsyncClient.listMessages(new ListChatMessagesOptions(), null);
        // Set up a lock to wait until all returned messages have been inspected
        CountDownLatch latch = new CountDownLatch(1);
        // Traverse the returned messages
        messagePagedAsyncStream.forEach(new AsyncStreamHandler<ChatMessage>() {
            @Override
            public void onNext(ChatMessage message) {
                // Messages that should be displayed in the chat
                if ((message.getType().equals(ChatMessageType.TEXT)
                    || message.getType().equals(ChatMessageType.HTML))
                    && !chatMessages.contains(message.getId())) {
                    newChatMessages.add(message);
                    chatMessages.add(message.getId());
                }
                if (message.getType().equals(ChatMessageType.PARTICIPANT_ADDED)) {
                    // Handle participants added to chat operation
                    List<ChatParticipant> participantsAdded = message.getContent().getParticipants();
                    CommunicationIdentifier participantsAddedBy = message.getContent().getInitiatorCommunicationIdentifier();
                }
                if (message.getType().equals(ChatMessageType.PARTICIPANT_REMOVED)) {
                    // Handle participants removed from chat operation
                    List<ChatParticipant> participantsRemoved = message.getContent().getParticipants();
                    CommunicationIdentifier participantsRemovedBy = message.getContent().getInitiatorCommunicationIdentifier();
                }
                if (message.getType().equals(ChatMessageType.TOPIC_UPDATED)) {
                    // Handle topic updated
                    String newTopic = message.getContent().getTopic();
                    CommunicationIdentifier topicUpdatedBy = message.getContent().getInitiatorCommunicationIdentifier();
                }
            }
            @Override
            public void onError(Throwable throwable) {
                latch.countDown();
            }
            @Override
            public void onComplete() {
                latch.countDown();
            }
        });
        // Wait until the operation completes
        latch.await(1, TimeUnit.MINUTES);
        // Returned messages should be ordered by the createdOn field to be guaranteed a proper chronological order
        // For the purpose of this demo we will just reverse the list of returned messages
        Collections.reverse(newChatMessages);
        for (ChatMessage chatMessage : newChatMessages)
        {
            LinearLayout chatBoxLayout = findViewById(R.id.chat_box_layout);
            // For the purpose of this demo UI, we don't need to use HTML formatting for displaying messages
            // The Teams client always sends html messages in meeting chats 
            String message = Html.fromHtml(chatMessage.getContent().getMessage(), Html.FROM_HTML_MODE_LEGACY).toString().trim();
            TextView messageView = new TextView(this);
            messageView.setText(message);
            // Compare with sender identifier and align LEFT/RIGHT accordingly
            // Azure Communication Services users are of type CommunicationUserIdentifier
            CommunicationIdentifier senderId = chatMessage.getSenderCommunicationIdentifier();
            if (senderId instanceof CommunicationUserIdentifier
                && InitiatorId.equals(((CommunicationUserIdentifier) senderId).getId())) {
                messageView.setTextColor(Color.GREEN);
                messageView.setGravity(Gravity.RIGHT);
            } else {
                messageView.setTextColor(Color.BLUE);
                messageView.setGravity(Gravity.LEFT);
            }
            // Note: messages with the deletedOn property set to a timestamp, should be marked as deleted
            // Note: messages with the editedOn property set to a timestamp, should be marked as edited
            messageView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
            chatBoxLayout.addView(messageView);
        }
    }

Weergavenamen van de deelnemers aan de chatthread worden niet ingesteld door de Teams-client. De namen worden geretourneerd als null in de API voor het weergeven van deelnemers, in de participantsAdded gebeurtenis en in de participantsRemoved gebeurtenis. De weergavenamen van de chatdeelnemers kunnen worden opgehaald uit het remoteParticipants veld van het call object.

Een chatgesprek in een Teams-vergadering ophalen voor een Communication Services-gebruiker

De details van de Teams-vergadering kunnen worden opgehaald met behulp van Graph-API's, zoals beschreven in de Graph-documentatie. De Communication Services Calling SDK accepteert een volledige koppeling naar Teams-vergaderingen of een vergaderings-id. Ze worden geretourneerd als onderdeel van de onlineMeeting resource, toegankelijk onder de joinWebUrl eigenschap

Met de Graph-API's kunt u ook de threadID. Het antwoord heeft een chatInfo object dat de threadID.

De code uitvoeren

De app kan nu worden gestart met behulp van de knop App uitvoeren op de werkbalk (Shift + F10).

Als u wilt deelnemen aan de Teams-vergadering en -chat, voert u de koppeling naar uw teamvergadering en de thread-id in de gebruikersinterface in.

Nadat u deelneemt aan de vergadering van het team, moet u de gebruiker toelaten tot de vergadering in de klant van uw team. Zodra de gebruiker is toegelaten en lid is geworden van de chat, kunt u berichten verzenden en ontvangen.

Schermopname van de voltooide Android-toepassing.

Notitie

Bepaalde functies worden momenteel niet ondersteund voor interoperabiliteitsscenario's met Teams. Meer informatie over de ondersteunde functies vindt u in teams-vergadermogelijkheden voor externe Teams-gebruikers

In deze quickstart leert u hoe u kunt chatten in een Teams-vergadering met behulp van de Azure Communication Services Chat SDK voor C#.

Voorbeeldcode

Zoek de code voor deze quickstart op GitHub.

Vereisten

Deelnemen aan de vergaderingschat

Een Communication Services-gebruiker kan deelnemen aan een Teams-vergadering als anonieme gebruiker met behulp van de Calling SDK. Als u deelneemt aan de vergadering, worden ze ook toegevoegd als deelnemer aan de vergaderingschat, waar ze berichten kunnen verzenden en ontvangen met andere gebruikers in de vergadering. De gebruiker heeft geen toegang tot chatberichten die zijn verzonden voordat ze deelnemen aan de vergadering en ze kunnen geen berichten verzenden of ontvangen nadat de vergadering is beëindigd. Als u wilt deelnemen aan de vergadering en wilt chatten, kunt u de volgende stappen volgen.

De code uitvoeren

U kunt de code bouwen en uitvoeren in Visual Studio. Let op de oplossingsplatformen die we ondersteunen: x64,x86, en ARM64.

  1. Open een exemplaar van PowerShell, Windows Terminal, opdrachtprompt of gelijkwaardig en navigeer naar de map waarnaar u het voorbeeld wilt klonen.
  2. git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git
  3. Open het project ChatTeamsInteropQuickStart/ChatTeamsInteropQuickStart.csproj in Visual Studio.
  4. Installeer de volgende NuGet-pakketten (of hoger):
Install-Package Azure.Communication.Calling -Version 1.0.0-beta.29
Install-Package Azure.Communication.Chat -Version 1.1.0
Install-Package Azure.Communication.Common -Version 1.0.1
Install-Package Azure.Communication.Identity -Version 1.0.1

  1. Voeg de connectionstring toe aan het bestand ChatTeamsInteropQuickStart/MainPage.xaml.cs wanneer de Communication Services-resource is aangeschaft in de vereisten.
//Azure Communication Services resource connection string, i.e., = "endpoint=https://your-resource.communication.azure.net/;accesskey=your-access-key";
private const string connectionString_ = "";

Belangrijk

  • Selecteer het juiste platform in de vervolgkeuzelijst Oplossingsplatforms in Visual Studio voordat u de code uitvoert, bijvoorbeeld x64
  • Zorg ervoor dat de ontwikkelaarsmodus is ingeschakeld in Windows 10 (Developer Instellingen)

De volgende stappen werken niet als dit niet juist is geconfigureerd

  1. Druk op F5 om het project te starten in de foutopsporingsmodus.
  2. Plak een geldige koppeling naar een teams-vergadering in het vak Koppeling naar Teams-vergadering (zie de volgende sectie)
  3. Druk op 'Deelnemen aan Teams-vergadering' om te beginnen met chatten.

Belangrijk

Zodra de aanroepende SDK de verbinding tot stand brengt met de teamsvergadering Zie Communication Services voor het aanroepen van de Windows-app, zijn de belangrijkste functies voor het afhandelen van chatbewerkingen: StartPollingForChatMessages en SendMessageButton_Click. Beide codefragmenten bevinden zich in ChatTeamsInteropQuickStart\MainPage.xaml.cs

        /// <summary>
        /// Background task that keeps polling for chat messages while the call connection is established
        /// </summary>
        private async Task StartPollingForChatMessages()
        {
            CommunicationTokenCredential communicationTokenCredential = new(user_token_);
            chatClient_ = new ChatClient(EndPointFromConnectionString(), communicationTokenCredential);
            await Task.Run(async () =>
            {
                keepPolling_ = true;

                ChatThreadClient chatThreadClient = chatClient_.GetChatThreadClient(thread_Id_);
                int previousTextMessages = 0;
                while (keepPolling_)
                {
                    try
                    {
                        CommunicationUserIdentifier currentUser = new(user_Id_);
                        AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
                        SortedDictionary<long, string> messageList = new();
                        int textMessages = 0;
                        string userPrefix;
                        await foreach (ChatMessage message in allMessages)
                        {
                            if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
                            {
                                textMessages++;
                                userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
                                messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{StripHtml(message.Content.Message)}");
                            }
                        }

                        //Update UI just when there are new messages
                        if (textMessages > previousTextMessages)
                        {
                            previousTextMessages = textMessages;
                            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                            {
                                TxtChat.Text = string.Join(Environment.NewLine, messageList.Values.ToList());
                            });

                        }
                        if (!keepPolling_)
                        {
                            return;
                        }

                        await SetInCallState(true);
                        await Task.Delay(3000);
                    }
                    catch (Exception e)
                    {
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                        {
                            _ = new MessageDialog($"An error occurred while fetching messages in PollingChatMessagesAsync(). The application will shutdown. Details : {e.Message}").ShowAsync();
                            throw e;
                        });
                        await SetInCallState(false);
                    }
                }
            });
        }
        private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
        {
            SendMessageButton.IsEnabled = false;
            ChatThreadClient chatThreadClient = chatClient_.GetChatThreadClient(thread_Id_);
            _ = await chatThreadClient.SendMessageAsync(TxtMessage.Text);
            
            TxtMessage.Text = "";
            SendMessageButton.IsEnabled = true;
        }

De koppeling naar teams-vergaderingen kan worden opgehaald met behulp van Graph-API's, zoals beschreven in de Graph-documentatie. Deze koppeling wordt geretourneerd als onderdeel van de onlineMeeting resource, toegankelijk onder de joinWebUrl eigenschap.

U kunt ook de vereiste koppeling voor de vergadering ophalen via de URL van de deelname aan vergadering in de uitnodiging voor de Teams-vergadering zelf. De koppeling naar een Teams-vergadering ziet er ongeveer zo uit: https://teams.microsoft.com/l/meetup-join/meeting_chat_thread_id/1606337455313?context=some_context_here. Als uw teams-koppeling een andere indeling heeft, moet u de thread-id ophalen met behulp van de Graph API.

Schermopname van de voltooide csharp-toepassing.

Notitie

Bepaalde functies worden momenteel niet ondersteund voor interoperabiliteitsscenario's met Teams. Meer informatie over de ondersteunde functies vindt u in teams-vergadermogelijkheden voor externe Teams-gebruikers

Resources opschonen

Als u een Communication Services-abonnement wilt opschonen en verwijderen, kunt u de resource of resourcegroep verwijderen. Als u de resourcegroep verwijdert, worden ook alle bijbehorende resources verwijderd. Meer informatie over het opschonen van resources.

Volgende stappen

Raadpleeg voor meer informatie de volgende artikelen: