Hızlı Başlangıç: Sohbet uygulamanızı Teams toplantısına ekleme

Sohbet çözümünüzü Microsoft Teams'e bağlayarak Azure İletişim Hizmetleri kullanmaya başlayın.

Bu hızlı başlangıçta, JavaScript için Azure İletişim Hizmetleri Sohbet SDK'sını kullanarak Teams toplantısında sohbet etmeyi öğreneceksiniz.

Örnek Kod

GitHub'da bu hızlı başlangıcın son halini alan kodu bulun.

Önkoşullar

Toplantı sohbete katılma

İletişim Hizmetleri kullanıcısı, Arama SDK'sını kullanarak teams toplantısına anonim kullanıcı olarak katılabilir. Toplantıya katılmak, toplantıdaki diğer kullanıcılarla ileti gönderip alabilecekleri toplantı sohbetine de katılımcı olarak ekler. Kullanıcı, toplantıya katılmadan önce gönderilen sohbet iletilerine erişemez ve toplantı sona erdikten sonra ileti gönderemez veya alamaz. Toplantıya katılmak ve sohbet etmeye başlamak için sonraki adımları izleyebilirsiniz.

Yeni bir Node.js uygulaması oluşturma

Terminalinizi veya komut pencerenizi açın, uygulamanız için yeni bir dizin oluşturun ve bu dizine gidin.

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

Varsayılan ayarlarla bir package.json dosyası oluşturmak için komutunu çalıştırınnpm init -y.

npm init -y

Sohbet paketlerini yükleme

npm install JavaScript için gerekli İletişim Hizmetleri SDK'larını yüklemek için komutunu kullanın.

npm install @azure/communication-common --save

npm install @azure/communication-identity --save

npm install @azure/communication-chat --save

npm install @azure/communication-calling --save

seçeneği--save, kitaplığı package.json dosyanızda bağımlılık olarak listeler.

Uygulama çerçevesini ayarlama

Bu hızlı başlangıçta uygulama varlıklarını paketlemek için Webpack kullanılır. Webpack, webpack-cli ve webpack-dev-server npm paketlerini yüklemek ve bunları package.json geliştirme bağımlılıkları olarak listelemek için aşağıdaki komutu çalıştırın:

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

Projenizin kök dizininde bir index.html dosyası oluşturun. Bu dosyayı, kullanıcının toplantıya katılmasına ve sohbet etmeye başlamasına olanak sağlayacak temel bir düzen yapılandırmak için kullanırız.

Teams kullanıcı arabirimi denetimlerini ekleme

index.html içindeki kodu aşağıdaki kod parçacığıyla değiştirin. Sayfanın üst kısmındaki metin kutusu, Teams toplantı bağlamını girmek için kullanılır. Belirtilen toplantıya katılmak için 'Teams Toplantısına Katıl' düğmesi kullanılır. Sayfanın en altında bir sohbet açılır penceresi görüntülenir. Toplantı iş parçacığında ileti göndermek için kullanılabilir ve İletişim Hizmetleri kullanıcısı üyeyken yazışmada gönderilen tüm iletiler gerçek zamanlı olarak görüntülenir.

<!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>

Teams kullanıcı arabirimi denetimlerini etkinleştirme

client.js dosyasının içeriğini aşağıdaki kod parçacığıyla değiştirin.

Kod parçacığının içinde

  • SECRET_CONNECTION_STRINGİletişim Hizmetinizin bağlantı dizesi
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}`);
});

Sohbet yazışması katılımcılarının görünen adları Teams istemcisi tarafından ayarlanmamıştır. Adlar, etkinlikte ve etkinlikte katılımcıları listelemek için API'de participantsAdded participantsRemoved null olarak döndürülür. Sohbet katılımcılarının görünen adları nesnenin remoteParticipants alanından call alınabilir. Liste değişikliğiyle ilgili bir bildirim aldıktan sonra, eklenen veya kaldırılan kullanıcının adını almak için bu kodu kullanabilirsiniz:

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

Kodu çalıştırma

Webpack kullanıcıları uygulamanızı derlemek ve çalıştırmak için uygulamasını webpack-dev-server kullanabilir. Uygulama konağınızı yerel bir web sunucusunda paketlemek için aşağıdaki komutu çalıştırın:

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

Tarayıcınızı açın ve adresine http://localhost:8080/gidin. Aşağıdaki ekran görüntüsünde gösterildiği gibi uygulamanın başlatıldığını görmeniz gerekir:

Tamamlanan JavaScript Uygulamasının ekran görüntüsü.

Teams toplantı bağlantısını metin kutusuna ekleyin. Teams toplantısına katılmak için Teams Toplantısına Katıl'a basın. İletişim Hizmetleri kullanıcısı toplantıya kabul edildikten sonra İletişim Hizmetleri uygulamanızın içinden sohbet edebilirsiniz. Sohbete başlamak için sayfanın alt kısmındaki kutuya gidin. Kolaylık olması için uygulama yalnızca sohbetteki son iki iletiyi gösterir.

Not

Teams ile birlikte çalışabilirlik senaryolarında şu anda bazı özellikler desteklenmemektedir. Desteklenen özellikler hakkında daha fazla bilgi edinmek için bkz . Teams dış kullanıcıları için Teams toplantı özellikleri

Bu hızlı başlangıçta, iOS için Azure İletişim Hizmetleri Sohbet SDK'sını kullanarak Teams toplantısında sohbet etmeyi öğreneceksiniz.

Örnek Kod

Sonuna atlamak isterseniz bu hızlı başlangıcı GitHub'da örnek olarak indirebilirsiniz.

Önkoşullar

az communication identity token issue --scope voip --connection-string "yourConnectionString"

Ayrıntılar için bkz . Erişim Belirteçleri Oluşturmak ve Yönetmek için Azure CLI kullanma.

Ayarlama

Xcode projesi oluşturma

Xcode'da yeni bir iOS projesi oluşturun ve Tek Görünüm Uygulaması şablonunu seçin. Bu öğreticide SwiftUI çerçevesi kullanılır, bu nedenle Dili Swift olarak ve Kullanıcı Arabirimini SwiftUI olarak ayarlamanız gerekir. Bu hızlı başlangıç sırasında test oluşturmayacaksınız. Testleri Dahil Et seçeneğinin işaretini kaldırabilirsiniz.

Xcode içindeki Yeni Proje penceresini gösteren ekran görüntüsü.

CocoaPods'u yükleme

Mac bilgisayarınıza CocoaPods yüklemek için bu kılavuzu kullanın.

CocoaPods ile paketi ve bağımlılıkları yükleme

  1. Uygulamanız için bir Podfile oluşturmak için terminali açın ve proje klasörüne gidin ve pod init komutunu çalıştırın.

  2. Aşağıdaki kodu hedefin Podfile altına ekleyin ve kaydedin.

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

  # Pods for Chat Teams Interop
  pod 'AzureCommunicationCalling'
  pod 'AzureCommunicationChat'
  
end
  1. pod install'i çalıştırın.

  2. .xcworkspace Dosyayı Xcode ile açın.

Mikrofona erişim isteme

Cihazın mikrofona erişmek için uygulamanızın Bilgi Özellik Listesi'ni ile NSMicrophoneUsageDescriptiongüncelleştirmeniz gerekir. İlişkili değeri, sistemin kullanıcıdan erişim istemek için kullandığı iletişim kutusuna eklenmiş bir string değere ayarlarsınız.

Hedefin altında, sekmeyi Info seçin ve 'Gizlilik - Mikrofon Kullanımı Açıklaması' için bir dize ekleyin

Xcode içine mikrofon kullanımı eklemeyi gösteren ekran görüntüsü.

Kullanıcı Betiği Korumalı Alanını Devre Dışı Bırakma

Bağlantılı kitaplıklar içindeki betiklerden bazıları derleme işlemi sırasında dosya yazar. Buna izin vermek için Xcode'da Kullanıcı Betiği Korumalı Alanını devre dışı bırakın. Derleme ayarları altında öğesini arayın sandbox ve olarak NoayarlayınUser Script Sandboxing.

Xcode içinde kullanıcı betiği korumalı alanını devre dışı bırakmayı gösteren ekran görüntüsü.

Toplantı sohbete katılma

İletişim Hizmetleri kullanıcısı, Arama SDK'sını kullanarak teams toplantısına anonim kullanıcı olarak katılabilir. Bir kullanıcı Teams toplantısına katıldıktan sonra diğer toplantı katılımcılarına ileti gönderebilir ve alabilir. Kullanıcı, katılmadan önce gönderilen sohbet iletilerine erişemez veya toplantıda olmadığında ileti gönderip alamaz. Toplantıya katılmak ve sohbet etmeye başlamak için sonraki adımları izleyebilirsiniz.

Uygulama çerçevesini ayarlama

Aşağıdaki kod parçacığını ekleyerek Azure İletişim paketlerini içeri ContentView.swift aktarın:

import AVFoundation
import SwiftUI

import AzureCommunicationCalling
import AzureCommunicationChat

içinde ContentView.swift bildiriminin hemen üstüne aşağıdaki kod parçacığını struct ContentView: View ekleyin:

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

değerini İletişim Hizmetleri kaynağınızın uç noktasıyla değiştirin <ADD_YOUR_ENDPOINT_URL_HERE> . değerini, Azure istemcisi komut satırı aracılığıyla yukarıda oluşturulan belirteçle değiştirin <ADD_YOUR_USER_TOKEN_HERE> . Kullanıcı erişim belirteçleri hakkında daha fazla bilgi edinin: Kullanıcı Erişim Belirteci

öğesini Sohbet'te kullanmak istediğiniz görünen adla değiştirin Quickstart User .

Durumu tutmak için yapıya ContentView aşağıdaki değişkenleri ekleyin:

  @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] = []

Şimdi kullanıcı arabirimi öğelerini tutmak için ana gövde var'ını ekleyelim. Bu hızlı başlangıçta bu denetimlere iş mantığı ekleyeceğiz. Yapıya ContentView aşağıdaki kodu ekleyin:

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
    }
  }

ChatClient'ı başlatma

İleti bildirimlerinin örneğini ChatClient oluşturma ve etkinleştirme. Sohbet iletilerini almak için gerçek zamanlı bildirimler kullanıyoruz.

Ana gövde ayarlandıysa, çağrı ve sohbet istemcilerinin kurulumunu işlemek için işlevleri ekleyelim.

işlevinde onAppear ve ChatClientöğesini başlatmak CallClient için aşağıdaki kodu ekleyin:

  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
  }

Toplantıya katılma işlevi ekleme

Toplantıya katılmayı ContentView işlemek için yapıya aşağıdaki işlevi ekleyin.

  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"
      }
    }
  }

ChatThreadClient'ı başlatma

Kullanıcı toplantıya katıldıktan sonra öğesini başlatacağız ChatThreadClient . Bunun için temsilciden toplantı durumunu denetlememiz ve toplantıya katıldığında ile threadId uygulamasını başlatmamız ChatThreadClient gerekir.

İşlevi connectChat() aşağıdaki kodla oluşturun:

  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
    }
  }

Mümkünse, Ekibinizin toplantı bağlantısından Sohbet yazışması kimliğini ayrıştırmak için kullanılan aşağıdaki yardımcı işlevini ContentViewöğesine ekleyin. Bu ayıklamanın başarısız olması durumunda, kullanıcının iş parçacığı kimliğini almak için Graph API'lerini kullanarak Sohbet iş parçacığı kimliğini el ile girmesi gerekir.

 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
}

İleti göndermeyi etkinleştirme

işlevini öğesine sendMessage() ContentViewekleyin. Bu işlev, kullanıcıdan ileti göndermek için öğesini ChatThreadClient kullanır.

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?"
    }
  }
}

İleti almayı etkinleştirme

İletileri almak için olaylar için ChatMessageReceived işleyiciyi uygularız. İş parçacığına yeni iletiler gönderildiğinde, bu işleyici iletileri değişkene meetingMessages ekler, böylece bunlar kullanıcı arabiriminde görüntülenebilir.

İlk olarak aşağıdaki yapıyı öğesine ContentView.swiftekleyin. Kullanıcı arabirimi, Sohbet iletilerimizi görüntülemek için yapıdaki verileri kullanır.

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
    )
  }
}

Ardından işlevini öğesine ContentViewekleyinreceiveMessage(). Bu, bir mesajlaşma olayı gerçekleştiğinde çağrılır. yöntemi aracılığıyla chatClient?.register() deyiminde switch işlemek istediğiniz tüm olaylara kaydolmanız gerektiğini unutmayın.

  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
    }
  }

Son olarak, çağrı istemcisi için temsilci işleyicisini uygulamamız gerekir. Bu işleyici, kullanıcı toplantıya katıldığında çağrı durumunu denetlemek ve sohbet istemcisini başlatmak için kullanılır.

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"
    }
  }
}

Sohbeti bırakma

Kullanıcı Ekip toplantısından ayrıldığında kullanıcı arabiriminden Sohbet iletilerini temizler ve aramayı kapatırız. Kodun tamamı aşağıda gösterilmiştir.

  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"
    }
  }

İletişim Hizmetleri kullanıcısı için Teams toplantı sohbet yazışması alma

Teams toplantı ayrıntıları, Graph belgelerinde ayrıntılı olarak açıklanan Graph API'leri kullanılarak alınabilir. İletişim Hizmetleri Arama SDK'sı, tam bir Teams toplantı bağlantısını veya toplantı kimliğini kabul eder. Bunlar kaynağın onlineMeeting bir parçası olarak döndürülür ve özelliği altında joinWebUrl erişilebilir

Graph API'leri ile de elde threadIDedebilirsiniz. Yanıt, öğesini içeren bir chatInfo nesnesine threadIDsahiptir.

Kodu çalıştırma

Uygulamayı çalıştırın.

Teams toplantısına katılmak için kullanıcı arabirimine Ekibinizin toplantı bağlantısını girin.

Ekibin toplantısına katıldıktan sonra, kullanıcıyı Ekibinizin istemcisinde toplantıya kabul etmeniz gerekir. Kullanıcı kabul ettikten ve sohbete katıldıktan sonra ileti gönderip alabilirsiniz.

Tamamlanan iOS Uygulamasının ekran görüntüsü.

Not

Teams ile birlikte çalışabilirlik senaryolarında şu anda bazı özellikler desteklenmemektedir. Desteklenen özellikler hakkında daha fazla bilgi edinmek için bkz . Teams dış kullanıcıları için Teams toplantı özellikleri

Bu hızlı başlangıçta, Android için Azure İletişim Hizmetleri Sohbet SDK'sını kullanarak Teams toplantısında sohbet etmeyi öğreneceksiniz.

Örnek Kod

Sonuna atlamak isterseniz bu hızlı başlangıcı GitHub'da örnek olarak indirebilirsiniz.

Önkoşullar

Teams birlikte çalışabilirliğini etkinleştirme

Teams toplantısına konuk kullanıcı olarak katılan bir İletişim Hizmetleri kullanıcısı, toplantının sohbete yalnızca Teams toplantı çağrısına katıldığında erişebilir. Teams toplantı aramasına İletişim Hizmetleri kullanıcısı eklemeyi öğrenmek için Teams birlikte çalışma belgelerine bakın.

Bu özelliği kullanabilmek için her iki varlığın da sahibi olan kuruluşun üyesi olmanız gerekir.

Toplantı sohbete katılma

Teams birlikte çalışabilirliği etkinleştirildikten sonra, bir İletişim Hizmetleri kullanıcısı Arama SDK'sını kullanarak Teams çağrısına dış kullanıcı olarak katılabilir. Aramaya katılmak, bu kişileri toplantı sohbetine de katılımcı olarak ekler; burada aramada diğer kullanıcılarla ileti gönderip alabilirler. Kullanıcının aramaya katılmadan önce gönderilen sohbet iletilerine erişimi yoktur. Toplantıya katılmak ve sohbet etmeye başlamak için sonraki adımları izleyebilirsiniz.

Teams arama uygulamasına Sohbet ekleme

Modül düzeyinizde build.gradle, sohbet SDK'sı bağımlılığını ekleyin.

Önemli

Bilinen sorun: Android Sohbet ve Arama SDK'sını aynı uygulamada birlikte kullanırken Sohbet SDK'sının gerçek zamanlı bildirimler özelliği çalışmaz. Bağımlılık çözümleme sorunuyla karşınıza çıkar. Bir çözüm üzerinde çalışırken uygulamanın dosyasındaki Sohbet SDK'sı build.gradle bağımlılığına aşağıdaki dışlamaları ekleyerek gerçek zamanlı bildirimler özelliğini kapatabilirsiniz:

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

Teams kullanıcı arabirimi düzenini ekleme

activity_main.xml içindeki kodu aşağıdaki kod parçacığıyla değiştirin. İş parçacığı kimliği ve ileti göndermek için girişler, yazılan iletiyi göndermek için bir düğme ve temel bir sohbet düzeni ekler.

<?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>

Teams kullanıcı arabirimi denetimlerini etkinleştirme

Paketleri içeri aktarma ve durum değişkenlerini tanımlama

içeriğine MainActivity.javaaşağıdaki içeri aktarmaları ekleyin:

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;

sınıfına MainActivity aşağıdaki değişkenleri ekleyin:

    // 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<>();

değerini sohbeti başlatan kullanıcının kimliğiyle değiştirin <USER_ID> . değerini İletişim Hizmetleri kaynağınızın uç noktasıyla değiştirin <COMMUNICATION_SERVICES_RESOURCE_ENDPOINT> .

ChatThreadClient'ı başlatma

Toplantıya katıldıktan sonra öğesinin örneğini ChatThreadClient açın ve sohbet bileşenlerini görünür hale getirin.

Yönteminin MainActivity.joinTeamsMeeting() sonunu aşağıdaki kodla güncelleştirin:

    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);
    }

İleti göndermeyi etkinleştirme

sendMessage() yöntemini öğesine MainActivityekleyin. kullanıcı adına ileti göndermek için kullanır ChatThreadClient .

    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("");
    }

İletiler için yoklamayı etkinleştirme ve bunları uygulamada işleme

Önemli

Bilinen sorun: Sohbet SDK'sının gerçek zamanlı bildirimler özelliği Arama SDK'ları ile birlikte çalışmadığından API'yi önceden tanımlanmış aralıklarla yoklamamız GetMessages gerekir. Örneğimizde 3 saniyelik aralıklar kullanacağız.

API tarafından GetMessages döndürülen ileti listesinden aşağıdaki verileri elde edebiliriz:

  • Katıldıktan text sonra iş parçacığındaki ve html iletileri
  • İş parçacığı listesinde yapılan değişiklikler
  • İş parçacığı konusuna Güncelleştirmeler

sınıfına MainActivity , 3 saniyelik aralıklarla çalıştırılacak bir işleyici ve çalıştırılabilir bir görev ekleyin:

    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);
        }
    };

Başlatma adımında güncelleştirilen yöntemin MainActivity.joinTeamsMeeting() sonunda görevin zaten başlatıldığını unutmayın.

Son olarak, iş parçacığındaki tüm erişilebilir iletileri sorgulamak, bunları ileti türüne göre ayrıştırmak ve ve text değerlerini görüntülemek html için yöntemini ekleyeceğiz:

    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);
        }
    }

Sohbet yazışması katılımcılarının görünen adları Teams istemcisi tarafından ayarlanmamıştır. Adlar, etkinlikte ve etkinlikte katılımcıları listelemek için API'de participantsAdded participantsRemoved null olarak döndürülür. Sohbet katılımcılarının görünen adları nesnenin remoteParticipants alanından call alınabilir.

İletişim Hizmetleri kullanıcısı için Teams toplantı sohbet yazışması alma

Teams toplantı ayrıntıları, Graph belgelerinde ayrıntılı olarak açıklanan Graph API'leri kullanılarak alınabilir. İletişim Hizmetleri Arama SDK'sı, tam bir Teams toplantı bağlantısını veya toplantı kimliğini kabul eder. Bunlar kaynağın onlineMeeting bir parçası olarak döndürülür ve özelliği altında joinWebUrl erişilebilir

Graph API'leri ile de elde threadIDedebilirsiniz. Yanıt, öğesini içeren bir chatInfo nesnesine threadIDsahiptir.

Kodu çalıştırma

Uygulama artık araç çubuğundaki "Uygulamayı Çalıştır" düğmesi kullanılarak başlatılabilir (Shift+F10).

Teams toplantısına ve sohbetine katılmak için Ekibinizin toplantı bağlantısını ve yazışma kimliğini kullanıcı arabirimine girin.

Ekibin toplantısına katıldıktan sonra, kullanıcıyı Ekibinizin istemcisinde toplantıya kabul etmeniz gerekir. Kullanıcı kabul ettikten ve sohbete katıldıktan sonra ileti gönderip alabilirsiniz.

Tamamlanmış Android Uygulamasının ekran görüntüsü.

Not

Teams ile birlikte çalışabilirlik senaryolarında şu anda bazı özellikler desteklenmemektedir. Desteklenen özellikler hakkında daha fazla bilgi edinmek için bkz . Teams dış kullanıcıları için Teams toplantı özellikleri

Bu hızlı başlangıçta, C# için Azure İletişim Hizmetleri Sohbet SDK'sını kullanarak Teams toplantısında sohbet etmeyi öğreneceksiniz.

Örnek kod

GitHub'da bu hızlı başlangıcın kodunu bulun.

Önkoşullar

Toplantı sohbete katılma

İletişim Hizmetleri kullanıcısı, Arama SDK'sını kullanarak teams toplantısına anonim kullanıcı olarak katılabilir. Toplantıya katılmak, toplantıdaki diğer kullanıcılarla ileti gönderip alabilecekleri toplantı sohbetine de katılımcı olarak ekler. Kullanıcı, toplantıya katılmadan önce gönderilen sohbet iletilerine erişemez ve toplantı sona erdikten sonra ileti gönderemez veya alamaz. Toplantıya katılmak ve sohbet etmeye başlamak için sonraki adımları izleyebilirsiniz.

Kodu çalıştırma

Kodu Visual Studio'da derleyebilir ve çalıştırabilirsiniz. Desteklediğimiz çözüm platformlarını not edin: x64,x86, ve ARM64.

  1. PowerShell, Windows Terminali, Komut İstemi veya eşdeğer bir örneği açın ve örneği kopyalamak istediğiniz dizine gidin.
  2. git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git
  3. Visual Studio'da ChatTeamsInteropQuickStart/ChatTeamsInteropQuickStart.csproj projesini açın.
  4. Aşağıdaki NuGet paketleri sürümlerini (veya üzerini) yükleyin:
Install-Package Azure.Communication.Calling -Version 1.0.0-beta.29
Install-Package Azure.Communication.Chat -Version 1.1.0
Install-Package Azure.Communication.Common -Version 1.0.1
Install-Package Azure.Communication.Identity -Version 1.0.1

  1. İletişim Hizmetleri kaynağı önkoşullarda temin edildiyse, connectionstring'i ChatTeamsInteropQuickStart/MainPage.xaml.cs dosyasına ekleyin.
//Azure Communication Services resource connection string, i.e., = "endpoint=https://your-resource.communication.azure.net/;accesskey=your-access-key";
private const string connectionString_ = "";

Önemli

  • Kodu çalıştırmadan önce Visual Studio'daki 'Çözüm Platformları' açılan listesinden uygun platformu seçin; örneğin,x64
  • Windows 10'da 'Geliştirici Modu'nun etkinleştirildiğinden emin olun (Geliştirici Ayarlar)

Bu doğru yapılandırılmazsa sonraki adımlar çalışmaz

  1. Projeyi hata ayıklama modunda başlatmak için F5 tuşuna basın.
  2. 'Teams Toplantı Bağlantısı' kutusuna geçerli bir Teams toplantı bağlantısı yapıştırın (sonraki bölüme bakın)
  3. Sohbete başlamak için 'Teams toplantısına katıl' tuşuna basın.

Önemli

Arama SDK'sı teams toplantısıyla bağlantı kurduktan sonra Bkz. İletişim Hizmetleri windows uygulamasını çağırırken, sohbet işlemlerini işlemeye yönelik temel işlevler şunlardır: StartPollingForChatMessages ve SendMessageButton_Click. Her iki kod parçacığı da 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;
        }

Teams toplantı bağlantısı, Graph belgelerinde ayrıntılı olarak açıklanan Graph API'leri kullanılarak alınabilir. Bu bağlantı kaynağın onlineMeeting bir parçası olarak döndürülür ve özelliğinden joinWebUrlerişilebilir.

Ayrıca, Teams toplantı davetinin kendisindeki Toplantıya Katıl URL'sinden de gerekli toplantı bağlantısını alabilirsiniz. Teams toplantı bağlantısı şöyle görünür: https://teams.microsoft.com/l/meetup-join/meeting_chat_thread_id/1606337455313?context=some_context_here. Teams bağlantınız bu bağlantıyla farklı bir biçime sahipse, Graph API'sini kullanarak iş parçacığı kimliğini almanız gerekir.

Tamamlanan csharp Uygulamasının ekran görüntüsü.

Not

Teams ile birlikte çalışabilirlik senaryolarında şu anda bazı özellikler desteklenmemektedir. Desteklenen özellikler hakkında daha fazla bilgi edinmek için bkz . Teams dış kullanıcıları için Teams toplantı özellikleri

Kaynakları temizleme

İletişim Hizmetleri aboneliğini temizlemek ve kaldırmak istiyorsanız, kaynağı veya kaynak grubunu silebilirsiniz. Kaynak grubunun silinmesi, kaynak grubuyla ilişkili diğer tüm kaynakları da siler. Kaynakları temizleme hakkında daha fazla bilgi edinin.

Sonraki adımlar

Daha fazla bilgi için aşağıdaki makaleleri inceleyin: