Delen via


Quickstart: Uw bel-app toevoegen aan een Teams Auto Attendant

In deze quickstart leert u hoe u een gesprek start van een Azure Communication Services-gebruiker naar Teams Auto Attendant. U gaat dit bereiken met de volgende stappen:

  1. Schakel federatie van Azure Communication Services-resource in met Teams-tenant.
  2. Selecteer of maak Teams Auto Attendant via het Teams-beheercentrum.
  3. Ontvang een e-mailadres van Auto Attendant via het Teams-beheercentrum.
  4. Object-id van de Auto Attendant ophalen via Graph API.
  5. Start een aanroep met azure Communication Services Calling SDK.

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Interoperabiliteit inschakelen in uw Teams-tenant

Microsoft Entra-gebruiker met de beheerdersrol Teams kan PowerShell-cmdlet uitvoeren met de MicrosoftTeams-module om de Communication Services-resource in de tenant in te schakelen.

1. De Microsoft Teams-module voorbereiden

Open eerst PowerShell en valideer het bestaan van de Teams-module met de volgende opdracht:

Get-module *teams* 

Als u de module niet ziet, installeert u deze MicrosoftTeams eerst. Als u de module wilt installeren, moet u PowerShell uitvoeren als beheerder. Voer vervolgens de volgende opdracht uit:

	Install-Module -Name MicrosoftTeams

U wordt geïnformeerd over de modules die worden geïnstalleerd, die u kunt bevestigen met een Y of A meer antwoorden. Als de module is geïnstalleerd maar verouderd is, kunt u de volgende opdracht uitvoeren om de module bij te werken:

	Update-Module MicrosoftTeams

2. Verbinding maken met microsoft Teams-module

Wanneer de module is geïnstalleerd en gereed is, kunt u verbinding maken met de MicrosftTeams-module met de volgende opdracht. U wordt gevraagd om u aan te melden met een interactief venster. Het gebruikersaccount dat u gaat gebruiken, moet beschikken over beheerdersmachtigingen voor Teams. Anders krijgt u mogelijk een access denied antwoord in de volgende stappen.

Connect-MicrosoftTeams

3. Tenantconfiguratie inschakelen

Interoperabiliteit met Communication Services-resources wordt beheerd via tenantconfiguratie en toegewezen beleid. Teams-tenant heeft één tenantconfiguratie en Teams-gebruikers hebben globaal beleid of aangepast beleid toegewezen. Zie Beleid toewijzen in Teams voor meer informatie.

Nadat u zich hebt aangemeld, kunt u de cmdlet Set-CsTeamsAcsFederationConfiguration uitvoeren om de Communication Services-resource in uw tenant in te schakelen. Vervang de tekst IMMUTABLE_RESOURCE_ID door een onveranderbare resource-id in uw communicatieresource. Hier vindt u meer informatie over hoe u deze informatie kunt verkrijgen.

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

4. Tenantbeleid inschakelen

Elke Teams-gebruiker heeft een External Access Policy toegewezen die bepaalt of Communication Services-gebruikers deze Teams-gebruiker kunnen aanroepen. Gebruik cmdlet Set-CsExternalAccessPolicy om ervoor te zorgen dat het beleid dat is toegewezen aan de Teams-gebruiker is ingesteld op EnableAcsFederationAccess$true

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Teams Auto Attendant maken of selecteren

Teams Auto Attendant is een systeem dat een geautomatiseerd systeem voor het verwerken van oproepen biedt voor binnenkomende oproepen. Het fungeert als een virtuele receptioniste, waardoor bellers automatisch worden doorgestuurd naar de juiste persoon of afdeling zonder dat een menselijke operator nodig is. U kunt bestaande auto attendant selecteren of maken via het Teams-beheercentrum.

Meer informatie over het maken van Auto Attendant met behulp van het Teams-beheercentrum vindt u hier.

Object-id voor Auto Attendant zoeken

Nadat Auto Attendant is gemaakt, moeten we gecorreleerde object-id vinden om deze later te kunnen gebruiken voor oproepen. Object-id is verbonden met het resourceaccount dat is gekoppeld aan Auto Attendant: open het tabblad Resourceaccounts in Teams-beheerder en zoek het e-mailaccount. Schermopname van resourceaccounts in de Beheerportal van Teams. Alle vereiste informatie voor het resourceaccount vindt u in Microsoft Graph Explorer met behulp van deze e-mail in de zoekopdracht.

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

In de resultaten kunnen we het veld Id vinden

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

Vereisten

Instellen

Een nieuwe Node.js-toepassing maken

Open uw terminal of opdrachtvenster om een nieuwe map voor uw app te maken en navigeer naar de map.

mkdir calling-quickstart && cd calling-quickstart

Het pakket installeren

Gebruik de npm install opdracht om de Sdk voor aanroepen van Azure Communication Services voor JavaScript te installeren.

Belangrijk

In deze quickstart wordt de SDK-versie nextvoor aanroepen van Azure Communication Services gebruikt.

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

Stel het app-framework in

In deze snelstart wordt webpack gebruikt om de toepassingsassets te bundelen. Voer de volgende opdracht uit om de webpacknpm-pakketten webpack-cli en webpack-dev-server npm-pakketten te installeren en weer te geven als ontwikkelingsafhankelijkheden in uw package.json:

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

Maak een index.html bestand in de hoofdmap van uw project. We gebruiken dit bestand om een eenvoudige indeling te configureren waarmee de gebruiker een videogesprek van 1:1 kan plaatsen.

Hier volgt de code:

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

Web-SDK-objectmodel aanroepen van Azure Communication Services

De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Azure Communication Services Calling SDK:

Name Beschrijving
CallClient Het belangrijkste toegangspunt voor de Aanroepende SDK.
CallAgent Wordt gebruikt om gesprekken te starten en te beheren.
DeviceManager Wordt gebruikt voor het beheren van mediaapparaten.
Call Wordt gebruikt voor het vertegenwoordigen van een gesprek.
LocalVideoStream Wordt gebruikt voor het maken van een lokale videostream voor een cameraapparaat op het lokale systeem.
RemoteParticipant Wordt gebruikt voor het vertegenwoordigen van een externe deelnemer in het gesprek.
RemoteVideoStream Wordt gebruikt voor het vertegenwoordigen van een externe videostream van een externe deelnemer.

Maak een bestand in de hoofdmap van uw project client.js dat de toepassingslogica voor deze quickstart bevat. Voeg de volgende code toe aan client.js:

// 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 applicationObjectId = 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 an Teams Auto attendant
 * 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: applicationObjectId.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.on('isLocalVideoStartedChanged', () => {
            console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
        });
        console.log(`isLocalVideoStarted: ${call.isLocalVideoStarted}`);
        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();
            });
        });
        
        // 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();
});

De lokale servercode van het webpack toevoegen

Maak een bestand in de hoofdmap van uw project met de naam webpack.config.js om de lokale serverlogica voor deze quickstart te bevatten. Voeg de volgende code toe aan webpack.config.js:

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'
            ]
        }),
    ]
};

De code uitvoeren

Gebruik de webpack-dev-server om uw app te bouwen en uit te voeren. Voer de volgende opdracht uit om de toepassingshost te bundelen op een lokale webserver:

npx webpack serve --config webpack.config.js

Handmatige stappen voor het instellen van het gesprek:

  1. Open uw browser en navigeer naar http://localhost:8080/.
  2. Voer een geldig toegangstoken voor gebruikers in. Raadpleeg de documentatie voor het token voor gebruikerstoegang als u nog geen toegangstokens hebt die u kunt gebruiken.
  3. Klik op de knoppen Oproepagent initialiseren.
  4. Voer de Object-id van De Auto Attendant in en selecteer de knop Gesprek starten. De toepassing start de uitgaande oproep naar de Auto Attendant met de opgegeven object-id.
  5. Oproep is verbonden met de Auto Attendant.
  6. Communication Services-gebruiker wordt gerouteerd via Auto Attendant op basis van de configuratie.

Belangrijk

Deze functie van Azure Communication Services is momenteel beschikbaar als preview-versie.

Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Sommige functies worden mogelijk niet ondersteund of hebben mogelijk beperkte mogelijkheden.

Raadpleeg aanvullende gebruiksvoorwaarden voor Microsoft Azure Previews voor meer informatie.

In deze quickstart leert u hoe u een gesprek start van een Azure Communication Services-gebruiker naar Teams Auto Attendant. U gaat dit bereiken met de volgende stappen:

  1. Schakel federatie van Azure Communication Services-resource in met Teams-tenant.
  2. Selecteer of maak Teams Auto Attendant via het Teams-beheercentrum.
  3. Ontvang een e-mailadres van Auto Attendant via het Teams-beheercentrum.
  4. Object-id van de Auto Attendant ophalen via Graph API.
  5. Start een aanroep met azure Communication Services Calling SDK.

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Interoperabiliteit inschakelen in uw Teams-tenant

Microsoft Entra-gebruiker met de beheerdersrol Teams kan PowerShell-cmdlet uitvoeren met de MicrosoftTeams-module om de Communication Services-resource in de tenant in te schakelen.

1. De Microsoft Teams-module voorbereiden

Open eerst PowerShell en valideer het bestaan van de Teams-module met de volgende opdracht:

Get-module *teams* 

Als u de module niet ziet, installeert u deze MicrosoftTeams eerst. Als u de module wilt installeren, moet u PowerShell uitvoeren als beheerder. Voer vervolgens de volgende opdracht uit:

	Install-Module -Name MicrosoftTeams

U wordt geïnformeerd over de modules die worden geïnstalleerd, die u kunt bevestigen met een Y of A meer antwoorden. Als de module is geïnstalleerd maar verouderd is, kunt u de volgende opdracht uitvoeren om de module bij te werken:

	Update-Module MicrosoftTeams

2. Verbinding maken met microsoft Teams-module

Wanneer de module is geïnstalleerd en gereed is, kunt u verbinding maken met de MicrosftTeams-module met de volgende opdracht. U wordt gevraagd om u aan te melden met een interactief venster. Het gebruikersaccount dat u gaat gebruiken, moet beschikken over beheerdersmachtigingen voor Teams. Anders krijgt u mogelijk een access denied antwoord in de volgende stappen.

Connect-MicrosoftTeams

3. Tenantconfiguratie inschakelen

Interoperabiliteit met Communication Services-resources wordt beheerd via tenantconfiguratie en toegewezen beleid. Teams-tenant heeft één tenantconfiguratie en Teams-gebruikers hebben globaal beleid of aangepast beleid toegewezen. Zie Beleid toewijzen in Teams voor meer informatie.

Nadat u zich hebt aangemeld, kunt u de cmdlet Set-CsTeamsAcsFederationConfiguration uitvoeren om de Communication Services-resource in uw tenant in te schakelen. Vervang de tekst IMMUTABLE_RESOURCE_ID door een onveranderbare resource-id in uw communicatieresource. Hier vindt u meer informatie over hoe u deze informatie kunt verkrijgen.

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

4. Tenantbeleid inschakelen

Elke Teams-gebruiker heeft een External Access Policy toegewezen die bepaalt of Communication Services-gebruikers deze Teams-gebruiker kunnen aanroepen. Gebruik cmdlet Set-CsExternalAccessPolicy om ervoor te zorgen dat het beleid dat is toegewezen aan de Teams-gebruiker is ingesteld op EnableAcsFederationAccess$true

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Teams Auto Attendant maken of selecteren

Teams Auto Attendant is een systeem dat een geautomatiseerd systeem voor het verwerken van oproepen biedt voor binnenkomende oproepen. Het fungeert als een virtuele receptioniste, waardoor bellers automatisch worden doorgestuurd naar de juiste persoon of afdeling zonder dat een menselijke operator nodig is. U kunt bestaande auto attendant selecteren of maken via het Teams-beheercentrum.

Meer informatie over het maken van Auto Attendant met behulp van het Teams-beheercentrum vindt u hier.

Object-id voor Auto Attendant zoeken

Nadat Auto Attendant is gemaakt, moeten we gecorreleerde object-id vinden om deze later te kunnen gebruiken voor oproepen. Object-id is verbonden met het resourceaccount dat is gekoppeld aan Auto Attendant: open het tabblad Resourceaccounts in Teams-beheerder en zoek het e-mailaccount. Schermopname van resourceaccounts in de Beheerportal van Teams. Alle vereiste informatie voor het resourceaccount vindt u in Microsoft Graph Explorer met behulp van deze e-mail in de zoekopdracht.

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

In de resultaten kunnen we het veld Id vinden

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

Als u de aanroepende app wilt gebruiken, moet u een voorvoegsel toevoegen aan deze id. Op dit moment worden de volgende ondersteund:

  • Auto Attendant voor openbare cloud: 28:orgid:<id>
  • Government cloud Auto Attendant: 28:gcch:<id>

Vereisten

Instellen

Een Android-app maken met een lege activiteit

Selecteer Een nieuw Android Studio-project starten in Android Studio.

Schermopname waarin de knop Een nieuw Android Studio-project starten is geselecteerd in Android Studio.

Selecteer de projectsjabloon Lege weergaven onder Telefoon en Tablet.

Schermopname waarin de optie Lege activiteit is geselecteerd op het scherm Projectsjabloon.

Selecteer minimum-SDK van 'API 26: Android 8.0 (Oreo)' of hoger.

Schermopname waarin de optie Lege activiteit is geselecteerd op het scherm Projectsjabloon 2.

Het pakket installeren

Zoek uw project settings.gradle.kts en zorg ervoor dat u de mavenCentral() lijst met opslagplaatsen onder pluginManagement en dependencyResolutionManagement

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

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

Voeg vervolgens in de build.gradle op moduleniveau de volgende regels toe aan de secties Afhankelijkheden en Android

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

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

Machtigingen toevoegen aan het toepassingsmanifest

Als u machtigingen wilt aanvragen die nodig zijn om een aanroep te doen, moeten ze worden gedeclareerd in het toepassingsmanifest (app/src/main/AndroidManifest.xml). Vervang de inhoud van het bestand door de volgende 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>
    

De indeling van de app instellen

Er moeten twee items worden toegevoegd: een tekstvak voor de id van de persoon die wordt gebeld en een knop om te bellen. Deze invoer kan worden toegevoegd via de ontwerpfunctie of door de xml-indeling te bewerken. Maak een knop met een id van call_button en een tekstinvoer van callee_id. Navigeer naar (app/src/main/res/layout/activity_main.xml) en vervang de inhoud van het bestand door de volgende 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>

De hoofdopbouw en -bindingen van de activiteit maken

Nu de indeling is gemaakt, kunnen de bindingen en de basisopzet van de activiteit worden toegevoegd. De activiteit verwerkt het aanvragen van runtimemachtigingen, het maken van de aanroepagent en het plaatsen van de aanroep wanneer de knop wordt ingedrukt. De onCreate methode wordt overschreven om de bindingen voor de oproepknop aan te roepen getAllPermissions en createAgent toe te voegen. Deze gebeurtenis vindt slechts één keer plaats wanneer de activiteit wordt gemaakt. Zie de handleiding Inzicht in de levenscyclus van activiteiten voor meer informatieonCreate.

Ga naar MainActivity.java en vervang de inhoud door de volgende 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));
    }
}

Machtigingen tijdens runtime aanvragen

Voor Android 6.0 en hoger (API-niveau 23) en targetSdkVersion 23 of hoger worden machtigingen toegekend tijdens de runtime in plaats van tijdens de installatie van de app. Om deze te ondersteunen, getAllPermissions kan worden geïmplementeerd om te bellen ActivityCompat.checkSelfPermission en ActivityCompat.requestPermissions voor elke vereiste machtiging.

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

Notitie

Houd tijdens het ontwerpen van uw app rekening met het moment waarop deze machtigingen moeten worden aangevraagd. Machtigingen moeten worden aangevraagd wanneer u ze nodig hebt, niet van tevoren. Zie de Handleiding voor Android-machtigingen voor meer informatie.

Objectmodel

De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Azure Communication Services Calling SDK:

Name Beschrijving
CallClient Dit CallClient is het belangrijkste toegangspunt voor de Calling SDK.
CallAgent Het CallAgent wordt gebruikt om oproepen te starten en te beheren.
CommunicationTokenCredential De CommunicationTokenCredential wordt gebruikt als de tokenreferentie om de CallAgent.
CommunicationIdentifier De CommunicationIdentifier wordt gebruikt als een ander type deelnemer dat deel kan uitmaken van een gesprek.

Een agent maken op basis van het toegangstoken voor gebruikers

Met een gebruikerstoken kan een geverifieerde oproepagent worden geïnstantieerd. Over het algemeen wordt dit token gegenereerd op basis van een service met verificatie die specifiek is voor de toepassing. Raadpleeg de handleiding gebruikerstoegangstokens voor meer informatie over tokens voor gebruikerstoegang.

Voor de quickstart vervangt u <User_Access_Token> door een gebruikerstoegangstoken dat voor uw Azure Communication Service-resource is gegenereerd.


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

De code uitvoeren

De app kan nu worden gestart met behulp van de knop App uitvoeren op de werkbalk.

Handmatige stappen voor het instellen van het gesprek:

  1. Start de app met Android Studio.
  2. Voer de Auto Attendant-object-id (met voorvoegsel) in en selecteer de knop Gesprek starten. De toepassing start de uitgaande oproep naar de Auto Attendant met de opgegeven object-id.
  3. Oproep is verbonden met de Auto Attendant.
  4. Communication Services-gebruiker wordt gerouteerd via Auto Attendant op basis van de configuratie.

Belangrijk

Deze functie van Azure Communication Services is momenteel beschikbaar als preview-versie.

Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Sommige functies worden mogelijk niet ondersteund of hebben mogelijk beperkte mogelijkheden.

Raadpleeg aanvullende gebruiksvoorwaarden voor Microsoft Azure Previews voor meer informatie.

In deze quickstart leert u hoe u een gesprek start van een Azure Communication Services-gebruiker naar Teams Auto Attendant. U gaat dit bereiken met de volgende stappen:

  1. Schakel federatie van Azure Communication Services-resource in met Teams-tenant.
  2. Selecteer of maak Teams Auto Attendant via het Teams-beheercentrum.
  3. Ontvang een e-mailadres van Auto Attendant via het Teams-beheercentrum.
  4. Object-id van de Auto Attendant ophalen via Graph API.
  5. Start een aanroep met azure Communication Services Calling SDK.

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Interoperabiliteit inschakelen in uw Teams-tenant

Microsoft Entra-gebruiker met de beheerdersrol Teams kan PowerShell-cmdlet uitvoeren met de MicrosoftTeams-module om de Communication Services-resource in de tenant in te schakelen.

1. De Microsoft Teams-module voorbereiden

Open eerst PowerShell en valideer het bestaan van de Teams-module met de volgende opdracht:

Get-module *teams* 

Als u de module niet ziet, installeert u deze MicrosoftTeams eerst. Als u de module wilt installeren, moet u PowerShell uitvoeren als beheerder. Voer vervolgens de volgende opdracht uit:

	Install-Module -Name MicrosoftTeams

U wordt geïnformeerd over de modules die worden geïnstalleerd, die u kunt bevestigen met een Y of A meer antwoorden. Als de module is geïnstalleerd maar verouderd is, kunt u de volgende opdracht uitvoeren om de module bij te werken:

	Update-Module MicrosoftTeams

2. Verbinding maken met microsoft Teams-module

Wanneer de module is geïnstalleerd en gereed is, kunt u verbinding maken met de MicrosftTeams-module met de volgende opdracht. U wordt gevraagd om u aan te melden met een interactief venster. Het gebruikersaccount dat u gaat gebruiken, moet beschikken over beheerdersmachtigingen voor Teams. Anders krijgt u mogelijk een access denied antwoord in de volgende stappen.

Connect-MicrosoftTeams

3. Tenantconfiguratie inschakelen

Interoperabiliteit met Communication Services-resources wordt beheerd via tenantconfiguratie en toegewezen beleid. Teams-tenant heeft één tenantconfiguratie en Teams-gebruikers hebben globaal beleid of aangepast beleid toegewezen. Zie Beleid toewijzen in Teams voor meer informatie.

Nadat u zich hebt aangemeld, kunt u de cmdlet Set-CsTeamsAcsFederationConfiguration uitvoeren om de Communication Services-resource in uw tenant in te schakelen. Vervang de tekst IMMUTABLE_RESOURCE_ID door een onveranderbare resource-id in uw communicatieresource. Hier vindt u meer informatie over hoe u deze informatie kunt verkrijgen.

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

4. Tenantbeleid inschakelen

Elke Teams-gebruiker heeft een External Access Policy toegewezen die bepaalt of Communication Services-gebruikers deze Teams-gebruiker kunnen aanroepen. Gebruik cmdlet Set-CsExternalAccessPolicy om ervoor te zorgen dat het beleid dat is toegewezen aan de Teams-gebruiker is ingesteld op EnableAcsFederationAccess$true

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Teams Auto Attendant maken of selecteren

Teams Auto Attendant is een systeem dat een geautomatiseerd systeem voor het verwerken van oproepen biedt voor binnenkomende oproepen. Het fungeert als een virtuele receptioniste, waardoor bellers automatisch worden doorgestuurd naar de juiste persoon of afdeling zonder dat een menselijke operator nodig is. U kunt bestaande auto attendant selecteren of maken via het Teams-beheercentrum.

Meer informatie over het maken van Auto Attendant met behulp van het Teams-beheercentrum vindt u hier.

Object-id voor Auto Attendant zoeken

Nadat Auto Attendant is gemaakt, moeten we gecorreleerde object-id vinden om deze later te kunnen gebruiken voor oproepen. Object-id is verbonden met het resourceaccount dat is gekoppeld aan Auto Attendant: open het tabblad Resourceaccounts in Teams-beheerder en zoek het e-mailaccount. Schermopname van resourceaccounts in de Beheerportal van Teams. Alle vereiste informatie voor het resourceaccount vindt u in Microsoft Graph Explorer met behulp van deze e-mail in de zoekopdracht.

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

In de resultaten kunnen we het veld Id vinden

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

Als u de aanroepende app wilt gebruiken, moet u een voorvoegsel toevoegen aan deze id. Op dit moment worden de volgende ondersteund:

  • Auto Attendant voor openbare cloud: 28:orgid:<id>
  • Government cloud Auto Attendant: 28:gcch:<id>

Vereisten

Instellen

Het Xcode-project maken

Maak in Xcode een nieuw iOS-project en selecteer de app-sjabloon. In deze zelfstudie wordt gebruikgemaakt van het SwiftUI-framework. U moet dus de taal instellen op Swift en de gebruikersinterface op SwiftUI. Tijdens deze quickstart maakt u geen tests. U kunt Tests opnemen uitschakelen.

Schermafbeelding met het venster Nieuw project in Xcode.

Installeer het pakket en de afhankelijkheden met CocoaPods

  1. Als u een Podfile voor uw toepassing wilt maken, opent u de terminal en navigeert u naar de projectmap en voert u het volgende uit:

    pod init

  2. Voeg de volgende code toe aan het Podfile en sla deze op (zorg ervoor dat 'doel' overeenkomt met de naam van uw project):

    platform :ios, '13.0'
    use_frameworks!
    
    target 'AzureCommunicationCallingSample' do
      pod 'AzureCommunicationCalling', '~> 2.14.0-beta.1'
    end
    
  3. Voer pod install uit.

  4. Open de .xcworkspace met Xcode.

Toegang tot de microfoon aanvragen

Als u toegang wilt krijgen tot de microfoon van het apparaat, moet u de eigenschappenlijst van de app bijwerken met een NSMicrophoneUsageDescription. U stelt de gekoppelde waarde in op een string waarde die is opgenomen in het dialoogvenster dat het systeem gebruikt om toegang van de gebruiker aan te vragen.

Klik met de rechtermuisknop op de Info.plist-vermelding van de projectstructuur en selecteer Open As>Source Code. Voeg de volgende regels toe in de bovenste sectie <dict> en sla het bestand op.

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

Stel het app-framework in

Open het bestand ContentView.swift van het project en voeg boven aan het bestand een import-declaratie toe om de AzureCommunicationCalling libraryte importeren. Daarnaast hebben AVFoundationwe deze code nodig voor de aanvraag voor audiomachtigingen in de code.

import AzureCommunicationCalling
import AVFoundation

Vervang de implementatie van de ContentView-struct door enkele eenvoudige UI-besturingselementen waarmee een gebruiker een oproep kan initiëren en beëindigen. In deze quickstart voegen we bedrijfslogica toe aan deze besturingselementen.

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

Objectmodel

De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Azure Communication Services Calling SDK:

Name Beschrijving
CallClient Dit CallClient is het belangrijkste toegangspunt voor de Calling SDK.
CallAgent Het CallAgent wordt gebruikt om oproepen te starten en te beheren.
CommunicationTokenCredential De CommunicationTokenCredential wordt gebruikt als de tokenreferentie om de CallAgent.
CommunicationUserIdentifier Het CommunicationUserIdentifier wordt gebruikt om de identiteit van de gebruiker weer te geven. Dit kan een van de volgende opties zijn: CommunicationUserIdentifierofPhoneNumberIdentifierCallingApplication.

De client verifiëren

Initialiseer een CallAgent exemplaar met een Token voor gebruikerstoegang, waarmee we oproepen kunnen plaatsen en ontvangen.

In de volgende code moet u vervangen door <USER ACCESS TOKEN> een geldig toegangstoken voor gebruikers voor uw resource. Raadpleeg de documentatie inzake Token voor gebruikerstoegang als u nog geen token hebt.

Voeg de volgende code toe aan de onAppear-call back in ContentView.swift:

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

Een oproep starten

De startCall methode wordt ingesteld als de actie die wordt uitgevoerd wanneer op de knop Gesprek starten wordt getikt. Werk de implementatie bij om een oproep te starten met de ASACallAgent:

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

U kunt de eigenschappen StartCallOptions ook gebruiken om de initiële opties voor het gesprek in te stellen (dat wil zeggen, hiermee kunt u het gesprek starten met de microfoon gedempt).

Een gesprek beëindigen

Implementeer de endCall-methode om de huidige oproep te beëindigen wanneer op de knop voor Oproep beëindigen wordt getikt.

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

De code uitvoeren

U kunt uw app bouwen en uitvoeren op iOS-simulator door ProductUitvoering> te selecteren of door de sneltoets (⌘-R) te gebruiken.

Notitie

De eerste keer dat u een oproep doet, wordt u gevraagd om toegang tot de microfoon. In een productietoepassing moet u de AVAudioSessionAPI gebruiken om de machtigingsstatus te controleren en het gedrag van uw toepassing bij te werken wanneer geen toestemming wordt verleend.

Handmatige stappen voor het instellen van het gesprek:

  1. De app starten met Xcode
  2. Voer de Auto Attendant-object-id (met voorvoegsel) in en selecteer de knop Gesprek starten. De toepassing start de uitgaande oproep naar de Auto Attendant met de opgegeven object-id.
  3. Oproep is verbonden met de Auto Attendant.
  4. Communication Services-gebruiker wordt gerouteerd via Auto Attendant op basis van de configuratie.

Belangrijk

Deze functie van Azure Communication Services is momenteel beschikbaar als preview-versie.

Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Sommige functies worden mogelijk niet ondersteund of hebben mogelijk beperkte mogelijkheden.

Raadpleeg aanvullende gebruiksvoorwaarden voor Microsoft Azure Previews voor meer informatie.

In deze quickstart leert u hoe u een gesprek start van een Azure Communication Services-gebruiker naar Teams Auto Attendant. U gaat dit bereiken met de volgende stappen:

  1. Schakel federatie van Azure Communication Services-resource in met Teams-tenant.
  2. Selecteer of maak Teams Auto Attendant via het Teams-beheercentrum.
  3. Ontvang een e-mailadres van Auto Attendant via het Teams-beheercentrum.
  4. Object-id van de Auto Attendant ophalen via Graph API.
  5. Start een aanroep met azure Communication Services Calling SDK.

Als u verder wilt gaan naar het einde, kunt u deze quickstart downloaden als voorbeeld op GitHub.

Interoperabiliteit inschakelen in uw Teams-tenant

Microsoft Entra-gebruiker met de beheerdersrol Teams kan PowerShell-cmdlet uitvoeren met de MicrosoftTeams-module om de Communication Services-resource in de tenant in te schakelen.

1. De Microsoft Teams-module voorbereiden

Open eerst PowerShell en valideer het bestaan van de Teams-module met de volgende opdracht:

Get-module *teams* 

Als u de module niet ziet, installeert u deze MicrosoftTeams eerst. Als u de module wilt installeren, moet u PowerShell uitvoeren als beheerder. Voer vervolgens de volgende opdracht uit:

	Install-Module -Name MicrosoftTeams

U wordt geïnformeerd over de modules die worden geïnstalleerd, die u kunt bevestigen met een Y of A meer antwoorden. Als de module is geïnstalleerd maar verouderd is, kunt u de volgende opdracht uitvoeren om de module bij te werken:

	Update-Module MicrosoftTeams

2. Verbinding maken met microsoft Teams-module

Wanneer de module is geïnstalleerd en gereed is, kunt u verbinding maken met de MicrosftTeams-module met de volgende opdracht. U wordt gevraagd om u aan te melden met een interactief venster. Het gebruikersaccount dat u gaat gebruiken, moet beschikken over beheerdersmachtigingen voor Teams. Anders krijgt u mogelijk een access denied antwoord in de volgende stappen.

Connect-MicrosoftTeams

3. Tenantconfiguratie inschakelen

Interoperabiliteit met Communication Services-resources wordt beheerd via tenantconfiguratie en toegewezen beleid. Teams-tenant heeft één tenantconfiguratie en Teams-gebruikers hebben globaal beleid of aangepast beleid toegewezen. Zie Beleid toewijzen in Teams voor meer informatie.

Nadat u zich hebt aangemeld, kunt u de cmdlet Set-CsTeamsAcsFederationConfiguration uitvoeren om de Communication Services-resource in uw tenant in te schakelen. Vervang de tekst IMMUTABLE_RESOURCE_ID door een onveranderbare resource-id in uw communicatieresource. Hier vindt u meer informatie over hoe u deze informatie kunt verkrijgen.

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

4. Tenantbeleid inschakelen

Elke Teams-gebruiker heeft een External Access Policy toegewezen die bepaalt of Communication Services-gebruikers deze Teams-gebruiker kunnen aanroepen. Gebruik cmdlet Set-CsExternalAccessPolicy om ervoor te zorgen dat het beleid dat is toegewezen aan de Teams-gebruiker is ingesteld op EnableAcsFederationAccess$true

Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true

Teams Auto Attendant maken of selecteren

Teams Auto Attendant is een systeem dat een geautomatiseerd systeem voor het verwerken van oproepen biedt voor binnenkomende oproepen. Het fungeert als een virtuele receptioniste, waardoor bellers automatisch worden doorgestuurd naar de juiste persoon of afdeling zonder dat een menselijke operator nodig is. U kunt bestaande auto attendant selecteren of maken via het Teams-beheercentrum.

Meer informatie over het maken van Auto Attendant met behulp van het Teams-beheercentrum vindt u hier.

Object-id voor Auto Attendant zoeken

Nadat Auto Attendant is gemaakt, moeten we gecorreleerde object-id vinden om deze later te kunnen gebruiken voor oproepen. Object-id is verbonden met het resourceaccount dat is gekoppeld aan Auto Attendant: open het tabblad Resourceaccounts in Teams-beheerder en zoek het e-mailaccount. Schermopname van resourceaccounts in de Beheerportal van Teams. Alle vereiste informatie voor het resourceaccount vindt u in Microsoft Graph Explorer met behulp van deze e-mail in de zoekopdracht.

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

In de resultaten kunnen we het veld Id vinden

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

Als u de aanroepende app wilt gebruiken, moet u een voorvoegsel toevoegen aan deze id. Op dit moment worden de volgende ondersteund:

  • Auto Attendant voor openbare cloud: 28:orgid:<id>
  • Government cloud Auto Attendant: 28:gcch:<id>

Vereisten

Voor het voltooien van deze zelfstudie moet aan de volgende vereisten worden voldaan:

Instellen

Het project maken

Maak in Visual Studio een nieuw project met de sjabloon Blank App (Universal Windows) om een UWP-app (single page Universeel Windows-platform) in te stellen.

Schermopname van het venster Nieuw UWP-project in Visual Studio.

Het pakket installeren

Selecteer uw project met de rechtermuisknop en ga naar Manage Nuget Packages 1.4.0 of superior te installeren Azure.Communication.Calling.WindowsClient . Controleer of Include Prerelease u de versies voor openbare preview wilt zien.

Toegang aanvragen

Ga naar Package.appxmanifest en selecteer Capabilities. Controleer Internet (Client) en Internet (Client & Server) om binnenkomende en uitgaande toegang tot internet te krijgen. Controleer Microphone of u toegang hebt tot de audiofeed van de microfoon en Webcam om toegang te krijgen tot de videofeed van de camera.

Schermopname van het aanvragen van toegang tot internet en microfoon in Visual Studio.

Stel het app-framework in

We moeten een eenvoudige indeling configureren om onze logica te koppelen. Om een uitgaande oproep te kunnen plaatsen, moeten TextBox we de gebruikers-id van de aanroepende gebruiker opgeven. We hebben ook een Start/Join call knop en een Hang up knop nodig. A Mute - en selectievakjes BackgroundBlur zijn ook opgenomen in dit voorbeeld om de functies van het schakelen tussen audiostatussen en video-effecten te demonstreren.

Open het MainPage.xaml project en voeg het knooppunt toe aan het Grid Pagevolgende:

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

Open de MainPage.xaml.cs inhoud en vervang deze door de volgende implementatie:

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

Objectmodel

De volgende tabel bevat de klassen en interfaces die enkele van de belangrijkste functies van de Aanroepende SDK van Azure Communication Services verwerken:

Name Beschrijving
CallClient Dit CallClient is het belangrijkste toegangspunt voor de Calling SDK.
CallAgent Het CallAgent wordt gebruikt om oproepen te starten en te beheren.
CommunicationCall Deze CommunicationCall wordt gebruikt om een doorlopend gesprek te beheren.
CallTokenCredential De CallTokenCredential wordt gebruikt als de tokenreferentie om de CallAgent.
CallIdentifier Het CallIdentifier wordt gebruikt om de identiteit van de gebruiker weer te geven, die een van de volgende opties kan zijn: UserCallIdentifier, PhoneNumberCallIdentifier enzovoort.

De client verifiëren

Initialiseer een CallAgent exemplaar met een token voor gebruikerstoegang waarmee we oproepen kunnen plaatsen en ontvangen, en eventueel een DeviceManager-exemplaar verkrijgen om een query uit te voeren op clientapparaatconfiguraties.

Vervang in de code door <AUTHENTICATION_TOKEN> een token voor gebruikerstoegang. Raadpleeg de documentatie inzake Token voor gebruikerstoegang als u nog geen token hebt.

Voeg een functie toe InitCallAgentAndDeviceManagerAsync , waarmee de SDK wordt opgestart. Deze helper kan worden aangepast om te voldoen aan de vereisten van uw toepassing.

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

Het gesprek starten

Zodra een StartCallOptions object is verkregen, CallAgent kan worden gebruikt om de Aanroep van Azure Communication Services te initiëren:

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

Een gesprek beëindigen

Beëindig het huidige gesprek wanneer op de Hang up knop wordt geklikt. Voeg de implementatie toe aan de HangupButton_Click om een gesprek te beëindigen en stop de preview- en 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 });
            }
        }

Geluid dempen/dempen opheffen

Demp de uitgaande audio wanneer op de Mute knop wordt geklikt. Voeg de implementatie toe aan de MuteLocal_Click om de aanroep te dempen.

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

Een inkomende oproep accepteren

IncomingCallReceived gebeurtenissink is ingesteld in de SDK bootstrap-helper InitCallAgentAndDeviceManagerAsync.

    this.callAgent.IncomingCallReceived += OnIncomingCallAsync;

De toepassing heeft de mogelijkheid om te configureren hoe de inkomende oproep moet worden geaccepteerd, zoals soorten video- en audiostreams.

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

            var acceptCallOptions = new AcceptCallOptions() { };

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

Gebeurtenis voor het wijzigen van oproepstatus controleren en reageren

StateChanged gebeurtenis op CommunicationCall object wordt geactiveerd wanneer transacties worden aangeroepen van de ene status naar de andere. De toepassing biedt de mogelijkheden om de statuswijzigingen in de gebruikersinterface weer te geven of bedrijfslogica in te voegen.

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

Knop Bellen werken

Zodra de Callee ID waarde niet null of leeg is, kunt u een aanroep starten.

De aanroepstatus moet worden gewijzigd met behulp van de OnStateChangedAsync actie.


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

De code uitvoeren

U kunt de code bouwen en uitvoeren in Visual Studio. Voor oplossingsplatformen ondersteunen ARM64we , x64en x86.

Handmatige stappen voor het instellen van het gesprek:

  1. Start de app met Visual Studio.
  2. Voer de Auto Attendant-object-id (met voorvoegsel) in en selecteer de knop Gesprek starten. De toepassing start de uitgaande oproep naar de Auto Attendant met de opgegeven object-id.
  3. Oproep is verbonden met de Auto Attendant.
  4. Communication Services-gebruiker wordt gerouteerd via Auto Attendant op basis van de configuratie.

Resources opschonen

Als u een Communication Services-abonnement wilt opschonen en verwijderen, kunt u de resource of resourcegroep verwijderen. Als u de resourcegroep verwijdert, worden ook alle bijbehorende resources verwijderd. Meer informatie over het opschonen van resources.

Volgende stappen

Raadpleeg voor meer informatie de volgende artikelen: