Snabbstart: Ansluta din samtalsapp till en automatisk Teams-dirigering
I den här snabbstarten får du lära dig hur du startar ett samtal från Azure Communication Services-användare till Automatisk teams-dirigering. Du kommer att uppnå det med följande steg:
- Aktivera federation av Azure Communication Services-resurs med Teams-klientorganisation.
- Välj eller skapa automatisk teams-dirigering via Administrationscenter för Teams.
- Hämta e-postadressen för automatisk dirigering via Administrationscenter för Teams.
- Hämta objekt-ID för den automatiska dirigering via Graph API.
- Starta ett samtal med Azure Communication Services Calling SDK.
Om du vill gå vidare till slutet kan du ladda ned den här snabbstarten som ett exempel på GitHub.
Aktivera samverkan i din Teams-klientorganisation
Microsoft Entra-användare med Teams-administratörsroll kan köra PowerShell-cmdlet med MicrosoftTeams-modulen för att aktivera Communication Services-resursen i klientorganisationen.
1. Förbered Microsoft Teams-modulen
Öppna först PowerShell och verifiera förekomsten av Teams-modulen med följande kommando:
Get-module *teams*
Om du inte ser modulen installerar du den MicrosoftTeams
först. Om du vill installera modulen måste du köra PowerShell som administratör. Kör följande kommando:
Install-Module -Name MicrosoftTeams
Du får information om de moduler som kommer att installeras, vilket du kan bekräfta med ett Y
eller A
svar. Om modulen är installerad men inaktuell kan du köra följande kommando för att uppdatera modulen:
Update-Module MicrosoftTeams
2. Ansluta till Microsoft Teams-modulen
När modulen är installerad och klar kan du ansluta till MicrosftTeams-modulen med följande kommando. Du uppmanas att logga in med ett interaktivt fönster. Det användarkonto som du ska använda måste ha behörighet som Teams-administratör. Annars kan du få ett access denied
svar i nästa steg.
Connect-MicrosoftTeams
3. Aktivera klientkonfiguration
Samverkan med Communication Services-resurser styrs via klientkonfiguration och tilldelad princip. Teams klientorganisation har en enda klientkonfiguration och Teams-användare har tilldelat global princip eller anpassad princip. Mer information finns i Tilldela principer i Teams.
När inloggningen har slutförts kan du köra cmdleten Set-CsTeamsAcsFederationConfiguration för att aktivera Communication Services-resursen i klientorganisationen. Ersätt texten IMMUTABLE_RESOURCE_ID
med ett oföränderligt resurs-ID i kommunikationsresursen. Mer information om hur du hämtar den här informationen finns här.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktivera klientprincip
Varje Teams-användare har tilldelats en External Access Policy
som avgör om Communication Services-användare kan anropa den här Teams-användaren. Använd cmdleten Set-CsExternalAccessPolicy för att säkerställa att principen som tilldelats Teams-användaren har angetts EnableAcsFederationAccess
till $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Skapa eller välj Automatisk teams-dirigering
Automatisk dirigering i Teams är ett system som tillhandahåller ett automatiserat samtalshanteringssystem för inkommande samtal. Det fungerar som en virtuell receptionist, vilket gör det möjligt för uppringare att automatiskt dirigeras till lämplig person eller avdelning utan behov av en mänsklig operatör. Du kan välja befintlig eller skapa ny automatisk dirigering via Administrationscenter för Teams.
Läs mer om hur du skapar automatisk dirigering med Hjälp av Administrationscenter för Teams här.
Hitta objekt-ID för automatisk dirigering
När automatisk dirigering har skapats måste vi hitta korrelerat objekt-ID för att kunna använda det senare för anrop. Objekt-ID är anslutet till resurskonto som har kopplats till automatisk dirigering – öppna fliken Resurskonton i Teams-administratör och hitta e-post för kontot. All nödvändig information för resurskontot finns i Microsoft Graph Explorer med det här e-postmeddelandet i sökningen.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
I resultat kan vi hitta fältet "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Förutsättningar
- Skaffa ett Azure-konto med en aktiv prenumeration. Skapa ett konto utan kostnad.
- Node.js Versionerna Active LTS and Maintenance LTS (8.11.1 och 10.14.1)
- Skapa en aktiv Communication Services-resurs. Skapa en Communication Services-resurs.
Konfigurera
Skapa ett nytt Node.js-program
Öppna terminalen eller kommandofönstret skapa en ny katalog för din app och navigera till katalogen.
mkdir calling-quickstart && cd calling-quickstart
Installera -paketet
npm install
Använd kommandot för att installera Azure Communication Services Calling SDK för JavaScript.
Viktigt!
Den här snabbstarten använder Azure Communication Services Calling SDK-versionen next
.
npm install @azure/communication-common@next --save
npm install @azure/communication-calling@next --save
Konfigurera appramverket
Den här snabbstarten använder webpack för att paketera programtillgångarna. Kör följande kommando för att installera , webpack-cli
och webpack-dev-server
npm-paketen webpack
och lista dem som utvecklingsberoenden i :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
Skapa en index.html
fil i rotkatalogen för projektet. Vi använder den här filen för att konfigurera en grundläggande layout som gör att användaren kan ringa ett 1:1-videosamtal.
Här är koden:
<!-- 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>
Azure Communication Services Anropar web-SDK-objektmodell
Följande klasser och gränssnitt hanterar några av huvudfunktionerna i Azure Communication Services Calling SDK:
Name | beskrivning |
---|---|
CallClient |
Huvudinmatningspunkten till anropande SDK. |
CallAgent |
Används för att starta och hantera anrop. |
DeviceManager |
Används för att hantera medieenheter. |
Call |
Används för att representera ett samtal. |
LocalVideoStream |
Används för att skapa en lokal videoström för en kameraenhet i det lokala systemet. |
RemoteParticipant |
Används för att representera en fjärrdeltagare i samtalet. |
RemoteVideoStream |
Används för att representera en fjärrvideoström från en fjärrdeltagare. |
Skapa en fil i rotkatalogen för projektet som anropas client.js
för att innehålla programlogik för den här snabbstarten. Lägg till följande kod i 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();
});
Lägg till den lokala serverkoden för webpack
Skapa en fil i rotkatalogen i projektet med namnet webpack.config.js för att innehålla den lokala serverlogik som finns i den här snabbstarten. Lägg till följande kod i 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'
]
}),
]
};
Kör koden
Använd för webpack-dev-server
att skapa och köra din app. Kör följande kommando för att paketa programvärden i en lokal webbserver:
npx webpack serve --config webpack.config.js
Manuella steg för att konfigurera anropet:
- Öppna webbläsaren och navigera till http://localhost:8080/.
- Ange en giltig användaråtkomsttoken. Se dokumentationen för användaråtkomsttoken om du inte redan har åtkomsttoken att använda.
- Klicka på knapparna "Initiera samtalsagent".
- Ange objekt-ID för automatisk dirigering och välj knappen "Starta samtal". Programmet startar det utgående anropet till den automatiska dirigering med angivet objekt-ID.
- Samtalet är anslutet till den automatiska dirigering.
- Communication Services-användaren dirigeras via automatisk dirigering baserat på dess konfiguration.
Viktigt!
Den här funktionen i Azure Communication Services är för närvarande i förhandsversion.
Förhandsversions-API:er och SDK:er tillhandahålls utan ett serviceavtal. Vi rekommenderar att du inte använder dem för produktionsarbetsbelastningar. Vissa funktioner kanske inte stöds, eller så kan de ha begränsade funktioner.
Mer information finns i Kompletterande användningsvillkor för Förhandsversioner av Microsoft Azure.
I den här snabbstarten får du lära dig hur du startar ett samtal från Azure Communication Services-användare till Automatisk teams-dirigering. Du kommer att uppnå det med följande steg:
- Aktivera federation av Azure Communication Services-resurs med Teams-klientorganisation.
- Välj eller skapa automatisk teams-dirigering via Administrationscenter för Teams.
- Hämta e-postadressen för automatisk dirigering via Administrationscenter för Teams.
- Hämta objekt-ID för den automatiska dirigering via Graph API.
- Starta ett samtal med Azure Communication Services Calling SDK.
Om du vill gå vidare till slutet kan du ladda ned den här snabbstarten som ett exempel på GitHub.
Aktivera samverkan i din Teams-klientorganisation
Microsoft Entra-användare med Teams-administratörsroll kan köra PowerShell-cmdlet med MicrosoftTeams-modulen för att aktivera Communication Services-resursen i klientorganisationen.
1. Förbered Microsoft Teams-modulen
Öppna först PowerShell och verifiera förekomsten av Teams-modulen med följande kommando:
Get-module *teams*
Om du inte ser modulen installerar du den MicrosoftTeams
först. Om du vill installera modulen måste du köra PowerShell som administratör. Kör följande kommando:
Install-Module -Name MicrosoftTeams
Du får information om de moduler som kommer att installeras, vilket du kan bekräfta med ett Y
eller A
svar. Om modulen är installerad men inaktuell kan du köra följande kommando för att uppdatera modulen:
Update-Module MicrosoftTeams
2. Ansluta till Microsoft Teams-modulen
När modulen är installerad och klar kan du ansluta till MicrosftTeams-modulen med följande kommando. Du uppmanas att logga in med ett interaktivt fönster. Det användarkonto som du ska använda måste ha behörighet som Teams-administratör. Annars kan du få ett access denied
svar i nästa steg.
Connect-MicrosoftTeams
3. Aktivera klientkonfiguration
Samverkan med Communication Services-resurser styrs via klientkonfiguration och tilldelad princip. Teams klientorganisation har en enda klientkonfiguration och Teams-användare har tilldelat global princip eller anpassad princip. Mer information finns i Tilldela principer i Teams.
När inloggningen har slutförts kan du köra cmdleten Set-CsTeamsAcsFederationConfiguration för att aktivera Communication Services-resursen i klientorganisationen. Ersätt texten IMMUTABLE_RESOURCE_ID
med ett oföränderligt resurs-ID i kommunikationsresursen. Mer information om hur du hämtar den här informationen finns här.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktivera klientprincip
Varje Teams-användare har tilldelats en External Access Policy
som avgör om Communication Services-användare kan anropa den här Teams-användaren. Använd cmdleten Set-CsExternalAccessPolicy för att säkerställa att principen som tilldelats Teams-användaren har angetts EnableAcsFederationAccess
till $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Skapa eller välj Automatisk teams-dirigering
Automatisk dirigering i Teams är ett system som tillhandahåller ett automatiserat samtalshanteringssystem för inkommande samtal. Det fungerar som en virtuell receptionist, vilket gör det möjligt för uppringare att automatiskt dirigeras till lämplig person eller avdelning utan behov av en mänsklig operatör. Du kan välja befintlig eller skapa ny automatisk dirigering via Administrationscenter för Teams.
Läs mer om hur du skapar automatisk dirigering med Hjälp av Administrationscenter för Teams här.
Hitta objekt-ID för automatisk dirigering
När automatisk dirigering har skapats måste vi hitta korrelerat objekt-ID för att kunna använda det senare för anrop. Objekt-ID är anslutet till resurskonto som har kopplats till automatisk dirigering – öppna fliken Resurskonton i Teams-administratör och hitta e-post för kontot. All nödvändig information för resurskontot finns i Microsoft Graph Explorer med det här e-postmeddelandet i sökningen.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
I resultat kan vi hitta fältet "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
För att kunna använda den anropande appen måste vi lägga till ett prefix i det här ID:t. För närvarande stöds följande:
- Automatisk dirigering för offentliga moln:
28:orgid:<id>
- Automatisk dirigering för myndighetsmoln:
28:gcch:<id>
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto utan kostnad.
Android Studio för att skapa ditt Android-program.
En distribuerad Communication Services-resurs. Skapa en Communication Services-resurs.
En användaråtkomsttoken för azure-kommunikationstjänsten. Du kan också använda Azure CLI och köra kommandot med din anslutningssträng för att skapa en användare och en åtkomsttoken.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Mer information finns i Använda Azure CLI för att skapa och hantera åtkomsttoken.
Lägsta stöd för Teams-samtalsprogram: 2.12.0-beta.1
Konfigurera
Skapa en Android-app med en tom aktivitet
Från Android Studio väljer du Starta ett nytt Android Studio-projekt.
Välj projektmallen "Tom visningsaktivitet" under "Telefon och surfplatta".
Välj Minsta SDK för "API 26: Android 8.0 (Oreo)" eller senare.
Installera -paketet
Leta upp projektet settings.gradle.kts
och se till att se mavenCentral()
i listan över lagringsplatser under pluginManagement
och dependencyResolutionManagement
pluginManagement {
repositories {
...
mavenCentral()
...
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
...
mavenCentral()
}
}
I modulnivån build.gradle lägger du sedan till följande rader i avsnitten beroenden och Android
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
implementation ("com.azure.android:azure-communication-calling:2.6.0")
...
}
Lägga till behörigheter i programmanifestet
För att kunna begära behörigheter som krävs för att göra ett anrop måste de deklareras i programmanifestet (app/src/main/AndroidManifest.xml
). Ersätt innehållet i filen med följande kod:
<?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>
Konfigurera layouten för appen
Två indata behövs: en textinmatning för samtals-ID:t och en knapp för att ringa samtalet. Dessa indata kan läggas till via designern eller genom att redigera xml-layouten. Skapa en knapp med ett ID call_button
för och en textinmatning på callee_id
. Gå till (app/src/main/res/layout/activity_main.xml
) och ersätt innehållet i filen med följande kod:
<?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>
Skapa huvudaktivitetens byggnadsställningar och bindningar
När layouten har skapats kan bindningarna läggas till samt den grundläggande scaffoldingen för aktiviteten. Aktiviteten hanterar begäran om körningsbehörigheter, skapar samtalsagenten och anropar när knappen trycks ned. Metoden onCreate
åsidosättas för att anropa getAllPermissions
och createAgent
lägga till bindningar för anropsknappen. Den här händelsen inträffar bara en gång när aktiviteten skapas. Mer information onCreate
finns i guiden Förstå aktivitetslivscykeln.
Gå till MainActivity.java och ersätt innehållet med följande kod:
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));
}
}
Begär behörigheter vid körning
För Android 6.0 och senare (API-nivå 23) och targetSdkVersion
23 eller senare beviljas behörigheter vid körning i stället för när appen installeras. För att stödja det getAllPermissions
kan implementeras för att anropa ActivityCompat.checkSelfPermission
och ActivityCompat.requestPermissions
för varje nödvändig behörighet.
/**
* 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);
}
}
Kommentar
När du utformar din app bör du tänka på när dessa behörigheter ska begäras. Behörigheter bör begäras när de behövs, inte i förväg. Mer information finns i Android-behörighetsguiden.
Objektmodell
Följande klasser och gränssnitt hanterar några av de viktigaste funktionerna i Azure Communication Services Calling SDK:
Name | beskrivning |
---|---|
CallClient |
CallClient är den viktigaste startpunkten för anropande SDK. |
CallAgent |
CallAgent Används för att starta och hantera anrop. |
CommunicationTokenCredential |
CommunicationTokenCredential Används som tokenautentiseringsuppgifter för att instansiera CallAgent . |
CommunicationIdentifier |
CommunicationIdentifier Används som en annan typ av deltagare som kan ingå i ett anrop. |
Skapa en agent från användarens åtkomsttoken
Med en användartoken kan en autentiserad samtalsagent instansieras. Vanligtvis genereras denna token från en tjänst med autentisering som är specifik för programmet. Mer information om token för användaråtkomst finns i guiden Användaråtkomsttoken .
För snabbstarten ersätter du <User_Access_Token>
med en användaråtkomsttoken som genererats för din Azure Communication Service-resurs.
/**
* 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();
}
}
Kör koden
Appen kan nu startas med knappen "Kör app" i verktygsfältet.
Manuella steg för att konfigurera anropet:
- Starta appen med Android Studio.
- Ange objekt-ID för automatisk dirigering (med prefix) och välj knappen "Starta anrop". Programmet startar det utgående anropet till den automatiska dirigering med angivet objekt-ID.
- Samtalet är anslutet till den automatiska dirigering.
- Communication Services-användaren dirigeras via automatisk dirigering baserat på dess konfiguration.
Viktigt!
Den här funktionen i Azure Communication Services är för närvarande i förhandsversion.
Förhandsversions-API:er och SDK:er tillhandahålls utan ett serviceavtal. Vi rekommenderar att du inte använder dem för produktionsarbetsbelastningar. Vissa funktioner kanske inte stöds, eller så kan de ha begränsade funktioner.
Mer information finns i Kompletterande användningsvillkor för Förhandsversioner av Microsoft Azure.
I den här snabbstarten får du lära dig hur du startar ett samtal från Azure Communication Services-användare till Automatisk teams-dirigering. Du kommer att uppnå det med följande steg:
- Aktivera federation av Azure Communication Services-resurs med Teams-klientorganisation.
- Välj eller skapa automatisk teams-dirigering via Administrationscenter för Teams.
- Hämta e-postadressen för automatisk dirigering via Administrationscenter för Teams.
- Hämta objekt-ID för den automatiska dirigering via Graph API.
- Starta ett samtal med Azure Communication Services Calling SDK.
Om du vill gå vidare till slutet kan du ladda ned den här snabbstarten som ett exempel på GitHub.
Aktivera samverkan i din Teams-klientorganisation
Microsoft Entra-användare med Teams-administratörsroll kan köra PowerShell-cmdlet med MicrosoftTeams-modulen för att aktivera Communication Services-resursen i klientorganisationen.
1. Förbered Microsoft Teams-modulen
Öppna först PowerShell och verifiera förekomsten av Teams-modulen med följande kommando:
Get-module *teams*
Om du inte ser modulen installerar du den MicrosoftTeams
först. Om du vill installera modulen måste du köra PowerShell som administratör. Kör följande kommando:
Install-Module -Name MicrosoftTeams
Du får information om de moduler som kommer att installeras, vilket du kan bekräfta med ett Y
eller A
svar. Om modulen är installerad men inaktuell kan du köra följande kommando för att uppdatera modulen:
Update-Module MicrosoftTeams
2. Ansluta till Microsoft Teams-modulen
När modulen är installerad och klar kan du ansluta till MicrosftTeams-modulen med följande kommando. Du uppmanas att logga in med ett interaktivt fönster. Det användarkonto som du ska använda måste ha behörighet som Teams-administratör. Annars kan du få ett access denied
svar i nästa steg.
Connect-MicrosoftTeams
3. Aktivera klientkonfiguration
Samverkan med Communication Services-resurser styrs via klientkonfiguration och tilldelad princip. Teams klientorganisation har en enda klientkonfiguration och Teams-användare har tilldelat global princip eller anpassad princip. Mer information finns i Tilldela principer i Teams.
När inloggningen har slutförts kan du köra cmdleten Set-CsTeamsAcsFederationConfiguration för att aktivera Communication Services-resursen i klientorganisationen. Ersätt texten IMMUTABLE_RESOURCE_ID
med ett oföränderligt resurs-ID i kommunikationsresursen. Mer information om hur du hämtar den här informationen finns här.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktivera klientprincip
Varje Teams-användare har tilldelats en External Access Policy
som avgör om Communication Services-användare kan anropa den här Teams-användaren. Använd cmdleten Set-CsExternalAccessPolicy för att säkerställa att principen som tilldelats Teams-användaren har angetts EnableAcsFederationAccess
till $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Skapa eller välj Automatisk teams-dirigering
Automatisk dirigering i Teams är ett system som tillhandahåller ett automatiserat samtalshanteringssystem för inkommande samtal. Det fungerar som en virtuell receptionist, vilket gör det möjligt för uppringare att automatiskt dirigeras till lämplig person eller avdelning utan behov av en mänsklig operatör. Du kan välja befintlig eller skapa ny automatisk dirigering via Administrationscenter för Teams.
Läs mer om hur du skapar automatisk dirigering med Hjälp av Administrationscenter för Teams här.
Hitta objekt-ID för automatisk dirigering
När automatisk dirigering har skapats måste vi hitta korrelerat objekt-ID för att kunna använda det senare för anrop. Objekt-ID är anslutet till resurskonto som har kopplats till automatisk dirigering – öppna fliken Resurskonton i Teams-administratör och hitta e-post för kontot. All nödvändig information för resurskontot finns i Microsoft Graph Explorer med det här e-postmeddelandet i sökningen.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
I resultat kan vi hitta fältet "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
För att kunna använda den anropande appen måste vi lägga till ett prefix i det här ID:t. För närvarande stöds följande:
- Automatisk dirigering för offentliga moln:
28:orgid:<id>
- Automatisk dirigering för myndighetsmoln:
28:gcch:<id>
Förutsättningar
Skaffa ett Azure-konto med en aktiv prenumeration. Skapa ett konto utan kostnad.
En Mac som kör Xcode, tillsammans med ett giltigt utvecklarcertifikat installerat i nyckelringen.
En distribuerad Communication Services-resurs. Skapa en Communication Services-resurs. Du måste registrera anslutningssträng för den här snabbstarten.
En användaråtkomsttoken för azure-kommunikationstjänsten. Du kan också använda Azure CLI och köra kommandot med din anslutningssträng för att skapa en användare och en åtkomsttoken.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Mer information finns i Använda Azure CLI för att skapa och hantera åtkomsttoken.
Lägsta stöd för Teams-samtalsprogram: 2.14.0-beta.1
Konfigurera
Skapa Xcode-projektet
I Xcode skapar du ett nytt iOS-projekt och väljer appmallen. I den här självstudien används SwiftUI-ramverket, så du bör ange Språket till Swift och användargränssnittet till SwiftUI. Du kommer inte att skapa tester under den här snabbstarten. Avmarkera Inkludera tester.
Installera paketet och beroenden med CocoaPods
Om du vill skapa en Podfile för ditt program öppnar du terminalen och navigerar till projektmappen och kör:
pod init
Lägg till följande kod i Podfile och spara (se till att "målet" matchar namnet på projektet):
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 2.14.0-beta.1' end
Kör
pod install
..xcworkspace
Öppna med Xcode.
Begär åtkomst till mikrofonen
För att få åtkomst till enhetens mikrofon måste du uppdatera appens informationsegenskapslista med en NSMicrophoneUsageDescription
. Du anger det associerade värdet till en string
som ingick i den dialogruta som systemet använder för att begära åtkomst från användaren.
Högerklicka på posten i Info.plist
projektträdet och välj Öppna som>källkod. Lägg till följande rader i avsnittet på den översta nivån <dict>
och spara sedan filen.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Konfigurera appramverket
Öppna projektets ContentView.swift-fil och lägg till en import
deklaration överst i filen för att importera AzureCommunicationCalling library
. Dessutom behöver vi den AVFoundation
här koden för begäran om ljudbehörighet i koden.
import AzureCommunicationCalling
import AVFoundation
Ersätt implementeringen av ContentView
struct med några enkla användargränssnittskontroller som gör att en användare kan initiera och avsluta ett anrop. Vi kopplar affärslogik till dessa kontroller i den här snabbstarten.
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
Följande klasser och gränssnitt hanterar några av de viktigaste funktionerna i Azure Communication Services Calling SDK:
Name | beskrivning |
---|---|
CallClient |
CallClient är den viktigaste startpunkten för anropande SDK. |
CallAgent |
CallAgent Används för att starta och hantera anrop. |
CommunicationTokenCredential |
CommunicationTokenCredential Används som tokenautentiseringsuppgifter för att instansiera CallAgent . |
CommunicationUserIdentifier |
CommunicationUserIdentifier Används för att representera användarens identitet, vilket kan vara något av följande alternativ: CommunicationUserIdentifier ,PhoneNumberIdentifier ellerCallingApplication. |
Autentisera klienten
Initiera en CallAgent
instans med en användaråtkomsttoken, vilket gör att vi kan ringa och ta emot samtal.
I följande kod måste du ersätta <USER ACCESS TOKEN>
med en giltig användaråtkomsttoken för din resurs. Se dokumentationen för användaråtkomsttoken om du inte redan har en tillgänglig token.
Lägg till följande kod i återanropet onAppear
i 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.")
}
}
Starta ett samtal
Metoden startCall
anges som den åtgärd som utförs när knappen Starta samtal knackas. Uppdatera implementeringen för att starta ett anrop med 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")
}
}
}
}
}
Du kan också använda egenskaperna i StartCallOptions
för att ange de första alternativen för anropet (det vill säga att det tillåter att samtalet startas med mikrofonen avstängd).
Avsluta samtal
endCall
Implementera metoden för att avsluta det aktuella anropet när knappen Avsluta samtal knackas.
func endCall()
{
self.call!.hangUp(options: HangUpOptions()) { (error) in
if (error != nil) {
print("ERROR: It was not possible to hangup the call.")
}
}
}
Kör koden
Du kan skapa och köra appen i iOS-simulatorn genom att välja Produktkörning> eller med hjälp av kortkommandot (⌘-R).
Kommentar
Första gången du ringer ett anrop uppmanar systemet dig att få åtkomst till mikrofonen. I ett produktionsprogram bör du använda API:et AVAudioSession
för att kontrollera behörighetsstatusen och korrekt uppdatera programmets beteende när behörighet inte beviljas.
Manuella steg för att konfigurera anropet:
- Starta appen med Xcode
- Ange objekt-ID för automatisk dirigering (med prefix) och välj knappen "Starta anrop". Programmet startar det utgående anropet till den automatiska dirigering med angivet objekt-ID.
- Samtalet är anslutet till den automatiska dirigering.
- Communication Services-användaren dirigeras via automatisk dirigering baserat på dess konfiguration.
Viktigt!
Den här funktionen i Azure Communication Services är för närvarande i förhandsversion.
Förhandsversions-API:er och SDK:er tillhandahålls utan ett serviceavtal. Vi rekommenderar att du inte använder dem för produktionsarbetsbelastningar. Vissa funktioner kanske inte stöds, eller så kan de ha begränsade funktioner.
Mer information finns i Kompletterande användningsvillkor för Förhandsversioner av Microsoft Azure.
I den här snabbstarten får du lära dig hur du startar ett samtal från Azure Communication Services-användare till Automatisk teams-dirigering. Du kommer att uppnå det med följande steg:
- Aktivera federation av Azure Communication Services-resurs med Teams-klientorganisation.
- Välj eller skapa automatisk teams-dirigering via Administrationscenter för Teams.
- Hämta e-postadressen för automatisk dirigering via Administrationscenter för Teams.
- Hämta objekt-ID för den automatiska dirigering via Graph API.
- Starta ett samtal med Azure Communication Services Calling SDK.
Om du vill gå vidare till slutet kan du ladda ned den här snabbstarten som ett exempel på GitHub.
Aktivera samverkan i din Teams-klientorganisation
Microsoft Entra-användare med Teams-administratörsroll kan köra PowerShell-cmdlet med MicrosoftTeams-modulen för att aktivera Communication Services-resursen i klientorganisationen.
1. Förbered Microsoft Teams-modulen
Öppna först PowerShell och verifiera förekomsten av Teams-modulen med följande kommando:
Get-module *teams*
Om du inte ser modulen installerar du den MicrosoftTeams
först. Om du vill installera modulen måste du köra PowerShell som administratör. Kör följande kommando:
Install-Module -Name MicrosoftTeams
Du får information om de moduler som kommer att installeras, vilket du kan bekräfta med ett Y
eller A
svar. Om modulen är installerad men inaktuell kan du köra följande kommando för att uppdatera modulen:
Update-Module MicrosoftTeams
2. Ansluta till Microsoft Teams-modulen
När modulen är installerad och klar kan du ansluta till MicrosftTeams-modulen med följande kommando. Du uppmanas att logga in med ett interaktivt fönster. Det användarkonto som du ska använda måste ha behörighet som Teams-administratör. Annars kan du få ett access denied
svar i nästa steg.
Connect-MicrosoftTeams
3. Aktivera klientkonfiguration
Samverkan med Communication Services-resurser styrs via klientkonfiguration och tilldelad princip. Teams klientorganisation har en enda klientkonfiguration och Teams-användare har tilldelat global princip eller anpassad princip. Mer information finns i Tilldela principer i Teams.
När inloggningen har slutförts kan du köra cmdleten Set-CsTeamsAcsFederationConfiguration för att aktivera Communication Services-resursen i klientorganisationen. Ersätt texten IMMUTABLE_RESOURCE_ID
med ett oföränderligt resurs-ID i kommunikationsresursen. Mer information om hur du hämtar den här informationen finns här.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktivera klientprincip
Varje Teams-användare har tilldelats en External Access Policy
som avgör om Communication Services-användare kan anropa den här Teams-användaren. Använd cmdleten Set-CsExternalAccessPolicy för att säkerställa att principen som tilldelats Teams-användaren har angetts EnableAcsFederationAccess
till $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Skapa eller välj Automatisk teams-dirigering
Automatisk dirigering i Teams är ett system som tillhandahåller ett automatiserat samtalshanteringssystem för inkommande samtal. Det fungerar som en virtuell receptionist, vilket gör det möjligt för uppringare att automatiskt dirigeras till lämplig person eller avdelning utan behov av en mänsklig operatör. Du kan välja befintlig eller skapa ny automatisk dirigering via Administrationscenter för Teams.
Läs mer om hur du skapar automatisk dirigering med Hjälp av Administrationscenter för Teams här.
Hitta objekt-ID för automatisk dirigering
När automatisk dirigering har skapats måste vi hitta korrelerat objekt-ID för att kunna använda det senare för anrop. Objekt-ID är anslutet till resurskonto som har kopplats till automatisk dirigering – öppna fliken Resurskonton i Teams-administratör och hitta e-post för kontot. All nödvändig information för resurskontot finns i Microsoft Graph Explorer med det här e-postmeddelandet i sökningen.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
I resultat kan vi hitta fältet "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
För att kunna använda den anropande appen måste vi lägga till ett prefix i det här ID:t. För närvarande stöds följande:
- Automatisk dirigering för offentliga moln:
28:orgid:<id>
- Automatisk dirigering för myndighetsmoln:
28:gcch:<id>
Förutsättningar
För att slutföra den här självstudien, finns följande förhandskrav:
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto utan kostnad.
Installera Visual Studio 2022 med Universell Windows-plattform utvecklingsarbetsbelastning.
En distribuerad Communication Services-resurs. Skapa en Communication Services-resurs. Du måste registrera anslutningssträng för den här snabbstarten.
En användaråtkomsttoken för azure-kommunikationstjänsten. Du kan också använda Azure CLI och köra kommandot med din anslutningssträng för att skapa en användare och en åtkomsttoken.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Mer information finns i Använda Azure CLI för att skapa och hantera åtkomsttoken.
Lägsta stöd för Teams-samtalsprogram: 1.10.0-beta.1
Konfigurera
Skapa projektet
I Visual Studio skapar du ett nytt projekt med mallen Tom app (Universell Windows) för att konfigurera en enkelsidig Universell Windows-plattform-app (UWP).
Installera -paketet
Välj projektet och gå till för att Manage Nuget Packages
installera Azure.Communication.Calling.WindowsClient
1.4.0 eller superior. Kontrollera att Include Prerelease
är markerat om du vill se versionerna för offentlig förhandsversion.
Begär åtkomst
Gå till Package.appxmanifest
och välj Capabilities
.
Kontrollera Internet (Client)
och Internet (Client & Server)
för att få inkommande och utgående åtkomst till Internet. Kontrollera Microphone
om du vill komma åt mikrofonens ljudflöde och Webcam
få åtkomst till kamerans videoflöde.
Konfigurera appramverket
Vi måste konfigurera en grundläggande layout för att koppla vår logik. För att kunna ringa ett utgående samtal behöver vi ett TextBox
för att ange användar-ID:t för den anropade. Vi behöver också en Start/Join call
knapp och en Hang up
knapp. En Mute
och en BackgroundBlur
kryssrutor ingår också i det här exemplet för att demonstrera funktionerna i att växla ljudtillstånd och videoeffekter.
MainPage.xaml
Öppna projektet och lägg till noden i Grid
:Page
<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>
MainPage.xaml.cs
Öppna och ersätt innehållet med följande implementering:
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
I nästa tabell visas klasserna och gränssnitten som hanterar några av de viktigaste funktionerna i Azure Communication Services Calling SDK:
Name | beskrivning |
---|---|
CallClient |
CallClient är den viktigaste startpunkten för anropande SDK. |
CallAgent |
CallAgent Används för att starta och hantera anrop. |
CommunicationCall |
CommunicationCall Används för att hantera ett pågående anrop. |
CallTokenCredential |
CallTokenCredential Används som tokenautentiseringsuppgifter för att instansiera CallAgent . |
CallIdentifier |
CallIdentifier Används för att representera användarens identitet, vilket kan vara något av följande alternativ: UserCallIdentifier , PhoneNumberCallIdentifier osv. |
Autentisera klienten
Initiera en CallAgent
instans med en användaråtkomsttoken som gör att vi kan göra och ta emot anrop och eventuellt hämta en DeviceManager-instans för att fråga efter klientenhetskonfigurationer.
I koden ersätter du <AUTHENTICATION_TOKEN>
med en användaråtkomsttoken. Se dokumentationen för användaråtkomsttoken om du inte redan har en tillgänglig token.
Lägg till InitCallAgentAndDeviceManagerAsync
funktion, som startar SDK:t. Den här hjälpen kan anpassas för att uppfylla kraven för ditt program.
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;
}
Starta samtalet
När ett StartCallOptions
objekt har hämtats CallAgent
kan användas för att initiera Azure Communication Services-anropet:
private async Task<CommunicationCall> StartCallAsync(string acsCallee)
{
var options = new StartCallOptions();
var call = await this.callAgent.StartCallAsync( new [] { new MicrosoftTeamsAppCallIdentifier(acsCallee) }, options);
return call;
}
Avsluta samtal
Avsluta det aktuella samtalet när Hang up
knappen klickas. Lägg till implementeringen i HangupButton_Click för att avsluta ett anrop och stoppa förhandsgranskningen och videoströmmarna.
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 });
}
}
Växla ljudavstängning/ljudavstängning
Stäng av det utgående ljudet när Mute
knappen klickas. Lägg till implementeringen i MuteLocal_Click för att stänga av anropet.
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
}
}
Acceptera ett inkommande samtal
IncomingCallReceived
händelsemottagaren har konfigurerats i SDK bootstrap-hjälpen InitCallAgentAndDeviceManagerAsync
.
this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
Programmet har möjlighet att konfigurera hur det inkommande samtalet ska godkännas, till exempel video- och ljudströmstyper.
private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
{
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() { };
call = await incomingCall.AcceptAsync(acceptCallOptions);
call.StateChanged += OnStateChangedAsync;
}
Övervaka och svara på anropstillståndsändringshändelse
StateChanged
händelsen på CommunicationCall
objektet utlöses när en pågående anropstransaktioner från ett tillstånd till ett annat. Programmet erbjuds möjligheter att återspegla tillståndsändringarna i användargränssnittet eller infoga affärslogik.
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;
}
}
}
Få samtalsknappen att fungera
När inte Callee ID
är null eller tomt kan du starta ett anrop.
Anropstillståndet måste ändras med hjälp av åtgärden OnStateChangedAsync
.
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;
}
}
Kör koden
Du kan skapa och köra koden i Visual Studio. För lösningsplattformar har vi stöd ARM64
för , x64
och x86
.
Manuella steg för att konfigurera anropet:
- Starta appen med Visual Studio.
- Ange objekt-ID för automatisk dirigering (med prefix) och välj knappen "Starta anrop". Programmet startar det utgående anropet till den automatiska dirigering med angivet objekt-ID.
- Samtalet är anslutet till den automatiska dirigering.
- Communication Services-användaren dirigeras via automatisk dirigering baserat på dess konfiguration.
Rensa resurser
Om du vill rensa och ta bort en Communication Services-prenumeration kan du ta bort resursen eller resursgruppen. Om du tar bort resursgruppen tas även alla andra resurser som är associerade med den bort. Läs mer om att rensa resurser.
Nästa steg
Mer information finns i följande artiklar:
- Kom igång med UI-samtal till Teams Röstappar
- Lär dig mer om funktioner för samtals-SDK
- Läs mer om hur samtal fungerar