Szybki start: dołączanie aplikacji czatu do spotkania usługi Teams
Rozpocznij pracę z usługami Azure Communication Services, łącząc rozwiązanie czatu z usługą Microsoft Teams.
W tym przewodniku Szybki start dowiesz się, jak rozmawiać na spotkaniu w usłudze Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka JavaScript.
Przykładowy kod
Znajdź sfinalizowany kod dla tego przewodnika Szybki start w witrynie GitHub.
Wymagania wstępne
Dołączanie do czatu na spotkaniu
Użytkownik usług Communication Services może dołączyć do spotkania usługi Teams jako anonimowy użytkownik przy użyciu zestawu SDK wywołującego. Dołączenie do spotkania powoduje dodanie ich jako uczestnika do czatu na spotkaniu, gdzie mogą wysyłać i odbierać wiadomości innym użytkownikom na spotkaniu. Użytkownik nie będzie miał dostępu do wiadomości czatu, które zostały wysłane przed dołączeniem do spotkania i nie będzie mógł wysyłać ani odbierać wiadomości po zakończeniu spotkania. Aby dołączyć do spotkania i rozpocząć rozmowę, możesz wykonać następne kroki.
Tworzenie nowej aplikacji Node.js
Otwórz terminal lub okno polecenia, utwórz nowy katalog dla aplikacji i przejdź do niego.
mkdir chat-interop-quickstart && cd chat-interop-quickstart
Uruchom polecenie npm init -y
, aby utworzyć plik package.json z ustawieniami domyślnymi.
npm init -y
Instalowanie pakietów czatów
Użyj polecenia , npm install
aby zainstalować niezbędne zestawy SDK usług Komunikacyjnych dla języka JavaScript.
npm install @azure/communication-common --save
npm install @azure/communication-identity --save
npm install @azure/communication-chat --save
npm install @azure/communication-calling --save
Opcja --save
wyświetla bibliotekę jako zależność w pliku package.json .
Konfigurowanie struktury aplikacji
Ten przewodnik Szybki start używa pakietu WebPack do tworzenia pakietów zasobów aplikacji. Uruchom następujące polecenie, aby zainstalować pakiety Webpack, webpack-cli i webpack-dev-server npm i wyświetlić je jako zależności programistyczne w package.json:
npm install webpack@5.89.0 webpack-cli@5.1.4 webpack-dev-server@4.15.1 --save-dev
Utwórz plik index.html w katalogu głównym projektu. Ten plik służy do konfigurowania podstawowego układu, który umożliwi użytkownikowi dołączenie do spotkania i rozpoczęcie rozmowy.
Dodawanie kontrolek interfejsu użytkownika usługi Teams
Zastąp kod w index.html poniższym fragmentem kodu. Pole tekstowe w górnej części strony będzie używane do wprowadzania kontekstu spotkania usługi Teams. Przycisk "Dołącz do spotkania w aplikacji Teams" służy do dołączania do określonego spotkania. W dolnej części strony zostanie wyświetlone wyskakujące okienko czatu. Może służyć do wysyłania wiadomości w wątku spotkania i wyświetla w czasie rzeczywistym wszystkie komunikaty wysyłane w wątku, gdy użytkownik usług komunikacyjnych jest członkiem.
<!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>
Włączanie kontrolek interfejsu użytkownika usługi Teams
Zastąp zawartość pliku client.js poniższym fragmentem kodu.
W fragmencie kodu zastąp
SECRET_CONNECTION_STRING
z parametry połączenia usługi komunikacyjnej
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}`);
});
Nazwy wyświetlane uczestników wątku czatu nie są ustawiane przez klienta usługi Teams. Nazwy są zwracane jako null w interfejsie API do wyświetlania listy uczestników, w participantsAdded
przypadku i w participantsRemoved
zdarzeniu. Nazwy wyświetlane uczestników czatu można pobrać z remoteParticipants
pola call
obiektu. Po otrzymaniu powiadomienia o zmianie listy możesz użyć tego kodu, aby pobrać nazwę użytkownika, który został dodany lub usunięty:
var displayName = call.remoteParticipants.find(p => p.identifier.communicationUserId == '<REMOTE_USER_ID>').displayName;
Uruchamianie kodu
Użytkownicy pakietu webpack mogą używać elementu webpack-dev-server
do kompilowania i uruchamiania aplikacji. Uruchom następujące polecenie, aby utworzyć pakiet hosta aplikacji na lokalnym serwerze internetowym:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Otwórz przeglądarkę i przejdź do http://localhost:8080/
adresu . Powinna zostać wyświetlona aplikacja uruchomiona, jak pokazano na poniższym zrzucie ekranu:
Wstaw link do spotkania usługi Teams w polu tekstowym. Naciśnij pozycję Dołącz do spotkania usługi Teams, aby dołączyć do spotkania usługi Teams. Po tym, jak użytkownik usług komunikacyjnych został przyjęty na spotkanie, możesz porozmawiać z poziomu aplikacji usług komunikacyjnych. Przejdź do pola w dolnej części strony, aby rozpocząć rozmowę. Dla uproszczenia aplikacja wyświetla tylko dwa ostatnie komunikaty na czacie.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Dowiedz się więcej o obsługiwanych funkcjach, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams
W tym przewodniku Szybki start dowiesz się, jak rozmawiać na spotkaniu w usłudze Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla systemu iOS.
Przykładowy kod
Jeśli chcesz przejść do końca, możesz pobrać ten przewodnik Szybki start jako przykład w usłudze GitHub.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Bezpłatne tworzenie konta
- Komputer Mac z uruchomionym programem Xcode wraz z prawidłowym certyfikatem dewelopera zainstalowanym w pęku kluczy.
- Wdrożenie usługi Teams.
- Token dostępu użytkownika dla usługi Azure Communication Service. Możesz również użyć interfejsu wiersza polecenia platformy Azure i uruchomić polecenie za pomocą parametry połączenia, aby utworzyć użytkownika i token dostępu.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Aby uzyskać szczegółowe informacje, zobacz Tworzenie tokenów dostępu za pomocą interfejsu wiersza polecenia platformy Azure i zarządzanie nimi.
Konfigurowanie
Tworzenie projektu Xcode
W programie Xcode utwórz nowy projekt systemu iOS i wybierz szablon Aplikacja z jednym widokiem. W tym samouczku jest używana struktura SwiftUI, dlatego należy ustawić język na swift i interfejs użytkownika na swiftUI. Podczas tego przewodnika Szybki start nie utworzysz testów. Możesz usunąć zaznaczenie pola wyboru Uwzględnij testy.
Instalowanie platformy CocoaPods
Skorzystaj z tego przewodnika, aby zainstalować narzędzie CocoaPods na komputerze Mac.
Instalowanie pakietu i zależności za pomocą narzędzia CocoaPods
Aby utworzyć aplikację
Podfile
dla aplikacji, otwórz terminal i przejdź do folderu projektu i uruchom init zasobnika.Dodaj następujący kod do obiektu
Podfile
docelowego i zapisz.
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
Uruchom program
pod install
.Otwórz plik za
.xcworkspace
pomocą programu Xcode.
Żądanie dostępu do mikrofonu
Aby uzyskać dostęp do mikrofonu urządzenia, należy zaktualizować listę właściwości informacji aplikacji za pomocą elementu NSMicrophoneUsageDescription
. Skojarzona wartość została ustawiona na string
wartość, która została uwzględniona w oknie dialogowym używanym przez system do żądania dostępu od użytkownika.
W obszarze docelowym wybierz kartę Info
i dodaj ciąg "Prywatność — opis użycia mikrofonu"
Wyłączanie piaskownicy skryptu użytkownika
Niektóre skrypty w połączonych bibliotekach zapisują pliki podczas procesu kompilacji. Aby to umożliwić, wyłącz piaskownicę skryptu użytkownika w środowisku Xcode.
W obszarze ustawień kompilacji wyszukaj sandbox
i ustaw wartość User Script Sandboxing
No
.
Dołączanie do czatu na spotkaniu
Użytkownik usług Communication Services może dołączyć do spotkania usługi Teams jako anonimowy użytkownik przy użyciu zestawu SDK wywołującego. Gdy użytkownik dołączy do spotkania usługi Teams, będzie mógł wysyłać i odbierać wiadomości z innymi uczestnikami spotkania. Użytkownik nie będzie miał dostępu do wiadomości czatu wysyłanych przed dołączeniem ani nie będzie mógł wysyłać ani odbierać wiadomości, gdy nie są w spotkaniu. Aby dołączyć do spotkania i rozpocząć rozmowę, możesz wykonać następne kroki.
Konfigurowanie struktury aplikacji
Zaimportuj pakiety usługi Azure Communication w programie ContentView.swift
, dodając następujący fragment kodu:
import AVFoundation
import SwiftUI
import AzureCommunicationCalling
import AzureCommunicationChat
W ContentView.swift
pliku dodaj następujący fragment kodu tuż nad deklaracją struct ContentView: View
:
let endpoint = "<ADD_YOUR_ENDPOINT_URL_HERE>"
let token = "<ADD_YOUR_USER_TOKEN_HERE>"
let displayName: String = "Quickstart User"
Zastąp <ADD_YOUR_ENDPOINT_URL_HERE>
element punktem końcowym zasobu usług Komunikacyjnych.
Zastąp <ADD_YOUR_USER_TOKEN_HERE>
element tokenem wygenerowany powyżej za pomocą wiersza polecenia klienta platformy Azure.
Dowiedz się więcej na temat tokenów dostępu użytkowników: Token dostępu użytkownika
Zastąp Quickstart User
ciąg nazwą wyświetlaną, której chcesz użyć w czacie.
Aby zachować stan, dodaj następujące zmienne do ContentView
struktury:
@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] = []
Teraz dodajmy główną treść var do przechowywania elementów interfejsu użytkownika. Dołączamy logikę biznesową do tych kontrolek w tym przewodniku Szybki start. Dodaj następujący kod do ContentView
struktury:
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
}
}
Inicjowanie obiektu ChatClient
ChatClient
Utwórz wystąpienie powiadomień i włącz powiadomienia o wiadomościach. Do odbierania wiadomości na czacie używamy powiadomień w czasie rzeczywistym.
Po skonfigurowaniu głównej treści dodajmy funkcje do obsługi konfiguracji klientów rozmów i czatów.
onAppear
W funkcji dodaj następujący kod, aby zainicjować element CallClient
i 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
}
Dodawanie funkcji dołączania do spotkania
Dodaj następującą funkcję do ContentView
struktury, aby obsłużyć dołączanie do spotkania.
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"
}
}
}
Inicjowanie elementu ChatThreadClient
Zainicjujemy ChatThreadClient
element po dołączeniu do spotkania przez użytkownika. Wymaga to sprawdzenia stanu spotkania od delegata, a następnie zainicjowania ChatThreadClient
elementu za threadId
pomocą elementu po dołączeniu do spotkania.
connectChat()
Utwórz funkcję przy użyciu następującego kodu:
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
}
}
Dodaj następującą funkcję pomocnika do ContentView
elementu , używaną do analizowania identyfikatora wątku czatu z linku spotkania zespołu, jeśli jest to możliwe. W przypadku niepowodzenia wyodrębniania użytkownik będzie musiał ręcznie wprowadzić identyfikator wątku czatu przy użyciu interfejsów API programu Graph w celu pobrania identyfikatora wątku.
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
}
Włączanie wysyłania komunikatów
sendMessage()
Dodaj funkcję do ContentView
. Ta funkcja używa elementu ChatThreadClient
do wysyłania komunikatów od użytkownika.
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?"
}
}
}
Włączanie odbierania komunikatów
Aby odbierać komunikaty, implementujemy procedurę obsługi zdarzeń ChatMessageReceived
. Po wysłaniu nowych komunikatów do wątku ta procedura obsługi dodaje komunikaty do meetingMessages
zmiennej, aby mogły być wyświetlane w interfejsie użytkownika.
Najpierw dodaj następującą strukturę do ContentView.swift
. Interfejs użytkownika używa danych w strukturze do wyświetlania naszych wiadomości na czacie.
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
)
}
}
Następnie dodaj receiveMessage()
funkcję do ContentView
. Jest to wywoływane w przypadku wystąpienia zdarzenia obsługi komunikatów. Należy pamiętać, że należy zarejestrować wszystkie zdarzenia, które mają być obsługiwane w instrukcji switch
za pośrednictwem chatClient?.register()
metody .
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
}
}
Na koniec musimy zaimplementować procedurę obsługi delegatów dla klienta wywołania. Ta procedura obsługi służy do sprawdzania stanu połączenia i inicjowania klienta czatu, gdy użytkownik dołącza do spotkania.
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"
}
}
}
Opuść czat
Gdy użytkownik opuści spotkanie zespołu, wyczyścimy wiadomości czatu z interfejsu użytkownika i zawiesimy połączenie. Pełny kod jest pokazany poniżej.
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"
}
}
Pobieranie wątku czatu spotkania usługi Teams dla użytkownika usług Communication Services
Szczegóły spotkania usługi Teams można pobrać przy użyciu interfejsów API programu Graph, szczegółowo opisanych w dokumentacji programu Graph. Zestaw SDK wywołujący usługi Communication Services akceptuje pełny link do spotkania usługi Teams lub identyfikator spotkania. Są one zwracane jako część onlineMeeting
zasobu dostępnego w joinWebUrl
ramach właściwości
Za pomocą interfejsów API programu Graph można również uzyskać threadID
element . Odpowiedź zawiera chatInfo
obiekt zawierający threadID
element .
Uruchamianie kodu
Uruchom aplikację.
Aby dołączyć do spotkania usługi Teams, wprowadź link spotkanie zespołu w interfejsie użytkownika.
Po dołączeniu do spotkania zespołu musisz przyznać użytkownika do spotkania w kliencie zespołu. Gdy użytkownik zostanie przyjęty i dołączy do czatu, możesz wysyłać i odbierać wiadomości.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Dowiedz się więcej o obsługiwanych funkcjach, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams
W tym przewodniku Szybki start dowiesz się, jak rozmawiać na spotkaniu w usłudze Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla systemu Android.
Przykładowy kod
Jeśli chcesz przejść do końca, możesz pobrać ten przewodnik Szybki start jako przykład w usłudze GitHub.
Wymagania wstępne
Włączanie współdziałania usługi Teams
Użytkownik usług Communication Services, który dołącza do spotkania usługi Teams jako użytkownik-gość, może uzyskać dostęp do czatu spotkania tylko wtedy, gdy dołączyli do rozmowy ze spotkaniem usługi Teams. Zapoznaj się z dokumentacją międzyoperajności usługi Teams, aby dowiedzieć się, jak dodać użytkownika usług Communication Services do połączenia konferencyjnego usługi Teams.
Aby korzystać z tej funkcji, musisz być członkiem organizacji, która jest właścicielem obu jednostek.
Dołączanie do czatu na spotkaniu
Po włączeniu współdziałania usługi Teams użytkownik usług Communication Services może dołączyć do wywołania usługi Teams jako użytkownik zewnętrzny przy użyciu zestawu SDK wywołującego. Dołączenie do połączenia powoduje dodanie ich jako uczestnika do czatu spotkania, gdzie mogą wysyłać i odbierać wiadomości innym użytkownikom podczas rozmowy. Użytkownik nie ma dostępu do wiadomości czatu, które zostały wysłane przed dołączeniem do połączenia. Aby dołączyć do spotkania i rozpocząć rozmowę, możesz wykonać następne kroki.
Dodawanie czatu do aplikacji wywołującej teams
Na poziomie build.gradle
modułu dodaj zależność od zestawu SDK czatu.
Ważne
Znany problem: W przypadku używania zestawu Android Chat i Calling SDK razem w tej samej aplikacji funkcja powiadomień w czasie rzeczywistym zestawu SDK czatu nie będzie działać. Otrzymasz problem z rozwiązaniem zależności. Podczas pracy nad rozwiązaniem możesz wyłączyć funkcję powiadomień w czasie rzeczywistym, dodając następujące wykluczenia do zależności zestawu Chat SDK w pliku aplikacji build.gradle
:
implementation ("com.azure.android:azure-communication-chat:2.0.3") {
exclude group: 'com.microsoft', module: 'trouter-client-android'
}
Dodawanie układu interfejsu użytkownika usługi Teams
Zastąp kod w activity_main.xml poniższym fragmentem kodu. Dodaje dane wejściowe dla identyfikatora wątku i wysyłania wiadomości, przycisk wysyłania wpisanej wiadomości i podstawowy układ czatu.
<?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>
Włączanie kontrolek interfejsu użytkownika usługi Teams
Importowanie pakietów i definiowanie zmiennych stanu
Do zawartości MainActivity.java
pliku dodaj następujące importy:
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;
MainActivity
W klasie dodaj następujące zmienne:
// 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<>();
Zastąp <USER_ID>
element identyfikatorem użytkownika inicjującego czat.
Zastąp <COMMUNICATION_SERVICES_RESOURCE_ENDPOINT>
element punktem końcowym zasobu usług Komunikacyjnych.
Inicjowanie elementu ChatThreadClient
Po dołączeniu do spotkania utwórz wystąpienie ChatThreadClient
elementów i udostępnij składniki czatu.
Zaktualizuj koniec MainActivity.joinTeamsMeeting()
metody przy użyciu poniższego kodu:
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);
}
Włączanie wysyłania komunikatów
Dodaj metodę sendMessage()
do MainActivity
metody . Używa obiektu do ChatThreadClient
wysyłania wiadomości w imieniu użytkownika.
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("");
}
Włączanie sondowania komunikatów i renderowanie ich w aplikacji
Ważne
Znany problem: ponieważ funkcja powiadomień w czasie rzeczywistym zestawu SDK czatu nie współdziała z zestawami Sdk wywołujących, musimy sondować GetMessages
interfejs API w wstępnie zdefiniowanych odstępach czasu. W naszym przykładzie użyjemy 3-sekundowych interwałów.
Możemy uzyskać następujące dane z listy komunikatów zwróconych przez GetMessages
interfejs API:
- Komunikaty
text
ihtml
w wątku od momentu dołączenia - Zmiany w składzie wątku
- Aktualizacje do tematu wątku
MainActivity
W klasie dodaj procedurę obsługi i zadanie, które będzie uruchamiane w 3-sekundowych odstępach czasu:
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);
}
};
Pamiętaj, że zadanie zostało już uruchomione na końcu MainActivity.joinTeamsMeeting()
metody zaktualizowanej w kroku inicjowania.
Na koniec dodamy metodę wykonywania zapytań dotyczących wszystkich dostępnych komunikatów w wątku, analizowania ich według typu komunikatu i wyświetlania html
elementów i 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);
}
}
Nazwy wyświetlane uczestników wątku czatu nie są ustawiane przez klienta usługi Teams. Nazwy są zwracane jako null w interfejsie API do wyświetlania listy uczestników, w participantsAdded
przypadku i w participantsRemoved
zdarzeniu. Nazwy wyświetlane uczestników czatu można pobrać z remoteParticipants
pola call
obiektu.
Pobieranie wątku czatu spotkania usługi Teams dla użytkownika usług Communication Services
Szczegóły spotkania usługi Teams można pobrać przy użyciu interfejsów API programu Graph, szczegółowo opisanych w dokumentacji programu Graph. Zestaw SDK wywołujący usługi Communication Services akceptuje pełny link do spotkania usługi Teams lub identyfikator spotkania. Są one zwracane jako część onlineMeeting
zasobu dostępnego w joinWebUrl
ramach właściwości
Za pomocą interfejsów API programu Graph można również uzyskać threadID
element . Odpowiedź zawiera chatInfo
obiekt zawierający threadID
element .
Uruchamianie kodu
Teraz można uruchomić aplikację przy użyciu przycisku "Uruchom aplikację" na pasku narzędzi (Shift+F10).
Aby dołączyć do spotkania i czatu w aplikacji Teams, wprowadź link spotkanie zespołu i identyfikator wątku w interfejsie użytkownika.
Po dołączeniu do spotkania zespołu musisz przyznać użytkownika do spotkania w kliencie zespołu. Gdy użytkownik zostanie przyjęty i dołączy do czatu, możesz wysyłać i odbierać wiadomości.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Dowiedz się więcej o obsługiwanych funkcjach, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams
Z tego przewodnika Szybki start dowiesz się, jak rozmawiać na spotkaniu w aplikacji Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka C#.
Przykładowy kod
Znajdź kod tego przewodnika Szybki start w witrynie GitHub.
Wymagania wstępne
- Wdrożenie usługi Teams.
- Konto platformy Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
- Zainstaluj program Visual Studio 2019 przy użyciu obciążenia programistycznego platforma uniwersalna systemu Windows.
- Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych.
- Link do spotkania w aplikacji Teams.
Dołączanie do czatu na spotkaniu
Użytkownik usług Communication Services może dołączyć do spotkania usługi Teams jako anonimowy użytkownik przy użyciu zestawu SDK wywołującego. Dołączenie do spotkania powoduje dodanie ich jako uczestnika do czatu na spotkaniu, gdzie mogą wysyłać i odbierać wiadomości innym użytkownikom na spotkaniu. Użytkownik nie będzie miał dostępu do wiadomości czatu, które zostały wysłane przed dołączeniem do spotkania i nie będzie mógł wysyłać ani odbierać wiadomości po zakończeniu spotkania. Aby dołączyć do spotkania i rozpocząć rozmowę, możesz wykonać następne kroki.
Uruchamianie kodu
Możesz skompilować i uruchomić kod w programie Visual Studio. Zwróć uwagę na obsługiwane platformy rozwiązań: x64
,x86
i ARM64
.
- Otwórz wystąpienie programu PowerShell, Terminal Windows, wiersza polecenia lub równoważnego i przejdź do katalogu, do którego chcesz sklonować przykład.
git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git
- Otwórz projekt ChatTeamsInteropQuickStart/ChatTeamsInteropQuickStart.csproj w programie Visual Studio.
- Zainstaluj następujące wersje pakietów NuGet (lub nowsze):
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
- W przypadku zasobu usług komunikacyjnych pozyskanych w wymaganiach wstępnych dodaj parametry połączenia do pliku 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_ = "";
Ważne
- Wybierz odpowiednią platformę z listy rozwijanej "Platformy rozwiązań" w programie Visual Studio przed uruchomieniem kodu, tj.
x64
- Upewnij się, że masz włączony tryb dewelopera w systemie Windows 10 (deweloper Ustawienia)
Następne kroki nie będą działać, jeśli nie jest to poprawnie skonfigurowane
- Naciśnij klawisz F5, aby uruchomić projekt w trybie debugowania.
- Wklej prawidłowy link do spotkania zespołów w polu "Łącze do spotkania w aplikacji Teams" (zobacz następną sekcję)
- Naciśnij pozycję "Dołącz do spotkania w aplikacji Teams", aby rozpocząć rozmowę.
Ważne
Po nawiązaniu połączenia z zespołami , gdy zestaw SDK wywołania wywołań zestawu SDK wywołania systemu Windows, kluczowe funkcje do obsługi operacji czatu to: StartPollingForChatMessages i SendMessageButton_Click. Oba fragmenty kodu znajdują się w kodzie 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;
}
Uzyskiwanie linku spotkania usługi Teams
Link do spotkania usługi Teams można pobrać przy użyciu interfejsów API programu Graph, szczegółowo w dokumentacji programu Graph. Ten link jest zwracany w ramach onlineMeeting
zasobu dostępnego w joinWebUrl
ramach właściwości .
Możesz również uzyskać wymagany link do spotkania z adresu URL dołączenia do spotkania w zaproszeniu do spotkania usługi Teams.
Link do spotkania usługi Teams wygląda następująco: https://teams.microsoft.com/l/meetup-join/meeting_chat_thread_id/1606337455313?context=some_context_here
.
Jeśli link do aplikacji Teams ma inny format, musisz pobrać identyfikator wątku przy użyciu interfejsu API programu Graph.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Dowiedz się więcej o obsługiwanych funkcjach, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams
Czyszczenie zasobów
Jeśli chcesz wyczyścić i usunąć subskrypcję usług Komunikacyjnych, możesz usunąć zasób lub grupę zasobów. Usunięcie grupy zasobów powoduje również usunięcie wszelkich innych skojarzonych z nią zasobów. Dowiedz się więcej o czyszczeniu zasobów.
Następne kroki
Aby uzyskać więcej informacji, zobacz następujące artykuły:
- Zapoznaj się z przykładem naszego bohatera czatu
- Dowiedz się więcej o sposobie działania czatu