Démarrage rapide : Joindre votre application de conversation à une réunion Teams
Démarrez avec Azure Communication Services en connectant votre solution de conversation à Microsoft Teams.
Dans ce guide de démarrage rapide, vous allez découvrir comment rejoindre une conversation dans une réunion Teams à l’aide du kit SDK Conversation Azure Communication Services pour JavaScript.
Exemple de code
Vous trouverez le code finalisé pour ce guide de démarrage rapide sur GitHub.
Prérequis
- Un déploiement de Teams
- Application de conversation opérationnelle.
Participation à la conversation d’une réunion
Un utilisateur de Communication Services peut participer à une réunion Teams en tant qu’utilisateur anonyme à l’aide du kit de développement logiciel (SDK) Appel. En rejoignant la réunion, il est également ajouté comme participant à la conversation de la réunion, où il peut échanger des messages avec d’autres utilisateurs connectés. L’utilisateur n’aura pas accès aux messages de la conversation envoyés avant qu’il rejoigne la réunion. Il ne pourra pas non plus envoyer ni recevoir des messages une fois la réunion terminée. Pour participer à la réunion et commencer à converser, vous pouvez suivre les étapes suivantes.
Création d’une application Node.js
Ouvrez votre fenêtre de terminal ou de commande, créez un répertoire pour votre application, puis accédez-y.
mkdir chat-interop-quickstart && cd chat-interop-quickstart
Exécutez npm init -y
pour créer un fichier package.json avec les paramètres par défaut.
npm init -y
Installer les packages de chat
Utilisez la commande npm install
pour installer les kits de développement logiciel (SDK) Communication Services pour JavaScript nécessaires.
npm install @azure/communication-common --save
npm install @azure/communication-identity --save
npm install @azure/communication-chat --save
npm install @azure/communication-calling --save
L’option --save
liste la bibliothèque comme dépendance dans votre fichier package.json.
Configurer le framework d’application
Ce guide de démarrage rapide utilise Webpack pour regrouper les ressources de l’application. Exécutez la commande suivante pour installer les packages npm webpack, webpack-cli et webpack-dev-server, puis listez-les comme dépendances de développement dans votre fichier package.json :
npm install webpack@5.89.0 webpack-cli@5.1.4 webpack-dev-server@4.15.1 --save-dev
Créez un fichier index.html dans le répertoire racine de votre projet. Nous utilisons ce fichier pour configurer une disposition de base qui permettra à l’utilisateur de participer à une réunion et de démarrer une conversation.
Ajouter les contrôles d’interface utilisateur de Teams
Remplacez le code dans index.html par l’extrait de code suivant. La zone de texte en haut de la page sera utilisée pour entrer le contexte de la réunion Teams. Le bouton « Participer à la réunion Teams » est utilisé pour rejoindre la réunion spécifiée. Une fenêtre de conversation contextuelle s’affiche au bas de la page. Elle permet d’envoyer des messages sur le thread de la réunion et affiche en temps réel tous les messages envoyés sur ce thread tant que l’utilisateur Communication Services en est membre.
<!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>
Activer les contrôles d’interface utilisateur de Teams
Remplacez le contenu du fichier client.js par l’extrait de code suivant.
Dans l’extrait de code, remplacez :
SECRET_CONNECTION_STRING
par la chaîne de connexion de votre service de communication ;
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}`);
});
Les noms d’affichage des participants aux conversations ne sont pas définis par le client Teams. La valeur Null est renvoyée dans l’API pour la liste des participants, dans l’événement participantsAdded
et dans l’événement participantsRemoved
. Les noms d’affichage des participants à la conversation peuvent être récupérés dans le champ remoteParticipants
de l’objet call
. Lorsque vous recevez une notification concernant une modification de la liste, vous pouvez utiliser ce code pour récupérer le nom de l’utilisateur qui a été ajouté ou supprimé :
var displayName = call.remoteParticipants.find(p => p.identifier.communicationUserId == '<REMOTE_USER_ID>').displayName;
Exécuter le code
Les utilisateurs de Webpack peuvent utiliser webpack-dev-server
pour générer et exécuter votre application. Exécutez la commande suivante pour créer un bundle de votre application hôte sur un serveur web local :
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Ouvrez votre navigateur et accédez à http://localhost:8080/
. Vous devriez voir l’application lancée, comme illustré dans la capture d’écran suivante :
Insérez le lien de la réunion Teams dans la zone de texte. Appuyez sur Participer à une réunion Teams pour participer à la réunion Teams. Une fois que l’utilisateur Communication Services est admis à la réunion, vous pouvez converser à partir de votre application Azure Communication Services. Accédez à la zone en bas de la page pour commencer la conversation. Par souci de simplicité, l’application n’affiche que les deux derniers messages de la conversation.
Notes
Certaines fonctionnalités ne sont actuellement pas prises en charge pour les scénarios d’interopérabilité avec Teams. Pour en savoir plus sur les fonctionnalités prises en charge, consultez Fonctionnalités de réunion Teams pour les utilisateurs Teams externes.
Dans ce guide de démarrage rapide, vous allez découvrir comment rejoindre une conversation dans une réunion Teams à l’aide du kit SDK Conversation Azure Communication Services pour iOS.
Exemple de code
Si vous souhaitez passer à la fin, vous pouvez télécharger ce guide de démarrage rapide en guise d’exemple sur GitHub.
Prérequis
- Compte Azure avec un abonnement actif. Créez un compte gratuitement.
- Un Mac exécutant Xcode, ainsi qu’un certificat de développeur valide installé dans votre trousseau
- Un déploiement de Teams
- Un jeton d’accès utilisateur pour votre service Azure Communication Vous pouvez également utiliser Azure CLI et exécuter la commande avec votre chaîne de connexion pour créer un utilisateur et un jeton d’accès.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Pour plus d’informations, consultez Utiliser Azure CLI pour créer et gérer des jetons d’accès.
Configuration
Création du projet Xcode
Dans Xcode, créez un projet iOS et sélectionnez le modèle Single View App. Ce tutoriel utilise le framework SwiftUI. Vous devez donc définir Swift comme langage et SwiftUI comme interface utilisateur. Vous n’allez pas créer de tests au cours de ce guide démarrage rapide. N’hésitez pas à décocher Inclure des tests.
Installation de CocoaPods
Utilisez ce guide pour installer CocoaPods sur votre Mac.
Installer le package et les dépendances avec CocoaPods
Pour créer un
Podfile
pour votre application, ouvrez le terminal et accédez au dossier du projet, puis exécutez pod init.Ajoutez le code suivant au
Podfile
sous la cible, puis enregistrez-le.
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
Exécutez
pod install
.Ouvrez le fichier
.xcworkspace
avec Xcode.
Demander l’accès au microphone
Pour accéder au microphone de l’appareil, vous devez mettre à jour la liste des propriétés d’informations de votre application avec un NSMicrophoneUsageDescription
. Vous affectez une valeur string
comme valeur associée qui était incluse dans la boîte de dialogue utilisée par le système pour demander l’accès de l’utilisateur.
Sous la cible, sélectionnez l’onglet Info
et ajoutez une chaîne pour « Confidentialité – Description de l’utilisation du microphone ».
Désactiver le bac à sable de script utilisateur
Certains des scripts dans les bibliothèques liées écrivent des fichiers pendant le processus de génération. Pour autoriser cela, désactivez le bac à sable de script utilisateur dans Xcode.
Sous les paramètres de génération, recherchez sandbox
et affectez la valeur No
à User Script Sandboxing
.
Participation à la conversation d’une réunion
Un utilisateur de Communication Services peut participer à une réunion Teams en tant qu’utilisateur anonyme à l’aide du kit de développement logiciel (SDK) Appel. Une fois qu’un utilisateur a rejoint la réunion Teams, il peut envoyer et recevoir des messages avec d’autres participants à la réunion. L’utilisateur n’aura pas accès aux messages de conversation envoyés avant qu’il n’ait rejoint la réunion, et ne pourra pas non plus envoyer ou recevoir de messages lorsqu’il ne fera plus partie de la réunion. Pour participer à la réunion et commencer à converser, vous pouvez suivre les étapes suivantes.
Configurer le framework d’application
Importez le package Azure Communication dans ContentView.swift
en ajoutant l’extrait de code suivant :
import AVFoundation
import SwiftUI
import AzureCommunicationCalling
import AzureCommunicationChat
Dans ContentView.swift
, ajoutez l’extrait de code suivant, juste au-dessus de la déclaration struct ContentView: View
:
let endpoint = "<ADD_YOUR_ENDPOINT_URL_HERE>"
let token = "<ADD_YOUR_USER_TOKEN_HERE>"
let displayName: String = "Quickstart User"
Remplacez <ADD_YOUR_ENDPOINT_URL_HERE>
par le point de terminaison de votre ressource Communication Services.
Remplacez <ADD_YOUR_USER_TOKEN_HERE>
par le jeton généré ci-dessus, via la ligne de commande du client Azure.
En découvrir plus sur les jetons d’accès utilisateur : Jeton d’accès utilisateur
Remplacez Quickstart User
par le nom complet à utiliser dans la conversation.
Pour stocker l’état, ajoutez les variables suivantes au struct ContentView
:
@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] = []
Nous allons maintenant ajouter la variable du corps principal pour stocker les éléments de l’interface utilisateur. Dans ce démarrage rapide, nous allons attacher une logique métier à ces contrôles. Ajoutez le code suivant au struct ContentView
:
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
}
}
Initialiser le ChatClient
Instanciez le ChatClient
et activez les messages de notification. Nous utilisons des notifications en temps réel pour la réception des messages de conversation.
Le corps principal étant configuré, nous allons maintenant ajouter les fonctions pour gérer la configuration des clients d’appel et de conversation.
Dans la fonction onAppear
, ajoutez le code suivant pour initialiser CallClient
et 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
}
Ajouter une fonction de participation à une réunion
Ajoutez la fonction suivante au struct ContentView
pour gérer la participation à la réunion.
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"
}
}
}
Initialiser le ChatThreadClient
Nous initialiserons le ChatThreadClient
une fois que l’utilisateur aura rejoint la réunion. Cela nous oblige à vérifier l’état de la réunion à partir du délégué, puis à initialiser le ChatThreadClient
avec le threadId
une fois la réunion rejointe.
Créez la fonction connectChat()
avec le code suivant :
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
}
}
Ajoutez la fonction d’assistance suivante au ContentView
, utilisée pour analyser l’ID de thread de conversation à partir du lien de réunion de l’équipe, si possible. Dans le cas où cette extraction échoue, l’utilisateur doit entrer manuellement l’ID de thread de conversation à l’aide des API Graph pour récupérer l’ID de thread.
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
}
Activer l’envoi des messages
Ajoutez la fonction sendMessage()
à ContentView
. Cette fonction utilise ChatThreadClient
pour envoyer les messages de l’utilisateur.
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?"
}
}
}
Activer la réception des messages
Pour recevoir des messages, nous devons implémenter le gestionnaire des événements ChatMessageReceived
. Quand de nouveaux messages sont envoyés au thread, ce gestionnaire ajoute les messages à la variable meetingMessages
afin qu’ils puissent être affichés dans l’interface utilisateur.
Tout d’abord, ajoutez le struct suivant à ContentView.swift
. L’interface utilisateur utilise les données du struct pour afficher les messages de conversation.
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
)
}
}
Ensuite, ajoutez la fonction receiveMessage()
à ContentView
. Cet appel a lieu lorsqu’un événement de messagerie se produit. Notez que vous devez vous inscrire à tous les événements que vous souhaitez gérer dans l’instruction switch
via la méthode chatClient?.register()
.
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
}
}
Pour finir, nous devons implémenter le gestionnaire de délégués pour le client d’appel. Ce gestionnaire est utilisé pour vérifier l’état de l’appel et initialiser le client de conversation lorsque l’utilisateur rejoint la réunion.
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"
}
}
}
Quitter la conversation
Lorsque l’utilisateur quitte la réunion de l’équipe, nous effaçons les messages de conversation de l’interface utilisateur et mettons fin à l’appel. Le code complet est indiqué ci-dessous.
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"
}
}
Obtenir le fil de conversation d’une réunion Teams pour un utilisateur Communication Services
Il est possible de récupérer les détails de la réunion Teams à l’aide d’API Graph décrites dans la Documentation Graph. Le kit SDK Communication Services Calling accepte un lien de réunion Teams complet ou un ID de réunion. Ces informations sont retournées dans le cadre de la ressource onlineMeeting
, accessible sous la propriété joinWebUrl
.
Avec les API Graph, vous pouvez également obtenir la valeur threadID
. La réponse a un objet chatInfo
qui contient le threadID
.
Exécuter le code
Exécutez l'application.
Pour rejoindre la réunion Teams, saisissez le lien de réunion de votre équipe dans l’interface utilisateur.
Une fois que vous avez rejoint la réunion de l’équipe, vous devez autoriser l’utilisateur à participer à la réunion dans le client de votre équipe. Une fois que l’utilisateur est admis et a rejoint la conversation, vous pouvez envoyer et recevoir des messages.
Notes
Certaines fonctionnalités ne sont actuellement pas prises en charge pour les scénarios d’interopérabilité avec Teams. Pour en savoir plus sur les fonctionnalités prises en charge, consultez Fonctionnalités de réunion Teams pour les utilisateurs Teams externes.
Dans ce démarrage rapide, vous allez découvrir comment rejoindre une conversation dans une réunion Teams à l’aide du Kit de développement logiciel (SDK) Conversation Azure Communication Services pour Android.
Exemple de code
Si vous souhaitez passer à la fin, vous pouvez télécharger ce guide de démarrage rapide en guise d’exemple sur GitHub.
Prérequis
- Un déploiement de Teams
- Une application d’appel opérationnelle.
Activer l’interopérabilité de Teams
Un utilisateur Communication Services qui rejoint une réunion Teams en tant qu’utilisateur invité ne peut accéder à la conversation de la réunion qu’après avoir rejoint l’appel de réunion Teams. Consultez la documentation Interopérabilité de Teams pour savoir comment ajouter un utilisateur Communication Services à un appel de réunion Teams.
Vous devez être membre de l’organisation propriétaire des deux entités pour pouvoir utiliser cette fonctionnalité.
Participation à la conversation d’une réunion
Une fois l’interopérabilité de Teams activée, un utilisateur de Communication Services peut rejoindre l’appel Teams en tant qu’utilisateur externe à l’aide du kit de développement logiciel (SDK) Calling. En rejoignant l’appel, il est également ajouté comme participant à la conversation de la réunion, où il peut échanger des messages avec d’autres utilisateurs lors de l’appel. L’utilisateur n’a pas accès aux messages de conversation qui ont été envoyés avant qu’il ne rejoigne l’appel. Pour participer à la réunion et commencer à converser, vous pouvez suivre les étapes suivantes.
Ajouter la conversation à l’application d’appel Teams
Dans votre fichier build.gradle
au niveau du module, ajoutez la dépendance au kit de développement logiciel (SDK) de conversation.
Important
Problème connu : lors de l’utilisation conjointe du chat Android et du Kit de développement logiciel (SDK) d’appel dans la même application, la fonctionnalité de notifications en temps réel du SDK de conversation ne fonctionne pas. Vous obtiendrez un problème de résolution de dépendance. Pendant que nous travaillons sur une solution, vous pouvez désactiver la fonctionnalité de notifications en temps réel en ajoutant les exclusions suivantes à la dépendance du Kit de développement logiciel (SDK) de conversation dans le fichier build.gradle
de l’application :
implementation ("com.azure.android:azure-communication-chat:2.0.3") {
exclude group: 'com.microsoft', module: 'trouter-client-android'
}
Ajouter la disposition de l’interface utilisateur Teams
Remplacez le code dans activity_main.xml par l’extrait de code suivant. Il ajoute des entrées pour l’ID de thread et pour l’envoi de messages, un bouton pour envoyer le message saisi et une disposition de base pour le chat.
<?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>
Activer les contrôles d’interface utilisateur de Teams
Importer des packages et définir des variables d’état
Ajoutez les importations suivantes au contenu de 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;
Ajoutez les variables suivantes à la classe MainActivity
:
// 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<>();
Remplacez <USER_ID>
par l’ID de l’utilisateur qui lance la conversation.
Remplacez <COMMUNICATION_SERVICES_RESOURCE_ENDPOINT>
par le point de terminaison de votre ressource Communication Services.
Initialiser le ChatThreadClient
Après avoir rejoint la réunion, instanciez le ChatThreadClient
et rendez visibles les composants du chat.
Mettez à jour la fin de la méthode MainActivity.joinTeamsMeeting()
avec le code ci-dessous :
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);
}
Activer l’envoi des messages
Ajoutez la méthode sendMessage()
à MainActivity
. Elle utilise le ChatThreadClient
pour envoyer des messages au nom de l’utilisateur.
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("");
}
Activer l’interrogation des messages et leur rendu dans l’application
Important
Problème connu : Dans la mesure où la fonctionnalité de notifications en temps réel du Kit de développement logiciel (SDK) de conversation ne fonctionne pas avec le SDK d’appel, nous devons interroger l’API GetMessages
à des intervalles prédéfinis. Dans notre exemple, nous allons utiliser des intervalles de trois secondes.
Nous pouvons obtenir les données suivantes à partir de la liste des messages renvoyée par l’API GetMessages
:
- Les messages
text
ethtml
sur la conversation depuis qu’elle a été rejointe - Les modifications apportées à la liste des participants à la conversation
- Les mises à jour du sujet de la conversation
Ajoutez à la classe MainActivity
un gestionnaire et une tâche exécutable qui seront exécutés à intervalles de trois secondes :
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);
}
};
Notez que la tâche a déjà été démarrée à la fin de la méthode MainActivity.joinTeamsMeeting()
mise à jour dans l’étape d’initialisation.
Enfin, nous devons ajouter la méthode permettant d’interroger tous les messages accessibles sur la conversation, de les analyser par type de message et d’afficher les messages html
et text
:
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);
}
}
Les noms d’affichage des participants aux conversations ne sont pas définis par le client Teams. La valeur Null est renvoyée dans l’API pour la liste des participants, dans l’événement participantsAdded
et dans l’événement participantsRemoved
. Les noms d’affichage des participants à la conversation peuvent être récupérés dans le champ remoteParticipants
de l’objet call
.
Obtenir le fil de conversation d’une réunion Teams pour un utilisateur Communication Services
Il est possible de récupérer les détails de la réunion Teams à l’aide d’API Graph décrites dans la Documentation Graph. Le kit SDK Communication Services Calling accepte un lien de réunion Teams complet ou un ID de réunion. Ces informations sont retournées dans le cadre de la ressource onlineMeeting
, accessible sous la propriété joinWebUrl
.
Avec les API Graph, vous pouvez également obtenir la valeur threadID
. La réponse a un objet chatInfo
qui contient le threadID
.
Exécuter le code
L’application peut maintenant être lancée à l’aide du bouton « Run App » de la barre d’outils (Maj+F10).
Pour rejoindre la conversation et la réunion Teams, entrez le lien de réunion et l’ID de conversation de votre équipe dans l’interface utilisateur.
Une fois que vous avez rejoint la réunion de l’équipe, vous devez autoriser l’utilisateur à participer à la réunion dans le client de votre équipe. Une fois que l’utilisateur est admis et a rejoint la conversation, vous pouvez envoyer et recevoir des messages.
Notes
Certaines fonctionnalités ne sont actuellement pas prises en charge pour les scénarios d’interopérabilité avec Teams. Pour en savoir plus sur les fonctionnalités prises en charge, consultez Fonctionnalités de réunion Teams pour les utilisateurs Teams externes.
Dans ce démarrage rapide, vous découvrez comment rejoindre une conversation dans une réunion Teams à l’aide du Kit de développement logiciel (SDK) Conversation d'Azure Communication Services pour C#.
Exemple de code
Retrouvez le code ce démarrage rapide sur GitHub.
Prérequis
- Un déploiement de Teams
- Compte Azure avec un abonnement actif. Créez un compte gratuitement.
- Installez Visual Studio 2019 avec la charge de travail de développement pour la plateforme Windows universelle.
- Une ressource Communication Services déployée. Créez une ressource Communication Services.
- Un lien de réunion Teams.
Participation à la conversation d’une réunion
Un utilisateur de Communication Services peut participer à une réunion Teams en tant qu’utilisateur anonyme à l’aide du kit de développement logiciel (SDK) Appel. En rejoignant la réunion, il est également ajouté comme participant à la conversation de la réunion, où il peut échanger des messages avec d’autres utilisateurs connectés. L’utilisateur n’aura pas accès aux messages de la conversation envoyés avant qu’il rejoigne la réunion, et il ne pourra pas non plus envoyer ni recevoir des messages une fois la réunion terminée. Pour participer à la réunion et commencer à converser, vous pouvez suivre les étapes suivantes.
Exécuter le code
Vous pouvez générer et exécuter le code sur Visual Studio. Notez que les plateformes de solution que nous prenons en charge sont : x64
, x86
et ARM64
.
- Ouvrez une instance de PowerShell, de Terminal Windows, une invite de commandes, ou équivalent, puis accédez au répertoire dans lequel vous souhaitez cloner l’exemple.
git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git
- Ouvrez le projet ChatTeamsInteropQuickStart/ChatTeamsInteropQuickStart.csproj dans Visual Studio.
- Installez les versions de packages NuGet suivantes (ou ultérieures) :
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
- À l’aide de la ressource Communication Services obtenue dans les prérequis, ajoutez la chaîne de connexion au fichier ChatTeamsInteropQuickStart/MainPage.xaml.cs.
//Azure Communication Services resource connection string, i.e., = "endpoint=https://your-resource.communication.azure.net/;accesskey=your-access-key";
private const string connectionString_ = "";
Important
- Sélectionnez la plateforme appropriée dans la liste déroulante « Plateformes de solution » dans Visual Studio avant d’exécuter le code, par exemple,
x64
- assurez-vous que le « mode développeur » est activé dans Windows 10 (Paramètres du développeur)
Les étapes suivantes ne fonctionnent pas si cette configuration n’est pas correcte.
- Appuyez sur la touche F5 pour démarrer le projet en mode débogage.
- Collez un lien de réunion Teams valide dans la zone « Lien de réunion Teams » (voir la section suivante).
- Appuyez sur « Rejoindre la réunion Teams » pour commencer la conversation instantanée.
Important
Une fois que le Kit de développement logiciel (SDK) appelant a établi la connexion avec la réunion Teams (voir Communication Services appelant une application Windows ), les fonctions clés pour gérer les opérations de conversation sont : StartPollingForChatMessages et SendMessageButton_Click. Les deux extraits de code se trouvent sous ChatTeamsInteropQuickStart\MainPage.xaml.cs.
/// <summary>
/// Background task that keeps polling for chat messages while the call connection is stablished
/// </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;
}
Obtenir un lien de réunion Teams
Il est possible de récupérer le lien de réunion Teams à l’aide d’API Graph décrites dans la documentation de Graph. Ce lien est retourné dans le cadre de la ressource onlineMeeting
, accessible sous la propriété joinWebUrl
.
Vous pouvez également récupérer le lien de réunion requis à partir de l’URL Rejoindre la réunion disponible dans l’invitation à la réunion Teams elle-même.
Un lien de réunion Teams ressemble à ceci : https://teams.microsoft.com/l/meetup-join/meeting_chat_thread_id/1606337455313?context=some_context_here
.
Si le lien de votre équipe a un format différent, vous devez récupérer l’identifiant de la conversation à l’aide de l’API Graph.
Notes
Certaines fonctionnalités ne sont actuellement pas prises en charge pour les scénarios d’interopérabilité avec Teams. Pour en savoir plus sur les fonctionnalités prises en charge, consultez Fonctionnalités de réunion Teams pour les utilisateurs Teams externes.
Nettoyer les ressources
Si vous voulez nettoyer et supprimer un abonnement Communication Services, vous pouvez supprimer la ressource ou le groupe de ressources. La suppression du groupe de ressources efface également les autres ressources qui y sont associées. Apprenez-en davantage sur le nettoyage des ressources.
Étapes suivantes
Pour plus d’informations, consultez les articles suivants :
- Consultez notre exemple de bannière de conversation.
- Apprenez-en davantage sur le fonctionnement de la conversation.