Freigeben über


Schnellstart: Verknüpfen Ihrer Anruf-App mit einer Teams-Anrufwarteschlange

In diesem Schnellstart werden Sie erfahren, wie Sie einen Anruf von einem Azure Communication Services-Benutzer an die Teams-Anrufwarteschlange starten. Sie werden dies mit den folgenden Schritten erreichen:

  1. Aktivieren Sie den Verbund der Azure Communication Services-Ressource mit dem Teams-Mandanten.
  2. Wählen oder erstellen Sie die Teams-Anrufwarteschlange über das Teams Admin Center.
  3. Rufen Sie die E-Mail-Adresse der Anrufwarteschlange über das Teams Admin Center ab.
  4. Rufen Sie die Objekt-ID der Anrufwarteschlange über die Graph-API ab.
  5. Starten Sie einen Anruf mit dem Anruf-SDK von Azure Communication Services.

Wenn Sie direkt zum Ende springen möchten, können Sie diese Schnellstartanleitung als Beispiel auf GitHub herunterladen.

Aktivieren der Interoperabilität in Ihrem Teams-Mandanten

Microsoft Entra-Benutzer mit der Teams-Administratorrolle können das PowerShell-Cmdlet mit dem MicrosoftTeams-Modul ausführen, um die Communication Services-Ressource im Mandanten zu aktivieren.

1. Vorbereiten des Microsoft Teams-Moduls

Öffnen Sie zunächst die PowerShell, und überprüfen Sie das Vorhandensein des Teams-Moduls mit dem folgenden Befehl:

Get-module *teams* 

Wenn das MicrosoftTeams-Modul nicht angezeigt wird, installieren Sie es zuerst. Um das Modul zu installieren, müssen Sie PowerShell als Administrator ausführen. Führen Sie dann den folgenden Befehl aus:

	Install-Module -Name MicrosoftTeams

Sie werden über die Module informiert, die installiert werden, die Sie mit der Antwort Y oder A bestätigen können. Wenn das Modul installiert, aber veraltet ist, können Sie den folgenden Befehl ausführen, um das Modul zu aktualisieren:

	Update-Module MicrosoftTeams

2. Herstellen einer Verbindung mit dem Microsoft Teams-Modul

Wenn das Modul installiert und bereit ist, können Sie mit dem folgenden Befehl eine Verbindung mit dem MicrosftTeams-Modul herstellen. Sie werden aufgefordert, sich mit einem interaktiven Fenster anzumelden. Das Benutzerkonto, das Sie verwenden möchten, muss über Teams-Administratorberechtigungen verfügen. Andernfalls erhalten Sie möglicherweise in den nächsten Schritten die Antwort access denied.

Connect-MicrosoftTeams

3. Aktivieren der Mandantenkonfiguration

Die Interoperabilität mit Communication Services-Ressourcen wird über die Mandantenkonfiguration und die zugewiesene Richtlinie gesteuert. Der Teams-Mandant verfügt über eine einzelne Mandantenkonfiguration, und Teams-Benutzer*innen wurde eine globale Richtlinie oder eine benutzerdefinierte Richtlinie zugewiesen. Weitere Informationen finden Sie unter Zuweisen von Richtlinien in Teams.

Nach erfolgreicher Anmeldung können Sie das Cmdlet Set-CsTeamsAcsFederationConfiguration ausführen, um die Communication Services-Ressource in Ihrem Mandanten zu aktivieren. Ersetzen Sie den Text IMMUTABLE_RESOURCE_ID durch eine unveränderliche Ressourcen-ID in Ihrer Kommunikationsressource. Weitere Informationen zum Abrufen dieser Informationen finden Sie hier.

$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist

4. Aktivieren der Mandantenrichtlinie

Jedem Teams-Benutzer wurde eine External Access Policy zugewiesen, die festlegt, ob Communication Services-Benutzer*innen diese Teams-Benutzer*in bzw. diesen Teams-Benutzer aufrufen können. Verwenden Sie das Cmdlet Set-CsExternalAccessPolicy, um sicherzustellen, dass für die der Teams-Benutzer*in bzw. dem Teams-Benutzer zugewiesene Richtlinie EnableAcsFederationAccess auf $true festgelegt ist

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Erstellen oder Auswählen einer Teams-Anrufwarteschlange

Die Teams-Anrufwarteschlange ist ein Feature in Microsoft Teams, das eingehende Anrufe effizient an eine Gruppe von bestimmten Benutzern oder Agenten verteilt. Es ist nützlich für Kundensupport- oder Callcenterszenarien. Aufrufe werden in eine Warteschlange gestellt und dem nächsten verfügbaren Agenten basierend auf einer vordefinierten Routingmethode zugewiesen. Agenten erhalten Benachrichtigungen und können Anrufe mithilfe der Anrufsteuerelementen von Teams verarbeiten. Das Feature bietet Berichte und Analysen für die Leistungsnachverfolgung. Es vereinfacht die Anrufbehandlung, stellt eine konsistente Kundenerfahrung sicher und optimiert die Produktivität der Agenten. Sie können über das Teams Admin Center eine vorhandene Anrufwarteschlange auswählen oder eine neue erstellen.

Weitere Informationen zum Erstellen der Anrufwarteschlange mit dem Teams Admin Center finden Sie hier.

Objekt-ID für Anrufwarteschlange suchen

Nachdem die Anrufwarteschlange erstellt wurde, müssen wir die korrelierte Objekt-ID suchen, um sie später für Aufrufe verwenden zu können. Die Objekt-ID ist mit dem Ressourcenkonto verbunden, das an die Anrufwarteschlange angefügt wurde. Öffnen Sie die Registerkarte „Ressourcenkonten“ in Teams Admin, und suchen Sie nach der E-Mail. Screenshot der Ressourcenkonten im Teams Admin-Portal. Alle erforderlichen Informationen zu Ressourcenkonten können im Microsoft Graph-Explorer gefunden werden, indem diese E-Mail in der Suche verwendet wird.

https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com

In den Ergebnissen können wir das Feld „ID“ finden

    "userPrincipalName": "lab-test2-cq@contoso.com",
    "id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"

Voraussetzungen

Einrichten

Erstellen einer neuen Node.js-Anwendung

Öffnen Sie das Terminal- oder Befehlsfenster, erstellen Sie ein neues Verzeichnis für Ihre App, und navigieren Sie zu diesem Verzeichnis.

mkdir calling-quickstart && cd calling-quickstart

Installieren des Pakets

Verwenden Sie den Befehl npm install, um das Azure Communication Services Calling SDK für JavaScript zu installieren.

Wichtig

In dieser Schnellstartanleitung wird Version next des Azure Communication Services Calling SDK verwendet.

npm install @azure/communication-common@next --save
npm install @azure/communication-calling@next --save

Einrichten des App-Frameworks

In dieser Schnellstartanleitung wird Webpack verwendet, um die Anwendungsressourcen zu bündeln. Führen Sie den folgenden Befehl aus, um die npm-Pakete webpack, webpack-cli und webpack-dev-server zu installieren und diese als Entwicklungsabhängigkeiten in package.json aufzulisten:

npm install copy-webpack-plugin@^11.0.0 webpack@^5.88.2 webpack-cli@^5.1.4 webpack-dev-server@^4.15.1 --save-dev

Erstellen Sie im Stammverzeichnis Ihres Projekts die Datei index.html. Diese Datei wird zum Konfigurieren eines grundlegenden Layouts verwendet, das es dem Benutzer ermöglicht, einen 1:1-Videoanruf zu tätigen.

Der Code lautet wie folgt:

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <title>Azure Communication Services - Calling Web SDK</title>
    </head>
    <body>
        <h4>Azure Communication Services - Calling Web SDK</h4>
        <input id="user-access-token"
            type="text"
            placeholder="User access token"
            style="margin-bottom:1em; width: 500px;"/>
        <button id="initialize-teams-call-agent" type="button">Initialize Call Agent</button>
        <br>
        <br>
        <input id="application-object-id"
            type="text"
            placeholder="Enter callee's Teams user identity in format: 'APP_GUID'"
            style="margin-bottom:1em; width: 500px; display: block;"/>
        <button id="start-call-button" type="button" disabled="true">Start Call</button>
        <button id="hangup-call-button" type="button" disabled="true">Hang up Call</button>
        <button id="accept-call-button" type="button" disabled="true">Accept Call</button>
        <button id="start-video-button" type="button" disabled="true">Start Video</button>
        <button id="stop-video-button" type="button" disabled="true">Stop Video</button>
        <br>
        <br>
        <div id="connectedLabel" style="color: #13bb13;" hidden>Call is connected!</div>
        <br>
        <div id="remoteVideoContainer" style="width: 40%;" hidden>Remote participants' video streams:</div>
        <br>
        <div id="localVideoContainer" style="width: 30%;" hidden>Local video stream:</div>
        <!-- points to the bundle generated from client.js -->
        <script src="./main.js"></script>
    </body>
</html>

Objektmodell des Azure Communication Services Calling Web SDK

Die folgenden Klassen und Schnittstellen befassen sich mit einigen der wichtigsten Features des Azure Communication Services Calling SDK:

Name BESCHREIBUNG
CallClient Der Haupteinstiegspunkt des Calling SDK.
CallAgent Dient zum Starten und Verwalten von Anrufen.
DeviceManager Dient zum Verwalten von Mediengeräten.
Call Dient zum Darstellen eines Anrufs.
LocalVideoStream Dient zum Erstellen eines lokalen Videostreams für ein Kameragerät auf dem lokalen System.
RemoteParticipant Dient zum Darstellen eines Remote-Teilnehmers im Anruf.
RemoteVideoStream Dient zum Darstellen eines Remotevideostreams von einem Remoteteilnehmer.

Erstellen Sie im Stammverzeichnis Ihres Projekts eine Datei mit dem Namen client.js, die die Anwendungslogik für diese Schnellstartanleitung enthalten soll. Fügen Sie den folgenden Code zu client.js hinzu.

// Make sure to install the necessary dependencies
const { CallClient, VideoStreamRenderer, LocalVideoStream } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential } = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the log level and output
setLogLevel('verbose');
AzureLogger.log = (...args) => {
    console.log(...args);
};
// Calling web sdk objects
let callAgent;
let deviceManager;
let call;
let incomingCall;
let localVideoStream;
let localVideoStreamRenderer;
// UI widgets
let userAccessToken = document.getElementById('user-access-token');
let callQueueId = document.getElementById('application-object-id');
let initializeCallAgentButton = document.getElementById('initialize-teams-call-agent');
let startCallButton = document.getElementById('start-call-button');
let hangUpCallButton = document.getElementById('hangup-call-button');
let acceptCallButton = document.getElementById('accept-call-button');
let startVideoButton = document.getElementById('start-video-button');
let stopVideoButton = document.getElementById('stop-video-button');
let connectedLabel = document.getElementById('connectedLabel');
let remoteVideoContainer = document.getElementById('remoteVideoContainer');
let localVideoContainer = document.getElementById('localVideoContainer');
/**
 * Create an instance of CallClient. Initialize a CallAgent instance with a AzureCommunicationTokenCredential via created CallClient. CallAgent enables us to make outgoing calls and receive incoming calls. 
 * You can then use the CallClient.getDeviceManager() API instance to get the DeviceManager.
 */
initializeCallAgentButton.onclick = async () => {
    try {
        const callClient = new CallClient(); 
        tokenCredential = new AzureCommunicationTokenCredential(userAccessToken.value.trim());
        callAgent = await callClient.createCallAgent(tokenCredential)
        // Set up a camera device to use.
        deviceManager = await callClient.getDeviceManager();
        await deviceManager.askDevicePermission({ video: true });
        await deviceManager.askDevicePermission({ audio: true });
        // Listen for an incoming call to accept.
        callAgent.on('incomingCall', async (args) => {
            try {
                incomingCall = args.incomingCall;
                acceptCallButton.disabled = false;
                startCallButton.disabled = true;
            } catch (error) {
                console.error(error);
            }
        });
        startCallButton.disabled = false;
        initializeCallAgentButton.disabled = true;
    } catch(error) {
        console.error(error);
    }
}
/**
 * Place a 1:1 outgoing video call to a Teams Call Queue
 * Add an event listener to initiate a call when the `startCallButton` is selected.
 * Enumerate local cameras using the deviceManager `getCameraList` API.
 * In this quickstart, we're using the first camera in the collection. Once the desired camera is selected, a
 * LocalVideoStream instance will be constructed and passed within `videoOptions` as an item within the
 * localVideoStream array to the call method. When the call connects, your application will be sending a video stream to the other participant. 
 */
startCallButton.onclick = async () => {
    try {
        const localVideoStream = await createLocalVideoStream();
        const videoOptions = localVideoStream ? { localVideoStreams: [localVideoStream] } : undefined;
        call = callAgent.startCall([{ teamsAppId: callQueueId.value.trim(), cloud:"public" }], { videoOptions: videoOptions });
        // Subscribe to the call's properties and events.
        subscribeToCall(call);
    } catch (error) {
        console.error(error);
    }
}
/**
 * Accepting an incoming call with a video
 * Add an event listener to accept a call when the `acceptCallButton` is selected.
 * You can accept incoming calls after subscribing to the `CallAgent.on('incomingCall')` event.
 * You can pass the local video stream to accept the call with the following code.
 */
acceptCallButton.onclick = async () => {
    try {
        const localVideoStream = await createLocalVideoStream();
        const videoOptions = localVideoStream ? { localVideoStreams: [localVideoStream] } : undefined;
        call = await incomingCall.accept({ videoOptions });
        // Subscribe to the call's properties and events.
        subscribeToCall(call);
    } catch (error) {
        console.error(error);
    }
}
// Subscribe to a call obj.
// Listen for property changes and collection udpates.
subscribeToCall = (call) => {
    try {
        // Inspect the initial call.id value.
        console.log(`Call Id: ${call.id}`);
        //Subsribe to call's 'idChanged' event for value changes.
        call.on('idChanged', () => {
            console.log(`Call ID changed: ${call.id}`); 
        });
        // Inspect the initial call.state value.
        console.log(`Call state: ${call.state}`);
        // Subscribe to call's 'stateChanged' event for value changes.
        call.on('stateChanged', async () => {
            console.log(`Call state changed: ${call.state}`);
            if(call.state === 'Connected') {
                connectedLabel.hidden = false;
                acceptCallButton.disabled = true;
                startCallButton.disabled = true;
                hangUpCallButton.disabled = false;
                startVideoButton.disabled = false;
                stopVideoButton.disabled = false;
            } else if (call.state === 'Disconnected') {
                connectedLabel.hidden = true;
                startCallButton.disabled = false;
                hangUpCallButton.disabled = true;
                startVideoButton.disabled = true;
                stopVideoButton.disabled = true;
                console.log(`Call ended, call end reason={code=${call.callEndReason.code}, subCode=${call.callEndReason.subCode}}`);
            }   
        });
        call.localVideoStreams.forEach(async (lvs) => {
            localVideoStream = lvs;
            await displayLocalVideoStream();
        });
        call.on('localVideoStreamsUpdated', e => {
            e.added.forEach(async (lvs) => {
                localVideoStream = lvs;
                await displayLocalVideoStream();
            });
            e.removed.forEach(lvs => {
               removeLocalVideoStream();
            });
        });
        
        call.on('isLocalVideoStartedChanged', () => {
            console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
        });
        console.log(`isLocalVideoStarted: ${call.isLocalVideoStarted}`);
        // Inspect the call's current remote participants and subscribe to them.
        call.remoteParticipants.forEach(remoteParticipant => {
            subscribeToRemoteParticipant(remoteParticipant);
        });
        // Subscribe to the call's 'remoteParticipantsUpdated' event to be
        // notified when new participants are added to the call or removed from the call.
        call.on('remoteParticipantsUpdated', e => {
            // Subscribe to new remote participants that are added to the call.
            e.added.forEach(remoteParticipant => {
                subscribeToRemoteParticipant(remoteParticipant)
            });
            // Unsubscribe from participants that are removed from the call
            e.removed.forEach(remoteParticipant => {
                console.log('Remote participant removed from the call.');
            });
        });
    } catch (error) {
        console.error(error);
    }
}
// Subscribe to a remote participant obj.
// Listen for property changes and collection udpates.
subscribeToRemoteParticipant = (remoteParticipant) => {
    try {
        // Inspect the initial remoteParticipant.state value.
        console.log(`Remote participant state: ${remoteParticipant.state}`);
        // Subscribe to remoteParticipant's 'stateChanged' event for value changes.
        remoteParticipant.on('stateChanged', () => {
            console.log(`Remote participant state changed: ${remoteParticipant.state}`);
        });
        // Inspect the remoteParticipants's current videoStreams and subscribe to them.
        remoteParticipant.videoStreams.forEach(remoteVideoStream => {
            subscribeToRemoteVideoStream(remoteVideoStream)
        });
        // Subscribe to the remoteParticipant's 'videoStreamsUpdated' event to be
        // notified when the remoteParticiapant adds new videoStreams and removes video streams.
        remoteParticipant.on('videoStreamsUpdated', e => {
            // Subscribe to newly added remote participant's video streams.
            e.added.forEach(remoteVideoStream => {
                subscribeToRemoteVideoStream(remoteVideoStream)
            });
            // Unsubscribe from newly removed remote participants' video streams.
            e.removed.forEach(remoteVideoStream => {
                console.log('Remote participant video stream was removed.');
            })
        });
    } catch (error) {
        console.error(error);
    }
}
/**
 * Subscribe to a remote participant's remote video stream obj.
 * You have to subscribe to the 'isAvailableChanged' event to render the remoteVideoStream. If the 'isAvailable' property
 * changes to 'true' a remote participant is sending a stream. Whenever the availability of a remote stream changes
 * you can choose to destroy the whole 'Renderer' a specific 'RendererView' or keep them. Displaying RendererView without a video stream will result in a blank video frame. 
 */
subscribeToRemoteVideoStream = async (remoteVideoStream) => {
    // Create a video stream renderer for the remote video stream.
    let videoStreamRenderer = new VideoStreamRenderer(remoteVideoStream);
    let view;
    const renderVideo = async () => {
        try {
            // Create a renderer view for the remote video stream.
            view = await videoStreamRenderer.createView();
            // Attach the renderer view to the UI.
            remoteVideoContainer.hidden = false;
            remoteVideoContainer.appendChild(view.target);
        } catch (e) {
            console.warn(`Failed to createView, reason=${e.message}, code=${e.code}`);
        }	
    }
    
    remoteVideoStream.on('isAvailableChanged', async () => {
        // Participant has switched video on.
        if (remoteVideoStream.isAvailable) {
            await renderVideo();
        // Participant has switched video off.
        } else {
            if (view) {
                view.dispose();
                view = undefined;
            }
        }
    });
    // Participant has video on initially.
    if (remoteVideoStream.isAvailable) {
        await renderVideo();
    }
}
// Start your local video stream.
// This will send your local video stream to remote participants so they can view it.
startVideoButton.onclick = async () => {
    try {
        const localVideoStream = await createLocalVideoStream();
        await call.startVideo(localVideoStream);
    } catch (error) {
        console.error(error);
    }
}
// Stop your local video stream.
// This will stop your local video stream from being sent to remote participants.
stopVideoButton.onclick = async () => {
    try {
        await call.stopVideo(localVideoStream);
    } catch (error) {
        console.error(error);
    }
}
/**
 * To render a LocalVideoStream, you need to create a new instance of VideoStreamRenderer, and then
 * create a new VideoStreamRendererView instance using the asynchronous createView() method.
 * You may then attach view.target to any UI element. 
 */
// Create a local video stream for your camera device
createLocalVideoStream = async () => {
    const camera = (await deviceManager.getCameras())[0];
    if (camera) {
        return new LocalVideoStream(camera);
    } else {
        console.error(`No camera device found on the system`);
    }
}
// Display your local video stream preview in your UI
displayLocalVideoStream = async () => {
    try {
        localVideoStreamRenderer = new VideoStreamRenderer(localVideoStream);
        const view = await localVideoStreamRenderer.createView();
        localVideoContainer.hidden = false;
        localVideoContainer.appendChild(view.target);
    } catch (error) {
        console.error(error);
    } 
}
// Remove your local video stream preview from your UI
removeLocalVideoStream = async() => {
    try {
        localVideoStreamRenderer.dispose();
        localVideoContainer.hidden = true;
    } catch (error) {
        console.error(error);
    } 
}
// End the current call
hangUpCallButton.addEventListener("click", async () => {
    // end the current call
    await call.hangUp();
});

Hinzufügen des lokalen Webpack-Servercodes

Erstellen Sie im Stammverzeichnis Ihres Projekts eine Datei mit dem Namen webpack.config.js, die die lokale Serverlogik für diesen Schnellstart enthalten soll. Fügen Sie der Datei webpack.config.js den folgenden Code hinzu:

const path = require('path');
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
    mode: 'development',
    entry: './client.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    devServer: {
        static: {
            directory: path.join(__dirname, './')
        },
    },
    plugins: [
        new CopyPlugin({
            patterns: [
                './index.html'
            ]
        }),
    ]
};

Ausführen des Codes

Verwenden Sie webpack-dev-server, um Ihre App zu erstellen und auszuführen. Führen Sie den folgenden Befehl aus, um den Anwendungshost auf einem lokalen Webserver zu bündeln:

npx webpack serve --config webpack.config.js

Manuelle Schritte zum Einrichten des Anrufs:

  1. Navigieren Sie in Ihrem Browser zu http://localhost:8080/..
  2. Geben Sie ein gültiges Benutzerzugriffstoken ein. Wenn Sie noch über kein Zugriffstoken verfügen, finden Sie in der Dokumentation zu Benutzerzugriffstoken weitere Informationen.
  3. Klicken Sie auf die Schaltflächen „Anruf-Agent initialisieren“.
  4. Geben Sie die ID des Anrufwarteschlangenobjekts ein, und wählen Sie die Schaltfläche „Anruf starten“ aus. Die Anwendung wird den ausgehenden Aufruf an die Anrufwarteschlange mit der angegebenen Objekt-ID starten.
  5. Der Anruf ist mit der Anrufwarteschlange verbunden.
  6. Der Communication Services-Benutzer wird basierend auf der Konfiguration durch die Anrufwarteschlange weitergeleitet.

Wichtig

Dieses Feature von Azure Communication Services befindet sich derzeit in der Vorschau.

Vorschau-APIs und -SDKs werden ohne Vereinbarung zum Servicelevel bereitgestellt. Es wird empfohlen, diese nicht für Produktionsworkloads zu verwenden. Einige Features werden möglicherweise nicht unterstützt oder bieten nur eingeschränkte Funktionalität.

Weitere Informationen finden Sie in den ergänzenden Nutzungsbestimmungen für Microsoft Azure-Vorschauversionen.

In diesem Schnellstart werden Sie erfahren, wie Sie einen Anruf von einem Azure Communication Services-Benutzer an die Teams-Anrufwarteschlange starten. Sie werden dies mit den folgenden Schritten erreichen:

  1. Aktivieren Sie den Verbund der Azure Communication Services-Ressource mit dem Teams-Mandanten.
  2. Wählen oder erstellen Sie die Teams-Anrufwarteschlange über das Teams Admin Center.
  3. Rufen Sie die E-Mail-Adresse der Anrufwarteschlange über das Teams Admin Center ab.
  4. Rufen Sie die Objekt-ID der Anrufwarteschlange über die Graph-API ab.
  5. Starten Sie einen Anruf mit dem Anruf-SDK von Azure Communication Services.

Wenn Sie direkt zum Ende springen möchten, können Sie diese Schnellstartanleitung als Beispiel auf GitHub herunterladen.

Aktivieren der Interoperabilität in Ihrem Teams-Mandanten

Microsoft Entra-Benutzer mit der Teams-Administratorrolle können das PowerShell-Cmdlet mit dem MicrosoftTeams-Modul ausführen, um die Communication Services-Ressource im Mandanten zu aktivieren.

1. Vorbereiten des Microsoft Teams-Moduls

Öffnen Sie zunächst die PowerShell, und überprüfen Sie das Vorhandensein des Teams-Moduls mit dem folgenden Befehl:

Get-module *teams* 

Wenn das MicrosoftTeams-Modul nicht angezeigt wird, installieren Sie es zuerst. Um das Modul zu installieren, müssen Sie PowerShell als Administrator ausführen. Führen Sie dann den folgenden Befehl aus:

	Install-Module -Name MicrosoftTeams

Sie werden über die Module informiert, die installiert werden, die Sie mit der Antwort Y oder A bestätigen können. Wenn das Modul installiert, aber veraltet ist, können Sie den folgenden Befehl ausführen, um das Modul zu aktualisieren:

	Update-Module MicrosoftTeams

2. Herstellen einer Verbindung mit dem Microsoft Teams-Modul

Wenn das Modul installiert und bereit ist, können Sie mit dem folgenden Befehl eine Verbindung mit dem MicrosftTeams-Modul herstellen. Sie werden aufgefordert, sich mit einem interaktiven Fenster anzumelden. Das Benutzerkonto, das Sie verwenden möchten, muss über Teams-Administratorberechtigungen verfügen. Andernfalls erhalten Sie möglicherweise in den nächsten Schritten die Antwort access denied.

Connect-MicrosoftTeams

3. Aktivieren der Mandantenkonfiguration

Die Interoperabilität mit Communication Services-Ressourcen wird über die Mandantenkonfiguration und die zugewiesene Richtlinie gesteuert. Der Teams-Mandant verfügt über eine einzelne Mandantenkonfiguration, und Teams-Benutzer*innen wurde eine globale Richtlinie oder eine benutzerdefinierte Richtlinie zugewiesen. Weitere Informationen finden Sie unter Zuweisen von Richtlinien in Teams.

Nach erfolgreicher Anmeldung können Sie das Cmdlet Set-CsTeamsAcsFederationConfiguration ausführen, um die Communication Services-Ressource in Ihrem Mandanten zu aktivieren. Ersetzen Sie den Text IMMUTABLE_RESOURCE_ID durch eine unveränderliche Ressourcen-ID in Ihrer Kommunikationsressource. Weitere Informationen zum Abrufen dieser Informationen finden Sie hier.

$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist

4. Aktivieren der Mandantenrichtlinie

Jedem Teams-Benutzer wurde eine External Access Policy zugewiesen, die festlegt, ob Communication Services-Benutzer*innen diese Teams-Benutzer*in bzw. diesen Teams-Benutzer aufrufen können. Verwenden Sie das Cmdlet Set-CsExternalAccessPolicy, um sicherzustellen, dass für die der Teams-Benutzer*in bzw. dem Teams-Benutzer zugewiesene Richtlinie EnableAcsFederationAccess auf $true festgelegt ist

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Erstellen oder Auswählen einer Teams-Anrufwarteschlange

Die Teams-Anrufwarteschlange ist ein Feature in Microsoft Teams, das eingehende Anrufe effizient an eine Gruppe von bestimmten Benutzern oder Agenten verteilt. Es ist nützlich für Kundensupport- oder Callcenterszenarien. Aufrufe werden in eine Warteschlange gestellt und dem nächsten verfügbaren Agenten basierend auf einer vordefinierten Routingmethode zugewiesen. Agenten erhalten Benachrichtigungen und können Anrufe mithilfe der Anrufsteuerelementen von Teams verarbeiten. Das Feature bietet Berichte und Analysen für die Leistungsnachverfolgung. Es vereinfacht die Anrufbehandlung, stellt eine konsistente Kundenerfahrung sicher und optimiert die Produktivität der Agenten. Sie können über das Teams Admin Center eine vorhandene Anrufwarteschlange auswählen oder eine neue erstellen.

Weitere Informationen zum Erstellen der Anrufwarteschlange mit dem Teams Admin Center finden Sie hier.

Objekt-ID für Anrufwarteschlange suchen

Nachdem die Anrufwarteschlange erstellt wurde, müssen wir die korrelierte Objekt-ID suchen, um sie später für Aufrufe verwenden zu können. Die Objekt-ID ist mit dem Ressourcenkonto verbunden, das an die Anrufwarteschlange angefügt wurde. Öffnen Sie die Registerkarte „Ressourcenkonten“ in Teams Admin, und suchen Sie nach der E-Mail. Screenshot der Ressourcenkonten im Teams Admin-Portal. Alle erforderlichen Informationen zu Ressourcenkonten können im Microsoft Graph-Explorer gefunden werden, indem diese E-Mail in der Suche verwendet wird.

https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com

In den Ergebnissen können wir das Feld „ID“ finden

    "userPrincipalName": "lab-test2-cq@contoso.com",
    "id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"

Um sie in der Anruf-App zu verwenden, müssen wir dieser ID ein Präfix hinzufügen. Derzeit wird Folgendes unterstützt:

  • Anrufwarteschleife in der öffentlichen Cloud: 28:orgid:<id>
  • Anrufwarteschleife in der Government Cloud: 28:gcch:<id>

Voraussetzungen

Einrichten

Erstellen Sie eine Android-App mit einer leeren Aktivität.

Wählen Sie in Android Studio „Start a new Android Studio project“ (Neues Android Studio-Projekt starten) aus.

Ein Screenshot, der die Schaltfläche „Start a new Android Studio project“ (Neues Android Studio-Projekt starten) zeigt, die in Android Studio ausgewählt ist

Wählen Sie unter „Phone and Tablet“ (Telefon und Tablet) die Projektvorlage „Empty Views Activity“ (Leere Ansicht-Aktivität) aus.

Screenshot, der die Option „Empty Activity“ (Leere Aktivität) zeigt, die auf dem Bildschirm für die Projektvorlage ausgewählt ist

Wählen Sie das SDK „API 26: Android 8.0 (Oreo)“ oder höher aus.

Screenshot, der die Option „Empty Activity“ (Leere Aktivität) zeigt, die auf dem Bildschirm für die Projektvorlage 2 ausgewählt ist

Installieren des Pakets

Wählen Sie Ihr Projekt settings.gradle.kts aus, und stellen Sie sicher, dass Sie mavenCentral() zur Liste der Repositorys unter pluginManagement und dependencyResolutionManagement hinzufügen

pluginManagement {
    repositories {
    ...
        mavenCentral()
    ...
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    ...
        mavenCentral()
    }
}

Fügen Sie anschließend in der Datei „build.gradle“ auf Modulebene die folgenden Zeilen zu den Abschnitten „dependencies“ und „android“ hinzu.

android {
    ...
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    implementation ("com.azure.android:azure-communication-calling:2.6.0")
    ...
}

Hinzufügen von Berechtigungen zum Anwendungsmanifest

Damit Sie Berechtigungen anfordern können, die für einen Anruf erforderlich sind, müssen diese zunächst im Anwendungsmanifest (app/src/main/AndroidManifest.xml) deklariert werden. Ersetzen Sie den Inhalt der Datei durch den folgenden Code:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.contoso.acsquickstart">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--Our Calling SDK depends on the Apache HTTP SDK.
When targeting Android SDK 28+, this library needs to be explicitly referenced.
See https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
    

Festlegen des Layouts für die App

Zwei Eingaben sind erforderlich: eine Texteingabe für die Angerufenen-ID und eine Schaltfläche zum Tätigen des Anrufs. Diese Eingaben können über den Designer oder durch Bearbeiten der Layout-XML-Datei hinzugefügt werden. Erstellen Sie eine Schaltfläche mit der ID von call_button und einer Texteingabe für callee_id. Navigieren Sie zu app/src/main/res/layout/activity_main.xml, und ersetzen Sie den Inhalt der Datei durch den folgenden Code:

<?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="${launchApp}">

    <EditText
        android:id="@+id/callee_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Callee Id"
        android:inputType="textPersonName"
        android:layout_marginTop="100dp"
        android:layout_marginHorizontal="20dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="46dp"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <Button
            android:id="@+id/call_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Call" />

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

    </LinearLayout>

    <TextView
        android:id="@+id/status_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Erstellen des Hauptaktivitätsgerüsts und der Bindungen

Nachdem das Layout erstellt wurde, können die Bindungen und das Grundgerüst der Aktivität hinzugefügt werden. Die Aktivität verarbeitet das Anfordern von Runtime-Berechtigungen, erstellt den Anruf-Agent und platziert den Anruf, wenn die Schaltfläche gedrückt wird. Die onCreate-Methode wird überschrieben, um getAllPermissions und createAgent aufzurufen und die Bindungen für die Schaltfläche „Anruf“ hinzuzufügen. Dieses Ereignis tritt nur einmal auf, wenn die Aktivität erstellt wird. Weitere Informationen zu onCreate finden Sie im Leitfaden mit grundlegenden Informationen zum Aktivitätslebenszyklus.

Navigieren Sie zu MainActivity.java, und ersetzen Sie den Inhalt durch den folgenden Code:

package com.contoso.acsquickstart;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import com.azure.android.communication.common.CommunicationIdentifier;
import com.azure.android.communication.common.CommunicationUserIdentifier;
import com.azure.android.communication.calling.Call;
import com.azure.android.communication.calling.CallAgent;
import com.azure.android.communication.calling.CallClient;
import com.azure.android.communication.calling.HangUpOptions;
import com.azure.android.communication.common.CommunicationTokenCredential;
import com.azure.android.communication.calling.StartCallOptions;

public class MainActivity extends AppCompatActivity {
    private static final String[] allPermissions = new String[] { Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE };
    private static final String UserToken = "<User_Access_Token>";

    TextView statusBar;

    private CallAgent agent;
    private Call call;
    private Button callButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        callButton = findViewById(R.id.call_button);

        getAllPermissions();
        createAgent();
        callButton.setOnClickListener(l -> startCall());

        Button hangupButton = findViewById(R.id.hangup_button);
        hangupButton.setOnClickListener(l -> endCall());

        statusBar = findViewById(R.id.status_bar);
        
        setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
    }

    /**
     * Start a call
     */
    private void startCall() {
        if (UserToken.startsWith("<")) {
            Toast.makeText(this, "Please enter token in source code", Toast.LENGTH_SHORT).show();
            return;
        }

        EditText calleeIdView = findViewById(R.id.callee_id);
        String calleeId = calleeIdView.getText().toString();
        if (calleeId.isEmpty()) {
            Toast.makeText(this, "Please enter callee", Toast.LENGTH_SHORT).show();
            return;
        }
        ArrayList<CommunicationIdentifier> participants = new ArrayList<>();
        participants.add(new MicrosoftTeamsAppIdentifier(calleeId));
        StartCallOptions options = new StartCallOptions();
        call = agent.startCall(
                getApplicationContext(),
                participants,
                options);
        call.addOnStateChangedListener(p -> setStatus(call.getState().toString()));
    }

    /**
     * Ends the call previously started
     */
    private void endCall() {
        try {
            call.hangUp(new HangUpOptions()).get();
        } catch (ExecutionException | InterruptedException e) {
            Toast.makeText(this, "Unable to hang up call", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Create the call agent
     */
    private void createAgent() {
        try {
            CommunicationTokenCredential credential = new CommunicationTokenCredential(UserToken);
            agent = new CallClient().createCallAgent(getApplicationContext(), credential).get();
        } catch (Exception ex) {
            Toast.makeText(getApplicationContext(), "Failed to create call agent.", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Ensure all permissions were granted, otherwise inform the user permissions are missing.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, int[] grantResults) {
        boolean allPermissionsGranted = true;
        for (int result : grantResults) {
            allPermissionsGranted &= (result == PackageManager.PERMISSION_GRANTED);
        }
        if (!allPermissionsGranted) {
            Toast.makeText(this, "All permissions are needed to make the call.", Toast.LENGTH_LONG).show();
            finish();
        }
    }

    /**
     * Shows message in the status bar
     */
    private void setStatus(String status) {
        runOnUiThread(() -> statusBar.setText(status));
    }
}

Anfordern von Berechtigungen zur Runtime

Für Android 6.0 und höher (API-Ebene 23) und targetSdkVersion 23 oder höher werden Berechtigungen zur Runtime gewährt und nicht bei der Installation der App. Damit dies unterstützt wird, kann getAllPermissions implementiert werden, um für jede erforderliche Berechtigung ActivityCompat.checkSelfPermission und ActivityCompat.requestPermissions aufzurufen.

/**
 * Request each required permission if the app doesn't already have it.
 */
private void getAllPermissions() {
    ArrayList<String> permissionsToAskFor = new ArrayList<>();
    for (String permission : allPermissions) {
        if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            permissionsToAskFor.add(permission);
        }
    }
    if (!permissionsToAskFor.isEmpty()) {
        ActivityCompat.requestPermissions(this, permissionsToAskFor.toArray(new String[0]), 1);
    }
}

Hinweis

Berücksichtigen Sie beim Entwerfen der App, wann diese Berechtigungen angefordert werden sollen. Berechtigungen müssen angefordert werden, wenn sie benötigt werden, und nicht vorher. Weitere Informationen finden Sie im Leitfaden zu Android-Berechtigungen.

Objektmodell

Die folgenden Klassen und Schnittstellen befassen sich mit einigen der wichtigsten Features des Azure Communication Services Calling SDK:

Name BESCHREIBUNG
CallClient CallClient ist der Haupteinstiegspunkt des Calling SDK.
CallAgent CallAgent dient zum Starten und Verwalten von Anrufen.
CommunicationTokenCredential CommunicationTokenCredential dient als tokengestützte Anmeldeinformation zum Instanziieren von CallAgent.
CommunicationIdentifier CommunicationIdentifier wird als anderer Typ von Teilnehmer verwendet, der Teil eines Anrufs sein könnte.

Erstellen eines Agents aus dem Benutzerzugriffstoken

Mit einem Benutzertoken kann ein authentifizierter Anruf-Agent instanziiert werden. In der Regel wird dieses Token von einem Dienst mit einer für die Anwendung spezifischen Authentifizierung generiert. Weitere Informationen zu Benutzerzugriffstoken finden Sie im Leitfaden zu Benutzerzugriffstoken.

Ersetzen Sie für den Schnellstart <User_Access_Token> durch ein Benutzerzugriffstoken, das für Ihre Azure Communication Service-Ressource generiert wurde.


/**
 * Create the call agent for placing calls
 */
private void createAgent() {
    String userToken = "<User_Access_Token>";

    try {
            CommunicationTokenCredential credential = new CommunicationTokenCredential(userToken);
            callAgent = new CallClient().createCallAgent(getApplicationContext(), credential).get();
    } catch (Exception ex) {
        Toast.makeText(getApplicationContext(), "Failed to create call agent.", Toast.LENGTH_SHORT).show();
    }
}

Ausführen des Codes

Die App kann jetzt mithilfe der Schaltfläche „Anwendung ausführen“ auf der Symbolleiste gestartet werden.

Manuelle Schritte zum Einrichten des Anrufs:

  1. Starten Sie die App mit Android Studio.
  2. Geben Sie die ID des Anrufwarteschlangenobjekts ein (mit Präfix), und wählen Sie die Schaltfläche „Anruf starten“ aus. Die Anwendung wird den ausgehenden Aufruf an die Anrufwarteschlange mit der angegebenen Objekt-ID starten.
  3. Der Anruf ist mit der Anrufwarteschlange verbunden.
  4. Der Communication Services-Benutzer wird basierend auf der Konfiguration durch die Anrufwarteschlange weitergeleitet.

Wichtig

Dieses Feature von Azure Communication Services befindet sich derzeit in der Vorschau.

Vorschau-APIs und -SDKs werden ohne Vereinbarung zum Servicelevel bereitgestellt. Es wird empfohlen, diese nicht für Produktionsworkloads zu verwenden. Einige Features werden möglicherweise nicht unterstützt oder bieten nur eingeschränkte Funktionalität.

Weitere Informationen finden Sie in den ergänzenden Nutzungsbestimmungen für Microsoft Azure-Vorschauversionen.

In diesem Schnellstart werden Sie erfahren, wie Sie einen Anruf von einem Azure Communication Services-Benutzer an die Teams-Anrufwarteschlange starten. Sie werden dies mit den folgenden Schritten erreichen:

  1. Aktivieren Sie den Verbund der Azure Communication Services-Ressource mit dem Teams-Mandanten.
  2. Wählen oder erstellen Sie die Teams-Anrufwarteschlange über das Teams Admin Center.
  3. Rufen Sie die E-Mail-Adresse der Anrufwarteschlange über das Teams Admin Center ab.
  4. Rufen Sie die Objekt-ID der Anrufwarteschlange über die Graph-API ab.
  5. Starten Sie einen Anruf mit dem Anruf-SDK von Azure Communication Services.

Wenn Sie direkt zum Ende springen möchten, können Sie diese Schnellstartanleitung als Beispiel auf GitHub herunterladen.

Aktivieren der Interoperabilität in Ihrem Teams-Mandanten

Microsoft Entra-Benutzer mit der Teams-Administratorrolle können das PowerShell-Cmdlet mit dem MicrosoftTeams-Modul ausführen, um die Communication Services-Ressource im Mandanten zu aktivieren.

1. Vorbereiten des Microsoft Teams-Moduls

Öffnen Sie zunächst die PowerShell, und überprüfen Sie das Vorhandensein des Teams-Moduls mit dem folgenden Befehl:

Get-module *teams* 

Wenn das MicrosoftTeams-Modul nicht angezeigt wird, installieren Sie es zuerst. Um das Modul zu installieren, müssen Sie PowerShell als Administrator ausführen. Führen Sie dann den folgenden Befehl aus:

	Install-Module -Name MicrosoftTeams

Sie werden über die Module informiert, die installiert werden, die Sie mit der Antwort Y oder A bestätigen können. Wenn das Modul installiert, aber veraltet ist, können Sie den folgenden Befehl ausführen, um das Modul zu aktualisieren:

	Update-Module MicrosoftTeams

2. Herstellen einer Verbindung mit dem Microsoft Teams-Modul

Wenn das Modul installiert und bereit ist, können Sie mit dem folgenden Befehl eine Verbindung mit dem MicrosftTeams-Modul herstellen. Sie werden aufgefordert, sich mit einem interaktiven Fenster anzumelden. Das Benutzerkonto, das Sie verwenden möchten, muss über Teams-Administratorberechtigungen verfügen. Andernfalls erhalten Sie möglicherweise in den nächsten Schritten die Antwort access denied.

Connect-MicrosoftTeams

3. Aktivieren der Mandantenkonfiguration

Die Interoperabilität mit Communication Services-Ressourcen wird über die Mandantenkonfiguration und die zugewiesene Richtlinie gesteuert. Der Teams-Mandant verfügt über eine einzelne Mandantenkonfiguration, und Teams-Benutzer*innen wurde eine globale Richtlinie oder eine benutzerdefinierte Richtlinie zugewiesen. Weitere Informationen finden Sie unter Zuweisen von Richtlinien in Teams.

Nach erfolgreicher Anmeldung können Sie das Cmdlet Set-CsTeamsAcsFederationConfiguration ausführen, um die Communication Services-Ressource in Ihrem Mandanten zu aktivieren. Ersetzen Sie den Text IMMUTABLE_RESOURCE_ID durch eine unveränderliche Ressourcen-ID in Ihrer Kommunikationsressource. Weitere Informationen zum Abrufen dieser Informationen finden Sie hier.

$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist

4. Aktivieren der Mandantenrichtlinie

Jedem Teams-Benutzer wurde eine External Access Policy zugewiesen, die festlegt, ob Communication Services-Benutzer*innen diese Teams-Benutzer*in bzw. diesen Teams-Benutzer aufrufen können. Verwenden Sie das Cmdlet Set-CsExternalAccessPolicy, um sicherzustellen, dass für die der Teams-Benutzer*in bzw. dem Teams-Benutzer zugewiesene Richtlinie EnableAcsFederationAccess auf $true festgelegt ist

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Erstellen oder Auswählen einer Teams-Anrufwarteschlange

Die Teams-Anrufwarteschlange ist ein Feature in Microsoft Teams, das eingehende Anrufe effizient an eine Gruppe von bestimmten Benutzern oder Agenten verteilt. Es ist nützlich für Kundensupport- oder Callcenterszenarien. Aufrufe werden in eine Warteschlange gestellt und dem nächsten verfügbaren Agenten basierend auf einer vordefinierten Routingmethode zugewiesen. Agenten erhalten Benachrichtigungen und können Anrufe mithilfe der Anrufsteuerelementen von Teams verarbeiten. Das Feature bietet Berichte und Analysen für die Leistungsnachverfolgung. Es vereinfacht die Anrufbehandlung, stellt eine konsistente Kundenerfahrung sicher und optimiert die Produktivität der Agenten. Sie können über das Teams Admin Center eine vorhandene Anrufwarteschlange auswählen oder eine neue erstellen.

Weitere Informationen zum Erstellen der Anrufwarteschlange mit dem Teams Admin Center finden Sie hier.

Objekt-ID für Anrufwarteschlange suchen

Nachdem die Anrufwarteschlange erstellt wurde, müssen wir die korrelierte Objekt-ID suchen, um sie später für Aufrufe verwenden zu können. Die Objekt-ID ist mit dem Ressourcenkonto verbunden, das an die Anrufwarteschlange angefügt wurde. Öffnen Sie die Registerkarte „Ressourcenkonten“ in Teams Admin, und suchen Sie nach der E-Mail. Screenshot der Ressourcenkonten im Teams Admin-Portal. Alle erforderlichen Informationen zu Ressourcenkonten können im Microsoft Graph-Explorer gefunden werden, indem diese E-Mail in der Suche verwendet wird.

https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com

In den Ergebnissen können wir das Feld „ID“ finden

    "userPrincipalName": "lab-test2-cq@contoso.com",
    "id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"

Um sie in der Anruf-App zu verwenden, müssen wir dieser ID ein Präfix hinzufügen. Derzeit wird Folgendes unterstützt:

  • Anrufwarteschleife in der öffentlichen Cloud: 28:orgid:<id>
  • Anrufwarteschleife in der Government Cloud: 28:gcch:<id>

Voraussetzungen

  • Rufen Sie ein Azure-Konto mit einem aktiven Abonnement ab. Sie können kostenlos ein Konto erstellen.

  • Einen Mac mit Xcode zusammen mit einem gültigen in Ihrer Keychain installierten Entwicklerzertifikat.

  • Eine bereitgestellte Communication Services-Ressource. Erstellen Sie eine Communication Services-Ressource. Für diese Schnellstartanleitung müssen Sie Ihre Verbindungszeichenfolge erfassen.

  • Ein Benutzerzugriffstoken für Ihren Azure Communication Service Sie können auch die Azure CLI verwenden und den Befehl mit Ihrer Verbindungszeichenfolge ausführen, um einen Benutzer und ein Zugriffs-Token zu erstellen.

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

    Ausführliche Informationen finden Sie unter Verwenden der Azure CLI zum Erstellen und Verwalten von Zugriffstoken.

  • Mindestunterstützung für Teams-Anrufanwendungen: 2.14.0-beta.1

Einrichten

Erstellen des Xcode-Projekts

Erstellen Sie in Xcode ein neues iOS-Projekt, und wählen Sie die Vorlage App aus. In diesem Tutorial wird das SwiftUI-Framework verwendet, weshalb Sie Language (Sprache) auf Swift und User Interface (Benutzeroberfläche) auf SwiftUI festlegen müssen. Im Rahmen dieses Schnellstarts werden keine Tests erstellt. Sie können die Option Tests einschließen daher deaktivieren.

Screenshot des Fensters „Neues Projekt“ in Xcode

Installieren des Pakets und der Abhängigkeiten mit CocoaPods

  1. Zum Erstellen einer Podfile-Datei für Ihre Anwendung müssen Sie das Terminal öffnen, zum Projektordner navigieren und Folgendes ausführen:

    pod init

  2. Fügen Sie den folgenden Code in die Podfile-Datei ein, und speichern Sie die Datei (stellen Sie sicher, dass „target (Ziel)“ mit dem Namen Ihres Projekts übereinstimmt):

    platform :ios, '13.0'
    use_frameworks!
    
    target 'AzureCommunicationCallingSample' do
      pod 'AzureCommunicationCalling', '~> 2.14.0-beta.1'
    end
    
  3. Führen Sie pod install aus.

  4. Öffnen Sie .xcworkspace mit Xcode.

Anfordern des Zugriffs auf das Mikrofon

Damit Sie auf das Mikrofon des Geräts zugreifen zu können, müssen Sie die Liste der Informationseigenschaften Ihrer App mit NSMicrophoneUsageDescription aktualisieren. Legen Sie den zugehörigen Wert auf eine Zeichenfolge (string) fest, die in den Dialog aufgenommen wurde, mit dem das System den Zugriff beim Benutzer anfordert.

Klicken Sie mit der rechten Maustaste auf den Eintrag Info.plist der Projektstruktur, und wählen Sie anschließend Open As (Öffnen als) >Source Code (Quellcode) aus. Fügen Sie die folgenden Zeilen im Abschnitt <dict> der obersten Ebene hinzu, und speichern anschließend Sie die Datei.

<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>

Einrichten des App-Frameworks

Öffnen Sie die Datei ContentView.swift Ihres Projekts, und fügen Sie am Anfang der Datei eine import-Deklaration hinzu, um AzureCommunicationCalling library zu importieren. Importieren Sie außerdem AVFoundation; wir benötigen diesen Code für die Berechtigungsanforderung für Audio im Code.

import AzureCommunicationCalling
import AVFoundation

Ersetzen Sie die Implementierung der ContentView-Struktur durch einige einfache Benutzeroberflächen-Steuerelemente, die einem Benutzer das Initiieren und Beenden eines Anrufs ermöglichen. In dieser Schnellstartanleitung fügen wir Geschäftslogik an diese Steuerelemente an.

struct ContentView: View {
    @State var callee: String = ""
    @State var callClient: CallClient?
    @State var callAgent: CallAgent?
    @State var call: Call?

    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Who would you like to call?", text: $callee)
                    Button(action: startCall) {
                        Text("Start Call")
                    }.disabled(callAgent == nil)
                    Button(action: endCall) {
                        Text("End Call")
                    }.disabled(call == nil)
                }
            }
            .navigationBarTitle("Calling Quickstart")
        }.onAppear {
            // Initialize call agent
        }
    }

    func startCall() {
        // Ask permissions
        AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
            if granted {
                // Add start call logic
            }
        }
    }

    func endCall() {
        // Add end call logic
    }
}

Objektmodell

Die folgenden Klassen und Schnittstellen befassen sich mit einigen der wichtigsten Features des Azure Communication Services Calling SDK:

Name BESCHREIBUNG
CallClient CallClient ist der Haupteinstiegspunkt des Calling SDK.
CallAgent CallAgent dient zum Starten und Verwalten von Anrufen.
CommunicationTokenCredential CommunicationTokenCredential dient als tokengestützte Anmeldeinformation zum Instanziieren von CallAgent.
CommunicationUserIdentifier CommunicationUserIdentifier wird zur Darstellung der Identität des Benutzers verwendet, die eine der folgenden Optionen sein kann: CommunicationUserIdentifier, PhoneNumberIdentifier oder CallingApplication.

Authentifizieren des Clients

Initialisieren Sie eine CallAgent-Instanz mit einem Benutzerzugriffs-Token, das es uns ermöglicht, Anrufe zu tätigen und zu empfangen.

Im folgenden Code müssen Sie <USER ACCESS TOKEN> durch ein gültiges Benutzerzugriffs-Token für Ihre Ressource ersetzen. Wenn Sie noch über kein Token verfügen, finden Sie unter Benutzerzugriffstoken weitere Informationen.

Fügen Sie den folgenden Code zum onAppear-Rückruf in ContentView.swift hinzu:

var userCredential: CommunicationTokenCredential?
do {
    userCredential = try CommunicationTokenCredential(token: "<USER ACCESS TOKEN>")
} catch {
    print("ERROR: It was not possible to create user credential.")
    return
}

self.callClient = CallClient()

// Creates the call agent
self.callClient?.createCallAgent(userCredential: userCredential!) { (agent, error) in
    if error != nil {
        print("ERROR: It was not possible to create a call agent.")
        return
    }
    else {
        self.callAgent = agent
        print("Call agent successfully created.")
    }
}

Beginnen eines Anrufs

Die Methode startCall wird als die Aktion festgelegt, die ausgeführt wird, wenn auf die Schaltfläche Start Call (Anruf starten) getippt wird. Aktualisieren Sie die Implementierung, um einen Anruf mit ASACallAgent zu beginnen:

func startCall()
{
    // Ask permissions
    AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
        if granted {
            // start call logic
            let callees:[CommunicationIdentifier] = [MicrosoftTeamsAppIdentifier(self.callee)]
            self.callAgent?.startCall(participants: callees, options: StartCallOptions()) { (call, error) in
                if (error == nil) {
                    self.call = call
                } else {
                    print("Failed to get call object")
                }
            }
        }
    }
}

Sie können auch die Eigenschaften in StartCallOptions verwenden, um die Anfangsoptionen für den Anruf festzulegen (d. h. Sie können den Anruf mit stummgeschaltetem Mikrofon starten).

Beenden eines Anrufs

Implementieren Sie die Methode endCall, um den aktuellen Anruf zu beenden, wenn auf die Schaltfläche End Call (Anruf beenden) getippt wird.

func endCall()
{    
    self.call!.hangUp(options: HangUpOptions()) { (error) in
        if (error != nil) {
            print("ERROR: It was not possible to hangup the call.")
        }
    }
}

Ausführen des Codes

Sie können Ihre App im iOS-Simulator erstellen und ausführen, indem Sie Produkt>Ausführen auswählen oder den Tastaturkurzbefehl (⌘-R) verwenden.

Hinweis

Wenn Sie zum ersten Mal einen Anruf tätigen, fordert das System Zugriff auf das Mikrofon an. Verwenden Sie in einer Produktionsanwendung die AVAudioSession-API, um den Berechtigungsstatus zu überprüfen und das Verhalten Ihrer Anwendung entsprechend zu aktualisieren, wenn die Berechtigung nicht erteilt wird.

Manuelle Schritte zum Einrichten des Anrufs:

  1. Starten der App mit Xcode
  2. Geben Sie die ID des Anrufwarteschlangenobjekts ein (mit Präfix), und wählen Sie die Schaltfläche „Anruf starten“ aus. Die Anwendung wird den ausgehenden Aufruf an die Anrufwarteschlange mit der angegebenen Objekt-ID starten.
  3. Der Anruf ist mit der Anrufwarteschlange verbunden.
  4. Der Communication Services-Benutzer wird basierend auf der Konfiguration durch die Anrufwarteschlange weitergeleitet.

Wichtig

Dieses Feature von Azure Communication Services befindet sich derzeit in der Vorschau.

Vorschau-APIs und -SDKs werden ohne Vereinbarung zum Servicelevel bereitgestellt. Es wird empfohlen, diese nicht für Produktionsworkloads zu verwenden. Einige Features werden möglicherweise nicht unterstützt oder bieten nur eingeschränkte Funktionalität.

Weitere Informationen finden Sie in den ergänzenden Nutzungsbestimmungen für Microsoft Azure-Vorschauversionen.

In diesem Schnellstart werden Sie erfahren, wie Sie einen Anruf von einem Azure Communication Services-Benutzer an die Teams-Anrufwarteschlange starten. Sie werden dies mit den folgenden Schritten erreichen:

  1. Aktivieren Sie den Verbund der Azure Communication Services-Ressource mit dem Teams-Mandanten.
  2. Wählen oder erstellen Sie die Teams-Anrufwarteschlange über das Teams Admin Center.
  3. Rufen Sie die E-Mail-Adresse der Anrufwarteschlange über das Teams Admin Center ab.
  4. Rufen Sie die Objekt-ID der Anrufwarteschlange über die Graph-API ab.
  5. Starten Sie einen Anruf mit dem Anruf-SDK von Azure Communication Services.

Wenn Sie direkt zum Ende springen möchten, können Sie diese Schnellstartanleitung als Beispiel auf GitHub herunterladen.

Aktivieren der Interoperabilität in Ihrem Teams-Mandanten

Microsoft Entra-Benutzer mit der Teams-Administratorrolle können das PowerShell-Cmdlet mit dem MicrosoftTeams-Modul ausführen, um die Communication Services-Ressource im Mandanten zu aktivieren.

1. Vorbereiten des Microsoft Teams-Moduls

Öffnen Sie zunächst die PowerShell, und überprüfen Sie das Vorhandensein des Teams-Moduls mit dem folgenden Befehl:

Get-module *teams* 

Wenn das MicrosoftTeams-Modul nicht angezeigt wird, installieren Sie es zuerst. Um das Modul zu installieren, müssen Sie PowerShell als Administrator ausführen. Führen Sie dann den folgenden Befehl aus:

	Install-Module -Name MicrosoftTeams

Sie werden über die Module informiert, die installiert werden, die Sie mit der Antwort Y oder A bestätigen können. Wenn das Modul installiert, aber veraltet ist, können Sie den folgenden Befehl ausführen, um das Modul zu aktualisieren:

	Update-Module MicrosoftTeams

2. Herstellen einer Verbindung mit dem Microsoft Teams-Modul

Wenn das Modul installiert und bereit ist, können Sie mit dem folgenden Befehl eine Verbindung mit dem MicrosftTeams-Modul herstellen. Sie werden aufgefordert, sich mit einem interaktiven Fenster anzumelden. Das Benutzerkonto, das Sie verwenden möchten, muss über Teams-Administratorberechtigungen verfügen. Andernfalls erhalten Sie möglicherweise in den nächsten Schritten die Antwort access denied.

Connect-MicrosoftTeams

3. Aktivieren der Mandantenkonfiguration

Die Interoperabilität mit Communication Services-Ressourcen wird über die Mandantenkonfiguration und die zugewiesene Richtlinie gesteuert. Der Teams-Mandant verfügt über eine einzelne Mandantenkonfiguration, und Teams-Benutzer*innen wurde eine globale Richtlinie oder eine benutzerdefinierte Richtlinie zugewiesen. Weitere Informationen finden Sie unter Zuweisen von Richtlinien in Teams.

Nach erfolgreicher Anmeldung können Sie das Cmdlet Set-CsTeamsAcsFederationConfiguration ausführen, um die Communication Services-Ressource in Ihrem Mandanten zu aktivieren. Ersetzen Sie den Text IMMUTABLE_RESOURCE_ID durch eine unveränderliche Ressourcen-ID in Ihrer Kommunikationsressource. Weitere Informationen zum Abrufen dieser Informationen finden Sie hier.

$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist

4. Aktivieren der Mandantenrichtlinie

Jedem Teams-Benutzer wurde eine External Access Policy zugewiesen, die festlegt, ob Communication Services-Benutzer*innen diese Teams-Benutzer*in bzw. diesen Teams-Benutzer aufrufen können. Verwenden Sie das Cmdlet Set-CsExternalAccessPolicy, um sicherzustellen, dass für die der Teams-Benutzer*in bzw. dem Teams-Benutzer zugewiesene Richtlinie EnableAcsFederationAccess auf $true festgelegt ist

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Erstellen oder Auswählen einer Teams-Anrufwarteschlange

Die Teams-Anrufwarteschlange ist ein Feature in Microsoft Teams, das eingehende Anrufe effizient an eine Gruppe von bestimmten Benutzern oder Agenten verteilt. Es ist nützlich für Kundensupport- oder Callcenterszenarien. Aufrufe werden in eine Warteschlange gestellt und dem nächsten verfügbaren Agenten basierend auf einer vordefinierten Routingmethode zugewiesen. Agenten erhalten Benachrichtigungen und können Anrufe mithilfe der Anrufsteuerelementen von Teams verarbeiten. Das Feature bietet Berichte und Analysen für die Leistungsnachverfolgung. Es vereinfacht die Anrufbehandlung, stellt eine konsistente Kundenerfahrung sicher und optimiert die Produktivität der Agenten. Sie können über das Teams Admin Center eine vorhandene Anrufwarteschlange auswählen oder eine neue erstellen.

Weitere Informationen zum Erstellen der Anrufwarteschlange mit dem Teams Admin Center finden Sie hier.

Objekt-ID für Anrufwarteschlange suchen

Nachdem die Anrufwarteschlange erstellt wurde, müssen wir die korrelierte Objekt-ID suchen, um sie später für Aufrufe verwenden zu können. Die Objekt-ID ist mit dem Ressourcenkonto verbunden, das an die Anrufwarteschlange angefügt wurde. Öffnen Sie die Registerkarte „Ressourcenkonten“ in Teams Admin, und suchen Sie nach der E-Mail. Screenshot der Ressourcenkonten im Teams Admin-Portal. Alle erforderlichen Informationen zu Ressourcenkonten können im Microsoft Graph-Explorer gefunden werden, indem diese E-Mail in der Suche verwendet wird.

https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com

In den Ergebnissen können wir das Feld „ID“ finden

    "userPrincipalName": "lab-test2-cq@contoso.com",
    "id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"

Um sie in der Anruf-App zu verwenden, müssen wir dieser ID ein Präfix hinzufügen. Derzeit wird Folgendes unterstützt:

  • Anrufwarteschleife in der öffentlichen Cloud: 28:orgid:<id>
  • Anrufwarteschleife in der Government Cloud: 28:gcch:<id>

Voraussetzungen

Zum Durchführen dieses Tutorials benötigen Sie Folgendes:

Einrichten

Erstellen des Projekts

Erstellen Sie in Visual Studio ein neues Projekt mit der Vorlage Leere App (Universelle Windows-App) , um eine einseitige UWP-App (Universelle Windows-Plattform) einzurichten.

Screenshot des Fensters „Neues UWP Projekt“ in Visual Studio.

Installieren des Pakets

Klicken Sie mit der rechten Maustaste auf Ihr Projekt, und wechseln Sie zu Manage Nuget Packages, um Azure.Communication.Calling.WindowsClient 1.4.0 oder höher zu installieren. Stellen Sie sicher, dass Include Prerelease aktiviert ist, wenn Sie die Versionen für die öffentliche Vorschau anzeigen möchten.

Anfordern des Zugriffs

Wechseln Sie zu Package.appxmanifest, und wählen Sie Capabilities aus. Aktivieren Sie Internet (Client) und Internet (Client & Server), um ein- und ausgehenden Zugriff auf das Internet zu erhalten. Markieren Sie Microphone, um auf den Audiofeed des Mikrofons zuzugreifen und Webcam, um auf den Videofeed der Kamera zuzugreifen.

Screenshot: Anfordern des Zugriffs auf das Internet und das Mikrofon in Visual Studio

Einrichten des App-Frameworks

Wir müssen ein einfaches Layout konfigurieren, um unsere Logik anzufügen. Um einen ausgehenden Anruf zu tätigen, benötigen wir ein TextBox-Element, um die Benutzer-ID des Angerufenen bereitzustellen. Außerdem benötigen wir die Schaltflächen Start/Join call und Hang up. In diesem Beispiel sind auch die Kontrollkästchen A Mute und a BackgroundBlur enthalten, um die Funktionen des Umschaltens von Audiozuständen und Videoeffekten zu veranschaulichen.

Öffnen Sie das MainPage.xaml-Element Ihres Projekts, und fügen Sie Ihrer Page den Knoten Grid hinzu:

<Page
    x:Class="CallingQuickstart.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CallingQuickstart"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="800" Height="600">

        <!-- Don't forget to replace ‘CallingQuickstart’ with your project’s name -->


    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="16*"/>
            <RowDefinition Height="30*"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="16*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="10,10,10,10" />

        <Grid x:Name="AppTitleBar" Background="LightSeaGreen">
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="7,7,0,0"/>
        </Grid>

        <Grid Grid.Row="2">
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <MediaPlayerElement x:Name="LocalVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="0" VerticalAlignment="Center" AutoPlay="True" />
            <MediaPlayerElement x:Name="RemoteVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="1" VerticalAlignment="Center" AutoPlay="True" />
        </Grid>
        <StackPanel Grid.Row="3" Orientation="Vertical" Grid.RowSpan="2">
            <StackPanel Orientation="Horizontal">
                <Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <CheckBox x:Name="MuteLocal" Content="Mute" Margin="10,0,0,0" Click="MuteLocal_Click" Width="74"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="5" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>
</Page>

Öffnen Sie MainPage.xaml.cs, und ersetzen Sie den Inhalt durch folgende Implementierung:

using Azure.Communication.Calling.WindowsClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Core;
using Windows.Media.Core;
using Windows.Networking.PushNotifications;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace CallingQuickstart
{
    public sealed partial class MainPage : Page
    {
        private const string authToken = "<AUTHENTICATION_TOKEN>";

        private CallClient callClient;
        private CallTokenRefreshOptions callTokenRefreshOptions = new CallTokenRefreshOptions(false);
        private CallAgent callAgent;
        private CommunicationCall call;

        private LocalOutgoingAudioStream micStream;

        #region Page initialization
        public MainPage()
        {
            this.InitializeComponent();
            // Additional UI customization code goes here
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            await InitCallAgentAndDeviceManagerAsync();

            base.OnNavigatedTo(e);
        }
        #endregion

        #region UI event handlers
        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // Hang up a call
        }

        private async void MuteLocal_Click(object sender, RoutedEventArgs e)
        {
            // Toggle mute/unmute audio state of a call
        }
        #endregion

        #region API event handlers
        private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
        {
            // Handle incoming call event
        }

        private async void OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            // Handle connected and disconnected state change of a call
        }
        #endregion

        #region Helper methods

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            //Initialize the call agent and search for devices
        }


        private async Task<CommunicationCall> StartCallAsync(string acsCallee)
        {
            // Start a call to an Azure Communication Services user using the CallAgent and the callee id
        }

        #endregion
    }
}

Objektmodell

Die folgende Tabelle führt die Klassen und Schnittstellen auf, die sich mit einigen der wichtigsten Features des Calling SDK von Azure Communication Services befassen:

Name BESCHREIBUNG
CallClient CallClient ist der Haupteinstiegspunkt des Calling SDK.
CallAgent CallAgent dient zum Starten und Verwalten von Anrufen.
CommunicationCall CommunicationCall wird verwendet, um einen laufenden Anruf zu verwalten.
CallTokenCredential CallTokenCredential dient als tokengestützte Anmeldeinformation zum Instanziieren von CallAgent.
CallIdentifier CallIdentifier wird zur Darstellung der Identität des Benutzers verwendet, die eine der folgenden Optionen sein kann: UserCallIdentifier oder PhoneNumberCallIdentifier usw.

Authentifizieren des Clients

Initialisieren Sie eine CallAgent-Instanz mit einem Benutzerzugriffs-Token, mit dem wir Anrufe tätigen und empfangen können, und rufen Sie optional eine DeviceManager-Instanz ab, um auf Client-Gerätekonfigurationen abzufragen.

Ersetzen Sie im folgenden Code <AUTHENTICATION_TOKEN> durch ein Benutzerzugriffs-Token. Wenn Sie noch über kein Token verfügen, finden Sie in der Dokumentation zu Benutzerzugriffstoken weitere Informationen.

Fügen Sie die Funktion InitCallAgentAndDeviceManagerAsync hinzu , die das SDK lädt. Dieses Hilfsprogramm kann an die Anforderungen Ihrer Anwendung angepasst werden.

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            this.callClient = new CallClient(new CallClientOptions() {
                Diagnostics = new CallDiagnosticsOptions() { 
                    
                    // make sure to put your project AppName
                    AppName = "CallingQuickstart",

                    AppVersion="1.0",

                    Tags = new[] { "Calling", "ACS", "Windows" }
                    }

                });

            // Set up local audio stream using the first mic enumerated
            var deviceManager = await this.callClient.GetDeviceManagerAsync();
            var mic = deviceManager?.Microphones?.FirstOrDefault();

            micStream = new LocalOutgoingAudioStream();

            var tokenCredential = new CallTokenCredential(authToken, callTokenRefreshOptions);

            var callAgentOptions = new CallAgentOptions()
            {
                DisplayName = $"{Environment.MachineName}/{Environment.UserName}",
            };

            this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);

            this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
        }

Starten des Anrufs

Sobald ein Objekt StartCallOptions abgerufen wurde, kann CallAgent zum Initiieren des ACS-Anrufs (Azure Communication Services) verwendet werden:

        private async Task<CommunicationCall> StartCallAsync(string acsCallee)
        {
            var options = new StartCallOptions();
            var call = await this.callAgent.StartCallAsync( new [] { new MicrosoftTeamsAppCallIdentifier(acsCallee) }, options);
            return call;
        }

Beenden eines Anrufs

Beenden Sie den aktuellen Anruf, nachdem auf die Schaltfläche Hang up geklickt wurde. Fügen Sie die Implementierung zum „HangupButton_Click“ hinzu, um einen Anruf zu beenden, und beenden Sie die Vorschau und Videostreams.

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            var call = this.callAgent?.Calls?.FirstOrDefault();
            if (call != null)
            {
                await call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
            }
        }

Stummschalten/Lautschalten bei Audio

Schalten Sie das ausgehende Audio stumm, wenn auf die Schaltfläche Mute geklickt wird. Fügen Sie die Implementierung zum „MuteLocal_Click“ hinzu, um den Aufruf stummzuschalten.

        private async void MuteLocal_Click(object sender, RoutedEventArgs e)
        {
            var muteCheckbox = sender as CheckBox;

            if (muteCheckbox != null)
            {
                var call = this.callAgent?.Calls?.FirstOrDefault();

                if (call != null)
                {
                    if ((bool)muteCheckbox.IsChecked)
                    {
                        await call.MuteOutgoingAudioAsync();
                    }
                    else
                    {
                        await call.UnmuteOutgoingAudioAsync();
                    }
                }

                // Update the UI to reflect the state
            }
        }

Annehmen eines eingehenden Anrufs

Die Ereignissenke IncomingCallReceived ist im SDK-Bootstrap-Hilfsprogramm InitCallAgentAndDeviceManagerAsync eingerichtet.

    this.callAgent.IncomingCallReceived += OnIncomingCallAsync;

Die Anwendung hat die Möglichkeit, zu konfigurieren, wie der eingehende Anruf angenommen werden soll, z. B. Video- und Audiostreamtypen.

        private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
        {
            var incomingCall = args.IncomingCall;

            var acceptCallOptions = new AcceptCallOptions() { };

            call = await incomingCall.AcceptAsync(acceptCallOptions);
            call.StateChanged += OnStateChangedAsync;
        }

Überwachen und Reagieren auf ein Anrufstatusänderungsereignis

Das Ereignis StateChanged für das Objekt CommunicationCall wird ausgelöst, wenn ein gerade ausgeführter Vorgang Transaktionen von einem Zustand in einen anderen aufruft. Der Anwendung wird die Möglichkeit geboten, die Zustandsänderungen auf der Benutzeroberfläche widerzuspiegeln oder Geschäftslogiken einzufügen.

        private async void OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            var call = sender as CommunicationCall;

            if (call != null)
            {
                var state = call.State;

                // Update the UI

                switch (state)
                {
                    case CallState.Connected:
                        {
                            await call.StartAudioAsync(micStream);

                            break;
                        }
                    case CallState.Disconnected:
                        {
                            call.StateChanged -= OnStateChangedAsync;

                            call.Dispose();

                            break;
                        }
                    default: break;
                }
            }
        }

Ruftaste aktivieren

Sobald Callee ID nicht null oder leer ist, können Sie einen Aufruf starten.

Der Aufrufstatus muss mithilfe der OnStateChangedAsync-Aktion geändert werden.


    private async void CallButton_Click(object sender, RoutedEventArgs e)
    {
        var callString = CalleeTextBox.Text.Trim();

        if (!string.IsNullOrEmpty(callString))
        {
            call = await StartCallAsync(callString);

            call.StateChanged += OnStateChangedAsync;
        }
    
        
    }

Ausführen des Codes

Sie können den Build in Visual Studio erstellen und den Code ausführen. Für Lösungsplattformen unterstützen wir ARM64, x64 und x86.

Manuelle Schritte zum Einrichten des Anrufs:

  1. Veröffentlichen Sie die App mithilfe von Visual Studio.
  2. Geben Sie die ID des Anrufwarteschlangenobjekts ein (mit Präfix), und wählen Sie die Schaltfläche „Anruf starten“ aus. Die Anwendung wird den ausgehenden Aufruf an die Anrufwarteschlange mit der angegebenen Objekt-ID starten.
  3. Der Anruf ist mit der Anrufwarteschlange verbunden.
  4. Der Communication Services-Benutzer wird basierend auf der Konfiguration durch die Anrufwarteschlange weitergeleitet.

Bereinigen von Ressourcen

Wenn Sie ein Communication Services-Abonnement bereinigen und entfernen möchten, können Sie die Ressource oder die Ressourcengruppe löschen. Wenn Sie die Ressourcengruppe löschen, werden auch alle anderen Ressourcen gelöscht, die ihr zugeordnet sind. Weitere Informationen zum Bereinigen von Ressourcen finden Sie hier.

Nächste Schritte

Weitere Informationen finden Sie in den folgenden Artikeln: