Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Rozpocznij pracę z usługami Azure Communication Services, łącząc rozwiązanie czatu z usługą Microsoft Teams.
W tym artykule opisano sposób czatu na spotkaniu w usłudze Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka JavaScript.
Przykładowy kod
Pobierz ten kod z GitHub Azure Samples Dołącz aplikację czatu do spotkania Teams.
Wymagania wstępne
Dołączanie do czatu na spotkaniu
Użytkownik usługi Communication Services może dołączyć do spotkania Teams jako anonimowy użytkownik za pośrednictwem Calling SDK. Dołączenie do spotkania powoduje również dodanie ich jako uczestnika do czatu spotkania, w którym mogą wysyłać i odbierać wiadomości innym użytkownikom na spotkaniu. Użytkownik nie ma dostępu do wiadomości czatu, które zostały wysłane przed dołączeniem do spotkania i nie może 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
W tym przykładzie użyto pakietu webpack do tworzenia pakietów zawartości 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żliwia 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.
Użyj pola tekstowego w górnej części strony, aby wprowadzić kontekst spotkania w Teams. Użytkownicy końcowi mogą dołączyć do określonego spotkania, klikając przycisk Dołącz do spotkania w aplikacji Teams .
W dolnej części strony zostanie wyświetlone wyskakujące okienko czatu. Użytkownicy końcowi mogą używać go do wysyłania wiadomości w wątku spotkania. Wyświetla on 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łącz kontrolki interfejsu użytkownika Teams
Zastąp zawartość pliku client.js poniższym fragmentem kodu.
W fragmencie kodu zastąp
-
SECRET_CONNECTION_STRING
z ciągiem połączeniowym 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}`);
});
Klient usługi Teams nie ustawia nazw wyświetlanych uczestników wątku czatu. Nazwy są zwracane jako wartość null w API listy uczestników, w przypadku zdarzeń participantsAdded
i participantsRemoved
. 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żyj polecenia , webpack-dev-server
aby skompilować i uruchomić aplikację. 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/
. Aplikacja powinna zostać uruchomiona, jak pokazano na poniższym zrzucie ekranu:
Wstaw link do spotkania w Teams w polu tekstowym. Użytkownicy mogą kliknąć pozycję Dołącz do spotkania usługi Teams , aby dołączyć do spotkania usługi Teams. Gdy użytkownik usług komunikacyjnych zostanie 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. Aby uzyskać więcej informacji na temat obsługiwanych funkcji, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams.
W tym artykule opisano sposób czatu na spotkaniu w aplikacji Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla systemu iOS.
Przykładowy kod
Pobierz ten kod w ramach GitHub Azure Samples Dołącz aplikację czatu do spotkania Teams.
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 Twoim 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ć Azure CLI i uruchomić polecenie z użyciem ciągu połączenia, aby utworzyć użytkownika i token dostępu.
az communication user-identity token issue --scope voip chat --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żywany framework SwiftUI, dlatego należy ustawić język na Swift i interfejs użytkownika na SwiftUI. Podczas tego szybkiego startu 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ć
Podfile
dla swojej aplikacji, otwórz terminal, przejdź do folderu projektu i uruchom pod init.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
.xcworkspace
w programie 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
, która została uwzględniona w dialogu używanym przez system do żądania dostępu od użytkownika.
W obszarze docelowym wybierz kartę Info
i dodaj ciąg dla elementu Privacy - Microphone Usage Description
.
Wyłącz piaskownicowanie skryptów użytkownika
Niektóre skrypty w połączonych bibliotekach zapisują pliki podczas procesu kompilacji. Aby umożliwić zapisywanie plików, wyłącz piaskownicę skryptów użytkownika w Xcode.
W obszarze ustawień kompilacji wyszukaj sandbox
i ustaw User Script Sandboxing
na No
.
Dołączanie do czatu na spotkaniu
Użytkownik usług komunikacyjnych może dołączyć do spotkania Microsoft Teams jako anonimowy użytkownik, używając SDK połączeń. 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 ma dostępu do wiadomości czatu wysyłanych przed dołączeniem ani nie może wysyłać ani odbierać wiadomości, gdy nie są w spotkaniu.
Aby dołączyć do spotkania i rozpocząć rozmowę, wykonaj 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>
punktem końcowym zasobu Usług Komunikacyjnych.
Zastąp <ADD_YOUR_USER_TOKEN_HERE>
wcześniej wygenerowanym tokenem za pomocą wiersza poleceń klienta Azure.
Aby uzyskać więcej informacji, zobacz Token dostępu użytkowników
Zastąp Quickstart User
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 dodaj główną treść var do przechowywania elementów interfejsu użytkownika. Dołączamy logikę biznesową do tych kontrolek. 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
Utwórz wystąpienie ChatClient
i włącz powiadomienia o wiadomościach. Do odbierania wiadomości na czacie używamy powiadomień w czasie rzeczywistym.
Po skonfigurowaniu głównej struktury dodajmy funkcje do obsługi konfiguracji klientów do połączeń i czatów.
W funkcji onAppear
dodaj następujący kod, aby zainicjować 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
}
Dodaj funkcję dołączania do spotkania
Dodaj następującą funkcję do struktury ContentView
, aby obsłużyć uczestnictwo w spotkaniu.
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
Inicjujemy ChatThreadClient
po tym, jak użytkownik dołączy do spotkania. Następnie musimy sprawdzić status spotkania od delegata, a następnie zainicjować ChatThreadClient
za pomocą threadId
przy 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ę pomocniczą do ContentView
, używaną do analizowania identyfikatora wątku czatu z linku ze spotkania zespołu, jeśli jest to możliwe. W przypadku niepowodzenia wyodrębniania użytkownik musi 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
Dodaj funkcję sendMessage()
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
. Gdy wystąpi zdarzenie komunikacyjne, wywołuje tę funkcję. Musisz zarejestrować się na wszystkie zdarzenia, które chcesz obsługiwać w instrukcji switch
za pomocą metody 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
}
}
Na koniec musimy zaimplementować handler delegata dla klienta połączeń. Użyj tej obsługi, aby sprawdzić stan połączenia i zainicjować 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 usługi Teams, wyczyścimy wiadomości czatu z interfejsu użytkownika i zawiesimy połączenie. Zapoznaj się z poniższym pełnym przykładem kodu.
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"
}
}
Uzyskaj wątek czatu spotkania Teams dla użytkownika usługi 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. SDK dla usług komunikacyjnych akceptuje pełny link do spotkania 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 Graph można również uzyskać threadID
. Odpowiedź ma obiekt chatInfo
zawierający threadID
element.
Uruchamianie kodu
Uruchom aplikację.
Aby dołączyć do spotkania Teams, wprowadź link do spotkania zespołu w interfejsie użytkownika.
Po dołączeniu do spotkania zespołu musisz przyznać użytkownika do spotkania w aplikacji Teams. Gdy użytkownik zostanie przyjęty i dołączy do czatu, może wysyłać i odbierać wiadomości.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Aby uzyskać więcej informacji na temat obsługiwanych funkcji, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams.
W tym artykule opisano sposób dodawania czatu spotkania usługi Teams do aplikacji przy użyciu zestawu SDK czatu usług Azure Communication Services dla systemu Android.
Przykładowy kod
Pobierz ten kod na stronie GitHub Azure Samples dołącz swoją aplikację czatu do spotkania Teams.
Wymagania wstępne
- Wdrożenie usługi Teams.
- Działająca aplikacja do dzwonienia.
Włącz współdziałanie usługi Teams
Użytkownik usług komunikacyjnych, który dołącza do spotkania w Teams jako użytkownik-gość, może uzyskać dostęp do czatu spotkania dopiero po dołączeniu do rozmowy w ramach spotkania w Teams. Aby uzyskać więcej informacji na temat dodawania użytkownika Usług Komunikacyjnych do spotkania w usłudze Teams, zobacz Teams interop.
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 interoperacyjności z Teams, użytkownik usług komunikacyjnych może dołączyć do wywołania w Teams jako użytkownik zewnętrzny przy użyciu SDK połączeń. Dołączenie do połączenia powoduje również dodanie ich jako uczestnika do czatu na spotkaniu. Z czatu mogą wysyłać i odbierać wiadomości z innymi użytkownikami 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 umożliwić użytkownikom końcowym dołączanie do spotkań usługi Teams i rozpoczynanie rozmowy, wykonaj następujące kroki.
Dodaj czat do aplikacji Teams do rozmów
Na poziomie build.gradle
modułu dodaj zależność od zestawu SDK czatu.
Ważne
Znany problem: Gdy używasz zestawu Android Chat i Calling SDK razem w tej samej aplikacji, funkcja powiadomień w czasie rzeczywistym zestawu SDK czatu nie działa. Generujesz 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łącz kontrolki interfejsu użytkownika 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 corresponding 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>
punktem końcowym zasobu usługi komunikacyjnej.
Inicjalizacja ChatThreadClient
Po dołączeniu do spotkania utwórz instancję ChatThreadClient
i wyświetl komponenty czatu.
Zaktualizuj koniec MainActivity.joinTeamsMeeting()
metody przy użyciu następującego 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
. Używa ChatThreadClient
do 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: Funkcja powiadomień w czasie rzeczywistym w zestawie SDK czatu nie współdziała z zestawami SDK do połączeń, dlatego musisz odpytywać interfejs API w zdefiniowanych odstępach czasu. W tym przykładzie używamy 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 tematu wątku
MainActivity
Do klasy dodaj program obsługi i zadanie, które można uruchomić w 3-sekundowych interwałach:
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);
}
};
Zadanie zostało już uruchomione na końcu metody MainActivity.joinTeamsMeeting()
, zaktualizowanej w kroku inicjowania.
Na koniec dodamy metodę zapytań dotyczących wszystkich dostępnych wiadomości w wątku, analizowania ich według typu wiadomości i wyświetlania tych, które są oznaczone jako html
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 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);
}
}
Klient usługi Teams nie ustawia nazw wyświetlanych uczestników wątku czatu. Nazwy są zwracane jako null w interfejsie API do listy uczestników, w participantsAdded
zdarzeniu i w participantsRemoved
zdarzeniu. Nazwy wyświetlane uczestników czatu można pobrać z remoteParticipants
pola call
obiektu.
Uzyskaj wątek czatu spotkania Teams dla użytkownika 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 do wywoływania usług Communication Services akceptuje pełny link do spotkania Teams lub identyfikator spotkania. Są one zwracane jako część onlineMeeting
zasobu dostępnego pod joinWebUrl
właściwością
Za pomocą interfejsów API Graph można również uzyskać threadID
. Odpowiedź ma obiekt chatInfo
, który zawiera element threadID
.
Uruchamianie kodu
Teraz możesz uruchomić aplikację z przycisku Uruchom aplikację na pasku narzędzi (Shift+F10).
Aby dołączyć do spotkania Teams i czatu, wprowadź link do spotkania zespołu i identyfikator wątku w interfejsie użytkownika.
Po dołączeniu do spotkania zespołu musisz zaakceptować użytkownika w aplikacji zespołu. Gdy użytkownik zostanie przyjęty i dołączy do czatu, może wysyłać i odbierać wiadomości.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Aby uzyskać więcej informacji na temat obsługiwanych funkcji, zobacz Możliwości spotkań usługi Teams dla użytkowników zewnętrznych usługi Teams
W tym artykule opisano sposób czatu na spotkaniu w aplikacji Teams przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka C#.
Przykładowy kod
Pobierz ten kod na stronie GitHub Azure Samples Join your chat app to a Teams meeting (Dołącz aplikację czatu do spotkania usługi Teams).
Wymagania wstępne
- Wdrożenie usługi Teams.
- Konto platformy Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
- Zainstaluj Visual Studio 2019 z modułem programistycznym dla uniwersalnej platformy Windows.
- Wdrożony zasób usług łącznościowych. Utwórz zasób usług komunikacyjnych.
- Link do spotkania w aplikacji Teams.
Dołączanie do czatu na spotkaniu
Użytkownik Communication Services może anonimowo dołączyć do spotkania w Teams przy użyciu Calling SDK. Dołączenie do spotkania powoduje również dodanie ich jako uczestnika do czatu spotkania. Na czacie mogą wysyłać i odbierać wiadomości z innymi użytkownikami na spotkaniu. Użytkownik nie ma dostępu do wiadomości czatu, które zostały wysłane przed dołączeniem do spotkania. Nie mogą wysyłać ani odbierać wiadomości po zakończeniu spotkania. Aby umożliwić użytkownikom dołączanie do spotkań usługi Teams i rozpoczynanie rozmowy, wykonaj następujące kroki.
Uruchamianie kodu
Możesz skompilować i uruchomić kod w programie Visual Studio. Obsługiwane platformy rozwiązań to: x64
,x86
i ARM64
.
Otwórz wystąpienie programu PowerShell, programu Terminal Windows, wiersza polecenia lub równoważnego i przejdź do pożądanego katalogu, do którego chcesz skopiować 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, na przykład
x64
- Upewnij się, że tryb dewelopera jest włączony w systemie Windows (ustawienia dewelopera)
Następne kroki nie działają, jeśli platforma nie jest poprawnie skonfigurowana.
- Wybierz odpowiednią platformę z listy rozwijanej Platformy rozwiązań w programie Visual Studio przed uruchomieniem kodu, na przykład
Naciśnij F5 , aby uruchomić projekt w trybie debugowania.
Wklej prawidłowy link do spotkania Microsoft Teams w polu Link do spotkania Teams (zobacz następną sekcję).
Użytkownicy końcowi klikają pozycję Dołącz do spotkania w aplikacji Teams , aby rozpocząć rozmowę.
Ważne
Po nawiązaniu połączenia z zestawem SDK wywołującego spotkanie zespołów Zobacz Usługi komunikacyjne wywołujące aplikację systemu Windows kluczowe funkcje do obsługi operacji czatu to: StartPollingForChatMessages
i SendMessageButton_Click
. Oba fragmenty kodu znajdują się w ChatTeamsInteropQuickStart\MainPage.xaml.cs
pliku
/// <summary>
/// Background task that keeps polling for chat messages while the call connection is established
/// </summary>
private async Task StartPollingForChatMessages()
{
CommunicationTokenCredential communicationTokenCredential = new(user_token_);
chatClient_ = new ChatClient(EndPointFromConnectionString(), communicationTokenCredential);
await Task.Run(async () =>
{
keepPolling_ = true;
ChatThreadClient chatThreadClient = chatClient_.GetChatThreadClient(thread_Id_);
int previousTextMessages = 0;
while (keepPolling_)
{
try
{
CommunicationUserIdentifier currentUser = new(user_Id_);
AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
SortedDictionary<long, string> messageList = new();
int textMessages = 0;
string userPrefix;
await foreach (ChatMessage message in allMessages)
{
if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
{
textMessages++;
userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{StripHtml(message.Content.Message)}");
}
}
//Update UI just when there are new messages
if (textMessages > previousTextMessages)
{
previousTextMessages = textMessages;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
TxtChat.Text = string.Join(Environment.NewLine, messageList.Values.ToList());
});
}
if (!keepPolling_)
{
return;
}
await SetInCallState(true);
await Task.Delay(3000);
}
catch (Exception e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_ = new MessageDialog($"An error occurred while fetching messages in PollingChatMessagesAsync(). The application will shutdown. Details : {e.Message}").ShowAsync();
throw e;
});
await SetInCallState(false);
}
}
});
}
private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
{
SendMessageButton.IsEnabled = false;
ChatThreadClient chatThreadClient = chatClient_.GetChatThreadClient(thread_Id_);
_ = await chatThreadClient.SendMessageAsync(TxtMessage.Text);
TxtMessage.Text = "";
SendMessageButton.IsEnabled = true;
}
Uzyskaj link do spotkania w Teams
Pobierz link do spotkania Teams przy użyciu Graph API, zgodnie z opisem w dokumentacji Graph. Ten link jest zwracany jako część zasobu onlineMeeting
, dostępnego w ramach właściwości joinWebUrl
.
Możesz również uzyskać link potrzebny do spotkania z URL 'Dołącz do spotkania' w zaproszeniu na spotkanie Teams.
Link do spotkania w Teams wygląda jak następujący adres URL:
https://teams.microsoft.com/l/meetup-join/meeting_chat_thread_id/1606337455313?context=some_context_here`.
Jeśli link do Teams ma inny format, musisz pobrać identyfikator wątku za pomocą Graph API.
Uwaga
Niektóre funkcje nie są obecnie obsługiwane w scenariuszach współdziałania z usługą Teams. Aby uzyskać więcej informacji na temat obsługiwanych funkcji, 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.
Powiązane artykuły
- Zapoznaj się z przykładem naszego bohatera czatu
- Dowiedz się więcej o sposobie działania czatu