Rychlý start: Připojení volající aplikace k frontě volání Teams
V tomto rychlém startu se dozvíte, jak zahájit volání od uživatele Azure Communication Services do fronty volání Teams. Dosáhnete toho pomocí následujících kroků:
- Povolte federaci prostředku Azure Communication Services s tenantem Teams.
- Vyberte nebo vytvořte frontu volání teams prostřednictvím Centra pro správu Teams.
- Získejte e-mailovou adresu fronty volání prostřednictvím Centra pro správu Teams.
- Získejte ID objektu fronty volání prostřednictvím rozhraní Graph API.
- Začněte volat pomocí sady SDK pro volání služeb Azure Communication Services.
Pokud chcete přeskočit na konec, můžete si tento rychlý start stáhnout jako ukázku na GitHubu.
Povolení interoperability v tenantovi Teams
Uživatel Microsoft Entra s rolí správce Teams může spustit rutinu PowerShellu s modulem MicrosoftTeams a povolit prostředek Komunikační služby v tenantovi.
1. Příprava modulu Microsoft Teams
Nejprve otevřete PowerShell a pomocí následujícího příkazu ověřte existenci modulu Teams:
Get-module *teams*
Pokud modul nevidíte MicrosoftTeams
, nejdřív ho nainstalujte. Pokud chcete nainstalovat modul, musíte spustit PowerShell jako správce. Pak spusťte následující příkaz:
Install-Module -Name MicrosoftTeams
Budete informováni o nainstalovaných modulech, které můžete potvrdit pomocí Y
odpovědi.A
Pokud je modul nainstalovaný, ale je zastaralý, můžete spuštěním následujícího příkazu modul aktualizovat:
Update-Module MicrosoftTeams
2. Připojení k modulu Microsoft Teams
Po instalaci a připravenosti modulu se můžete připojit k modulu MicrosoftTeams pomocí následujícího příkazu. Zobrazí se výzva k přihlášení pomocí interaktivního okna. Uživatelský účet, který budete používat, musí mít oprávnění správce Teams. V opačném případě můžete získat access denied
odpověď v dalších krocích.
Connect-MicrosoftTeams
3. Povolení konfigurace tenanta
Interoperabilita s prostředky komunikačních služeb se řídí prostřednictvím konfigurace tenanta a přiřazených zásad. Tenant Teams má jednu konfiguraci tenanta a uživatelé Teams přiřadili globální zásady nebo vlastní zásady. Další informace najdete v tématu Přiřazení zásad v Teams.
Po úspěšném přihlášení můžete spuštěním rutiny Set-CsTeamsAcsFederationConfiguration povolit prostředek Komunikační služby ve vašem tenantovi. Nahraďte text IMMUTABLE_RESOURCE_ID
neměnným ID prostředku v komunikačním prostředku. Další podrobnosti o tom, jak tyto informace získat, najdete tady.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Povolení zásad tenanta
Každý uživatel Teams přiřadil, External Access Policy
který určuje, jestli uživatelé komunikačních služeb mohou volat tohoto uživatele Teams. Pomocí rutiny Set-CsExternalAccessPolicy zajistěte, aby zásady přiřazené uživateli Teams byly nastaveny EnableAcsFederationAccess
na $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Vytvoření nebo výběr fronty volání v Teams
Fronta hovorů v Teams je funkce v Microsoft Teams, která efektivně distribuuje příchozí hovory mezi skupinu určených uživatelů nebo agentů. Je užitečné pro scénáře zákaznické podpory nebo call centra. Volání se umístí do fronty a přiřadí se k dalšímu dostupnému agentovi na základě předem určené metody směrování. Agenti přijímají oznámení a můžou zpracovávat hovory pomocí ovládacích prvků volání v Teams. Tato funkce nabízí vytváření sestav a analýzy pro sledování výkonu. Zjednodušuje zpracování hovorů, zajišťuje konzistentní uživatelské prostředí a optimalizuje produktivitu agentů. Můžete vybrat existující nebo vytvořit novou frontu volání prostřednictvím Centra pro správu Teams.
Přečtěte si další informace o tom, jak vytvořit frontu volání pomocí Centra pro správu Teams.
Vyhledání ID objektu pro frontu volání
Po vytvoření fronty volání potřebujeme najít korelované ID objektu, abychom ho mohli později použít pro volání. ID objektu je připojené k účtu prostředku připojenému k frontě volání – otevřete kartu Účty zdrojů v Aplikaci Teams Admin a vyhledejte e-mail.
Všechny požadované informace o účtu prostředků najdete v Microsoft Graph Exploreru pomocí tohoto e-mailu ve vyhledávání.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Ve výsledcích budeme moct najít pole ID.
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Požadavky
- Získejte účet Azure s aktivním předplatným. Vytvoření účtu zdarma
- Node.js verze LTS a údržba ACTIVE LTS (8.11.1 a 10.14.1)
- Vytvořte aktivní prostředek komunikační služby. Vytvořte prostředek komunikační služby.
Nastavení
Vytvoření nové aplikace Node.js
Otevřete terminál nebo příkazové okno, vytvořte pro aplikaci nový adresář a přejděte do adresáře.
mkdir calling-quickstart && cd calling-quickstart
Nainstalujte balíček .
npm install
Pomocí příkazu nainstalujte sadu SDK pro volání služeb Azure Communication Services pro JavaScript.
Důležité
V tomto rychlém startu se používá verze next
sady SDK pro volání služeb Azure Communication Services .
npm install @azure/communication-common@next --save
npm install @azure/communication-calling@next --save
Nastavení architektury aplikace
V tomto rychlém startu se ke sbalení prostředků aplikace používá webpack. Spuštěním následujícího příkazu nainstalujte webpack
balíčky a webpack-cli
npm a webpack-dev-server
uveďte je jako vývojové závislosti ve vaší 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
Vytvořte index.html
soubor v kořenovém adresáři projektu. Tento soubor použijeme ke konfiguraci základního rozložení, které uživateli umožní umístit videohovor 1:1.
Tady je kód:
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Azure Communication Services - Calling Web SDK</title>
</head>
<body>
<h4>Azure Communication Services - Calling Web SDK</h4>
<input id="user-access-token"
type="text"
placeholder="User access token"
style="margin-bottom:1em; width: 500px;"/>
<button id="initialize-teams-call-agent" type="button">Initialize Call Agent</button>
<br>
<br>
<input id="application-object-id"
type="text"
placeholder="Enter callee's Teams user identity in format: 'APP_GUID'"
style="margin-bottom:1em; width: 500px; display: block;"/>
<button id="start-call-button" type="button" disabled="true">Start Call</button>
<button id="hangup-call-button" type="button" disabled="true">Hang up Call</button>
<button id="accept-call-button" type="button" disabled="true">Accept Call</button>
<button id="start-video-button" type="button" disabled="true">Start Video</button>
<button id="stop-video-button" type="button" disabled="true">Stop Video</button>
<br>
<br>
<div id="connectedLabel" style="color: #13bb13;" hidden>Call is connected!</div>
<br>
<div id="remoteVideoContainer" style="width: 40%;" hidden>Remote participants' video streams:</div>
<br>
<div id="localVideoContainer" style="width: 30%;" hidden>Local video stream:</div>
<!-- points to the bundle generated from client.js -->
<script src="./main.js"></script>
</body>
</html>
Objektový model webové sady SDK volání služeb Azure Communication Services
Následující třídy a rozhraní zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Hlavní vstupní bod do volající sady SDK. |
CallAgent |
Používá se ke spouštění a správě hovorů. |
DeviceManager |
Slouží ke správě mediálních zařízení. |
Call |
Používá se pro reprezentaci hovoru. |
LocalVideoStream |
Používá se k vytvoření místního videostreamu pro zařízení fotoaparátu v místním systému. |
RemoteParticipant |
Slouží k reprezentaci vzdáleného účastníka hovoru. |
RemoteVideoStream |
Používá se pro reprezentaci vzdáleného video streamu ze vzdáleného účastníka. |
Vytvořte soubor v kořenovém adresáři projektu, který bude client.js
obsahovat logiku aplikace pro účely tohoto rychlého startu. Do client.js přidejte následující kód:
// Make sure to install the necessary dependencies
const { CallClient, VideoStreamRenderer, LocalVideoStream } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential } = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the log level and output
setLogLevel('verbose');
AzureLogger.log = (...args) => {
console.log(...args);
};
// Calling web sdk objects
let callAgent;
let deviceManager;
let call;
let incomingCall;
let localVideoStream;
let localVideoStreamRenderer;
// UI widgets
let userAccessToken = document.getElementById('user-access-token');
let callQueueId = document.getElementById('application-object-id');
let initializeCallAgentButton = document.getElementById('initialize-teams-call-agent');
let startCallButton = document.getElementById('start-call-button');
let hangUpCallButton = document.getElementById('hangup-call-button');
let acceptCallButton = document.getElementById('accept-call-button');
let startVideoButton = document.getElementById('start-video-button');
let stopVideoButton = document.getElementById('stop-video-button');
let connectedLabel = document.getElementById('connectedLabel');
let remoteVideoContainer = document.getElementById('remoteVideoContainer');
let localVideoContainer = document.getElementById('localVideoContainer');
/**
* Create an instance of CallClient. Initialize a CallAgent instance with a AzureCommunicationTokenCredential via created CallClient. CallAgent enables us to make outgoing calls and receive incoming calls.
* You can then use the CallClient.getDeviceManager() API instance to get the DeviceManager.
*/
initializeCallAgentButton.onclick = async () => {
try {
const callClient = new CallClient();
tokenCredential = new AzureCommunicationTokenCredential(userAccessToken.value.trim());
callAgent = await callClient.createCallAgent(tokenCredential)
// Set up a camera device to use.
deviceManager = await callClient.getDeviceManager();
await deviceManager.askDevicePermission({ video: true });
await deviceManager.askDevicePermission({ audio: true });
// Listen for an incoming call to accept.
callAgent.on('incomingCall', async (args) => {
try {
incomingCall = args.incomingCall;
acceptCallButton.disabled = false;
startCallButton.disabled = true;
} catch (error) {
console.error(error);
}
});
startCallButton.disabled = false;
initializeCallAgentButton.disabled = true;
} catch(error) {
console.error(error);
}
}
/**
* Place a 1:1 outgoing video call to a Teams Call Queue
* Add an event listener to initiate a call when the `startCallButton` is selected.
* Enumerate local cameras using the deviceManager `getCameraList` API.
* In this quickstart, we're using the first camera in the collection. Once the desired camera is selected, a
* LocalVideoStream instance will be constructed and passed within `videoOptions` as an item within the
* localVideoStream array to the call method. When the call connects, your application will be sending a video stream to the other participant.
*/
startCallButton.onclick = async () => {
try {
const localVideoStream = await createLocalVideoStream();
const videoOptions = localVideoStream ? { localVideoStreams: [localVideoStream] } : undefined;
call = callAgent.startCall([{ teamsAppId: callQueueId.value.trim(), cloud:"public" }], { videoOptions: videoOptions });
// Subscribe to the call's properties and events.
subscribeToCall(call);
} catch (error) {
console.error(error);
}
}
/**
* Accepting an incoming call with a video
* Add an event listener to accept a call when the `acceptCallButton` is selected.
* You can accept incoming calls after subscribing to the `CallAgent.on('incomingCall')` event.
* You can pass the local video stream to accept the call with the following code.
*/
acceptCallButton.onclick = async () => {
try {
const localVideoStream = await createLocalVideoStream();
const videoOptions = localVideoStream ? { localVideoStreams: [localVideoStream] } : undefined;
call = await incomingCall.accept({ videoOptions });
// Subscribe to the call's properties and events.
subscribeToCall(call);
} catch (error) {
console.error(error);
}
}
// Subscribe to a call obj.
// Listen for property changes and collection updates.
subscribeToCall = (call) => {
try {
// Inspect the initial call.id value.
console.log(`Call Id: ${call.id}`);
//Subscribe to call's 'idChanged' event for value changes.
call.on('idChanged', () => {
console.log(`Call ID changed: ${call.id}`);
});
// Inspect the initial call.state value.
console.log(`Call state: ${call.state}`);
// Subscribe to call's 'stateChanged' event for value changes.
call.on('stateChanged', async () => {
console.log(`Call state changed: ${call.state}`);
if(call.state === 'Connected') {
connectedLabel.hidden = false;
acceptCallButton.disabled = true;
startCallButton.disabled = true;
hangUpCallButton.disabled = false;
startVideoButton.disabled = false;
stopVideoButton.disabled = false;
} else if (call.state === 'Disconnected') {
connectedLabel.hidden = true;
startCallButton.disabled = false;
hangUpCallButton.disabled = true;
startVideoButton.disabled = true;
stopVideoButton.disabled = true;
console.log(`Call ended, call end reason={code=${call.callEndReason.code}, subCode=${call.callEndReason.subCode}}`);
}
});
call.localVideoStreams.forEach(async (lvs) => {
localVideoStream = lvs;
await displayLocalVideoStream();
});
call.on('localVideoStreamsUpdated', e => {
e.added.forEach(async (lvs) => {
localVideoStream = lvs;
await displayLocalVideoStream();
});
e.removed.forEach(lvs => {
removeLocalVideoStream();
});
});
call.on('isLocalVideoStartedChanged', () => {
console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
});
console.log(`isLocalVideoStarted: ${call.isLocalVideoStarted}`);
// Inspect the call's current remote participants and subscribe to them.
call.remoteParticipants.forEach(remoteParticipant => {
subscribeToRemoteParticipant(remoteParticipant);
});
// Subscribe to the call's 'remoteParticipantsUpdated' event to be
// notified when new participants are added to the call or removed from the call.
call.on('remoteParticipantsUpdated', e => {
// Subscribe to new remote participants that are added to the call.
e.added.forEach(remoteParticipant => {
subscribeToRemoteParticipant(remoteParticipant)
});
// Unsubscribe from participants that are removed from the call
e.removed.forEach(remoteParticipant => {
console.log('Remote participant removed from the call.');
});
});
} catch (error) {
console.error(error);
}
}
// Subscribe to a remote participant obj.
// Listen for property changes and collection updates.
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 remoteParticipant 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();
});
Přidání kódu místního serveru webpacku
V kořenovém adresáři projektu vytvořte soubor s názvem webpack.config.js , který bude obsahovat logiku místního serveru pro účely tohoto rychlého startu. Do webpack.config.js přidejte následující kód:
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'
]
}),
]
};
Spuštění kódu
Použijte k webpack-dev-server
sestavení a spuštění aplikace. Spuštěním následujícího příkazu sbalte hostitele aplikace v místním webovém serveru:
npx webpack serve --config webpack.config.js
Ruční postup nastavení hovoru:
- Otevřete prohlížeč a přejděte na http://localhost:8080/.
- Zadejte platný přístupový token uživatele. Pokud ještě nemáte k dispozici přístupové tokeny, projděte si dokumentaci k přístupovým tokenům uživatele.
- Klikněte na tlačítka Inicializovat agenta volání.
- Zadejte ID objektu fronty volání a vyberte tlačítko Zahájit hovor. Aplikace spustí odchozí volání do fronty volání s daným ID objektu.
- Volání je připojené k frontě volání.
- Uživatel komunikačních služeb je směrován prostřednictvím fronty volání na základě své konfigurace.
V tomto rychlém startu se dozvíte, jak zahájit volání od uživatele Azure Communication Services do fronty volání Teams. Dosáhnete toho pomocí následujících kroků:
- Povolte federaci prostředku Azure Communication Services s tenantem Teams.
- Vyberte nebo vytvořte frontu volání teams prostřednictvím Centra pro správu Teams.
- Získejte e-mailovou adresu fronty volání prostřednictvím Centra pro správu Teams.
- Získejte ID objektu fronty volání prostřednictvím rozhraní Graph API.
- Začněte volat pomocí sady SDK pro volání služeb Azure Communication Services.
Pokud chcete přeskočit na konec, můžete si tento rychlý start stáhnout jako ukázku na GitHubu.
Povolení interoperability v tenantovi Teams
Uživatel Microsoft Entra s rolí správce Teams může spustit rutinu PowerShellu s modulem MicrosoftTeams a povolit prostředek Komunikační služby v tenantovi.
1. Příprava modulu Microsoft Teams
Nejprve otevřete PowerShell a pomocí následujícího příkazu ověřte existenci modulu Teams:
Get-module *teams*
Pokud modul nevidíte MicrosoftTeams
, nejdřív ho nainstalujte. Pokud chcete nainstalovat modul, musíte spustit PowerShell jako správce. Pak spusťte následující příkaz:
Install-Module -Name MicrosoftTeams
Budete informováni o nainstalovaných modulech, které můžete potvrdit pomocí Y
odpovědi.A
Pokud je modul nainstalovaný, ale je zastaralý, můžete spuštěním následujícího příkazu modul aktualizovat:
Update-Module MicrosoftTeams
2. Připojení k modulu Microsoft Teams
Po instalaci a připravenosti modulu se můžete připojit k modulu MicrosoftTeams pomocí následujícího příkazu. Zobrazí se výzva k přihlášení pomocí interaktivního okna. Uživatelský účet, který budete používat, musí mít oprávnění správce Teams. V opačném případě můžete získat access denied
odpověď v dalších krocích.
Connect-MicrosoftTeams
3. Povolení konfigurace tenanta
Interoperabilita s prostředky komunikačních služeb se řídí prostřednictvím konfigurace tenanta a přiřazených zásad. Tenant Teams má jednu konfiguraci tenanta a uživatelé Teams přiřadili globální zásady nebo vlastní zásady. Další informace najdete v tématu Přiřazení zásad v Teams.
Po úspěšném přihlášení můžete spuštěním rutiny Set-CsTeamsAcsFederationConfiguration povolit prostředek Komunikační služby ve vašem tenantovi. Nahraďte text IMMUTABLE_RESOURCE_ID
neměnným ID prostředku v komunikačním prostředku. Další podrobnosti o tom, jak tyto informace získat, najdete tady.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Povolení zásad tenanta
Každý uživatel Teams přiřadil, External Access Policy
který určuje, jestli uživatelé komunikačních služeb mohou volat tohoto uživatele Teams. Pomocí rutiny Set-CsExternalAccessPolicy zajistěte, aby zásady přiřazené uživateli Teams byly nastaveny EnableAcsFederationAccess
na $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Vytvoření nebo výběr fronty volání v Teams
Fronta hovorů v Teams je funkce v Microsoft Teams, která efektivně distribuuje příchozí hovory mezi skupinu určených uživatelů nebo agentů. Je užitečné pro scénáře zákaznické podpory nebo call centra. Volání se umístí do fronty a přiřadí se k dalšímu dostupnému agentovi na základě předem určené metody směrování. Agenti přijímají oznámení a můžou zpracovávat hovory pomocí ovládacích prvků volání v Teams. Tato funkce nabízí vytváření sestav a analýzy pro sledování výkonu. Zjednodušuje zpracování hovorů, zajišťuje konzistentní uživatelské prostředí a optimalizuje produktivitu agentů. Můžete vybrat existující nebo vytvořit novou frontu volání prostřednictvím Centra pro správu Teams.
Přečtěte si další informace o tom, jak vytvořit frontu volání pomocí Centra pro správu Teams.
Vyhledání ID objektu pro frontu volání
Po vytvoření fronty volání potřebujeme najít korelované ID objektu, abychom ho mohli později použít pro volání. ID objektu je připojené k účtu prostředku připojenému k frontě volání – otevřete kartu Účty zdrojů v Aplikaci Teams Admin a vyhledejte e-mail.
Všechny požadované informace o účtu prostředků najdete v Microsoft Graph Exploreru pomocí tohoto e-mailu ve vyhledávání.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Ve výsledcích budeme moct najít pole ID.
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Abychom mohli v volající aplikaci používat, musíme k tomuto ID přidat předponu. V současné době jsou podporovány následující položky:
- Fronta volání veřejného cloudu:
28:orgid:<id>
- Fronta volání cloudu pro státní správu:
28:gcch:<id>
Požadavky
Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
Android Studio pro vytvoření aplikace pro Android
Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby.
Přístupový token uživatele pro vaši službu Azure Communication Service. K vytvoření uživatele a přístupového tokenu můžete také použít Azure CLI a spustit příkaz se svým připojovací řetězec.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Podrobnosti najdete v tématu Použití Azure CLI k vytváření a správě přístupových tokenů.
Minimální podpora pro aplikace teams volající: 2.12.0-beta.1
Nastavení
Vytvoření aplikace pro Android s prázdnou aktivitou
V Android Studiu vyberte Spustit nový projekt Android Studio.
V části Telefon a tablet vyberte šablonu projektu Prázdná zobrazení.
Vyberte minimální sadu SDK rozhraní API 26: Android 8.0 (Oreo) nebo vyšší.
Nainstalujte balíček .
Vyhledejte projekt settings.gradle.kts
a nezapomeňte se podívat mavenCentral()
na seznam úložišť v části pluginManagement
a dependencyResolutionManagement
pluginManagement {
repositories {
...
mavenCentral()
...
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
...
mavenCentral()
}
}
Potom na úrovni modulu build.gradle přidejte následující řádky do oddílů závislostí a androidu.
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
implementation ("com.azure.android:azure-communication-calling:2.+")
...
}
Přidání oprávnění k manifestu aplikace
Aby bylo možné požádat o oprávnění požadovaná k volání, musí být deklarována v manifestu aplikace (app/src/main/AndroidManifest.xml
). Obsah souboru nahraďte následujícím kódem:
<?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>
Nastavení rozložení aplikace
Jsou potřeba dva vstupy: textový vstup pro volané ID a tlačítko pro umístění hovoru. Tyto vstupy lze přidat prostřednictvím návrháře nebo úpravou xml rozložení. Vytvořte tlačítko s ID call_button
a textovým vstupem callee_id
. Přejděte na (app/src/main/res/layout/activity_main.xml
) a nahraďte obsah souboru následujícím kódem:
<?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>
Vytvoření generování uživatelského rozhraní a vazeb hlavní aktivity
S rozložením vytvořeným vazbami je možné přidat i základní generování aktivity. Aktivita zpracovává žádosti o oprávnění modulu runtime, vytvoření agenta volání a umístění hovoru při stisknutí tlačítka. Metoda onCreate
je přepsána k vyvolání getAllPermissions
a createAgent
přidání vazeb pro tlačítko volání. K této události dochází pouze jednou při vytvoření aktivity. Další informace onCreate
najdete v příručce Principy životního cyklu aktivity.
Přejděte na MainActivity.java a nahraďte obsah následujícím kódem:
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;
}
List<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));
}
}
Vyžádání oprávnění za běhu
Pro Android 6.0 a vyšší (úroveň rozhraní API 23) a targetSdkVersion
23 nebo vyšší jsou oprávnění udělena za běhu místo instalace aplikace. Aby bylo možné ho podporovat, getAllPermissions
je možné implementovat volání ActivityCompat.checkSelfPermission
a ActivityCompat.requestPermissions
pro každé požadované oprávnění.
/**
* 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);
}
}
Poznámka:
Při návrhu aplikace zvažte, kdy by se tato oprávnění měla požadovat. Oprávnění by se měla vyžadovat podle potřeby, a ne předem. Další informace najdete v průvodci oprávněními androidu .
Objektový model
Následující třídy a rozhraní zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Jedná se CallClient o hlavní vstupní bod volající sady SDK. |
CallAgent |
Slouží CallAgent ke spouštění a správě hovorů. |
CommunicationTokenCredential |
Slouží CommunicationTokenCredential jako přihlašovací údaje tokenu k vytvoření instance CallAgent . |
CommunicationIdentifier |
Používá CommunicationIdentifier se jako jiný typ účastníka, který může být součástí hovoru. |
Vytvoření agenta z přístupového tokenu uživatele
Pomocí tokenu uživatele je možné vytvořit instanci ověřeného agenta volání. Obecně platí, že tento token se generuje ze služby s ověřováním specifickým pro aplikaci. Další informace o přístupových tokenech uživatelů najdete v průvodci uživatelskými přístupovými tokeny .
V tomto rychlém startu nahraďte <User_Access_Token>
přístupovým tokenem uživatele vygenerovaným pro prostředek služby Azure Communication Service.
/**
* 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();
}
}
Spuštění kódu
Aplikaci teď můžete spustit pomocí tlačítka Spustit aplikaci na panelu nástrojů.
Ruční postup nastavení hovoru:
- Spusťte aplikaci pomocí Android Studia.
- Zadejte ID objektu fronty volání (s předponou) a vyberte tlačítko Zahájit hovor. Aplikace spustí odchozí volání do fronty volání s daným ID objektu.
- Volání je připojené k frontě volání.
- Uživatel komunikačních služeb je směrován prostřednictvím fronty volání na základě své konfigurace.
V tomto rychlém startu se dozvíte, jak zahájit volání od uživatele Azure Communication Services do fronty volání Teams. Dosáhnete toho pomocí následujících kroků:
- Povolte federaci prostředku Azure Communication Services s tenantem Teams.
- Vyberte nebo vytvořte frontu volání teams prostřednictvím Centra pro správu Teams.
- Získejte e-mailovou adresu fronty volání prostřednictvím Centra pro správu Teams.
- Získejte ID objektu fronty volání prostřednictvím rozhraní Graph API.
- Začněte volat pomocí sady SDK pro volání služeb Azure Communication Services.
Pokud chcete přeskočit na konec, můžete si tento rychlý start stáhnout jako ukázku na GitHubu.
Povolení interoperability v tenantovi Teams
Uživatel Microsoft Entra s rolí správce Teams může spustit rutinu PowerShellu s modulem MicrosoftTeams a povolit prostředek Komunikační služby v tenantovi.
1. Příprava modulu Microsoft Teams
Nejprve otevřete PowerShell a pomocí následujícího příkazu ověřte existenci modulu Teams:
Get-module *teams*
Pokud modul nevidíte MicrosoftTeams
, nejdřív ho nainstalujte. Pokud chcete nainstalovat modul, musíte spustit PowerShell jako správce. Pak spusťte následující příkaz:
Install-Module -Name MicrosoftTeams
Budete informováni o nainstalovaných modulech, které můžete potvrdit pomocí Y
odpovědi.A
Pokud je modul nainstalovaný, ale je zastaralý, můžete spuštěním následujícího příkazu modul aktualizovat:
Update-Module MicrosoftTeams
2. Připojení k modulu Microsoft Teams
Po instalaci a připravenosti modulu se můžete připojit k modulu MicrosoftTeams pomocí následujícího příkazu. Zobrazí se výzva k přihlášení pomocí interaktivního okna. Uživatelský účet, který budete používat, musí mít oprávnění správce Teams. V opačném případě můžete získat access denied
odpověď v dalších krocích.
Connect-MicrosoftTeams
3. Povolení konfigurace tenanta
Interoperabilita s prostředky komunikačních služeb se řídí prostřednictvím konfigurace tenanta a přiřazených zásad. Tenant Teams má jednu konfiguraci tenanta a uživatelé Teams přiřadili globální zásady nebo vlastní zásady. Další informace najdete v tématu Přiřazení zásad v Teams.
Po úspěšném přihlášení můžete spuštěním rutiny Set-CsTeamsAcsFederationConfiguration povolit prostředek Komunikační služby ve vašem tenantovi. Nahraďte text IMMUTABLE_RESOURCE_ID
neměnným ID prostředku v komunikačním prostředku. Další podrobnosti o tom, jak tyto informace získat, najdete tady.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Povolení zásad tenanta
Každý uživatel Teams přiřadil, External Access Policy
který určuje, jestli uživatelé komunikačních služeb mohou volat tohoto uživatele Teams. Pomocí rutiny Set-CsExternalAccessPolicy zajistěte, aby zásady přiřazené uživateli Teams byly nastaveny EnableAcsFederationAccess
na $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Vytvoření nebo výběr fronty volání v Teams
Fronta hovorů v Teams je funkce v Microsoft Teams, která efektivně distribuuje příchozí hovory mezi skupinu určených uživatelů nebo agentů. Je užitečné pro scénáře zákaznické podpory nebo call centra. Volání se umístí do fronty a přiřadí se k dalšímu dostupnému agentovi na základě předem určené metody směrování. Agenti přijímají oznámení a můžou zpracovávat hovory pomocí ovládacích prvků volání v Teams. Tato funkce nabízí vytváření sestav a analýzy pro sledování výkonu. Zjednodušuje zpracování hovorů, zajišťuje konzistentní uživatelské prostředí a optimalizuje produktivitu agentů. Můžete vybrat existující nebo vytvořit novou frontu volání prostřednictvím Centra pro správu Teams.
Přečtěte si další informace o tom, jak vytvořit frontu volání pomocí Centra pro správu Teams.
Vyhledání ID objektu pro frontu volání
Po vytvoření fronty volání potřebujeme najít korelované ID objektu, abychom ho mohli později použít pro volání. ID objektu je připojené k účtu prostředku připojenému k frontě volání – otevřete kartu Účty zdrojů v Aplikaci Teams Admin a vyhledejte e-mail.
Všechny požadované informace o účtu prostředků najdete v Microsoft Graph Exploreru pomocí tohoto e-mailu ve vyhledávání.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Ve výsledcích budeme moct najít pole ID.
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Abychom mohli v volající aplikaci používat, musíme k tomuto ID přidat předponu. V současné době jsou podporovány následující položky:
- Fronta volání veřejného cloudu:
28:orgid:<id>
- Fronta volání cloudu pro státní správu:
28:gcch:<id>
Požadavky
Získejte účet Azure s aktivním předplatným. Vytvoření účtu zdarma
Mac se systémem Xcode spolu s platným certifikátem vývojáře nainstalovaným do klíčenky.
Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby. Pro účely tohoto rychlého startu musíte zaznamenat připojovací řetězec.
Přístupový token uživatele pro vaši službu Azure Communication Service. K vytvoření uživatele a přístupového tokenu můžete také použít Azure CLI a spustit příkaz se svým připojovací řetězec.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Podrobnosti najdete v tématu Použití Azure CLI k vytváření a správě přístupových tokenů.
Minimální podpora pro aplikace teams volající: 2.15.0
Nastavení
Vytvoření projektu Xcode
V Xcode vytvořte nový projekt pro iOS a vyberte šablonu aplikace . Tento kurz používá architekturu SwiftUI, takže byste měli nastavit jazyk na Swift a uživatelské rozhraní na SwiftUI. Během tohoto rychlého startu nebudete vytvářet testy. Nebojte se zrušit zaškrtnutí políčka Zahrnout testy.
Instalace balíčku a závislostí pomocí CocoaPods
Chcete-li vytvořit podfile pro vaši aplikaci, otevřete terminál a přejděte do složky projektu a spusťte:
pod init
Do souboru Podfile přidejte následující kód a uložte ho (ujistěte se, že cíl odpovídá názvu projektu):
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 2.15.0' end
Spusťte
pod install
.Otevřete soubor
.xcworkspace
xcode.
Vyžádání přístupu k mikrofonu
Pokud chcete získat přístup k mikrofonu zařízení, musíte aktualizovat seznam vlastností informací aplikace pomocí funkce NSMicrophoneUsageDescription
. Nastavíte přidruženou string
hodnotu na hodnotu, která byla zahrnuta v dialogovém okně, který systém používá k vyžádání přístupu od uživatele.
Klikněte pravým tlačítkem myši na Info.plist
položku stromu projektu a vyberte Otevřít jako>zdrojový kód. Přidejte následující řádky oddílu nejvyšší úrovně <dict>
a pak soubor uložte.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Nastavení architektury aplikace
Otevřete soubor ContentView.swift projektu a přidejte import
do horní části souboru deklaraci pro import souboru AzureCommunicationCalling library
. Kromě toho AVFoundation
potřebujeme tento kód pro požadavek na zvukové oprávnění v kódu.
import AzureCommunicationCalling
import AVFoundation
Nahraďte implementaci ContentView
struktury některými jednoduchými ovládacími prvky uživatelského rozhraní, které uživateli umožňují zahájit a ukončit volání. K těmto ovládacím prvkům připojíme obchodní logiku v tomto rychlém startu.
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
}
}
Objektový model
Následující třídy a rozhraní zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Jedná se CallClient o hlavní vstupní bod volající sady SDK. |
CallAgent |
Slouží CallAgent ke spouštění a správě hovorů. |
CommunicationTokenCredential |
Slouží CommunicationTokenCredential jako přihlašovací údaje tokenu k vytvoření instance CallAgent . |
CommunicationUserIdentifier |
Slouží CommunicationUserIdentifier k reprezentaci identity uživatele, což může být jedna z následujících možností: CommunicationUserIdentifier neboPhoneNumberIdentifier CallingApplication. |
Ověření klienta
Inicializace CallAgent
instance pomocí přístupového tokenu uživatele, což nám umožňuje provádět a přijímat volání.
V následujícím kódu je nutné nahradit <USER ACCESS TOKEN>
platným přístupovým tokenem uživatele pro váš prostředek.
Pokud ještě token nemáte k dispozici, projděte si dokumentaci k přístupovým tokenům uživatele.
Do zpětného onAppear
volání v ContentView.swift přidejte následující kód:
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.")
}
}
Zahájení hovoru
Metoda startCall
je nastavena jako akce, která se provádí při klepnutí na tlačítko Zahájit volání . Aktualizujte implementaci tak, aby se spustilo volání pomocí ASACallAgent
příkazu :
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")
}
}
}
}
}
Pomocí vlastností StartCallOptions
můžete také nastavit počáteční možnosti volání (to znamená, že umožňuje zahájit hovor s ztlumeným mikrofonem).
Ukončení hovoru
Implementujte metodu endCall
pro ukončení aktuálního volání při klepnutí na tlačítko Ukončit hovor .
func endCall()
{
self.call!.hangUp(options: HangUpOptions()) { (error) in
if (error != nil) {
print("ERROR: It was not possible to hangup the call.")
}
}
}
Spuštění kódu
Aplikaci můžete sestavit a spustit v simulátoru iOS tak, že vyberete Spuštění produktu>nebo pomocí klávesové zkratky (⌘-R).
Poznámka:
Při prvním volání vás systém vyzve k přístupu k mikrofonu. V produkční aplikaci byste měli použít AVAudioSession
rozhraní API ke kontrole stavu oprávnění a řádné aktualizaci chování aplikace v případě, že oprávnění není uděleno.
Ruční postup nastavení hovoru:
- Spuštění aplikace pomocí Xcode
- Zadejte ID objektu fronty volání (s předponou) a vyberte tlačítko Zahájit hovor. Aplikace spustí odchozí volání do fronty volání s daným ID objektu.
- Volání je připojené k frontě volání.
- Uživatel komunikačních služeb je směrován prostřednictvím fronty volání na základě své konfigurace.
V tomto rychlém startu se dozvíte, jak zahájit volání od uživatele Azure Communication Services do fronty volání Teams. Dosáhnete toho pomocí následujících kroků:
- Povolte federaci prostředku Azure Communication Services s tenantem Teams.
- Vyberte nebo vytvořte frontu volání teams prostřednictvím Centra pro správu Teams.
- Získejte e-mailovou adresu fronty volání prostřednictvím Centra pro správu Teams.
- Získejte ID objektu fronty volání prostřednictvím rozhraní Graph API.
- Začněte volat pomocí sady SDK pro volání služeb Azure Communication Services.
Pokud chcete přeskočit na konec, můžete si tento rychlý start stáhnout jako ukázku na GitHubu.
Povolení interoperability v tenantovi Teams
Uživatel Microsoft Entra s rolí správce Teams může spustit rutinu PowerShellu s modulem MicrosoftTeams a povolit prostředek Komunikační služby v tenantovi.
1. Příprava modulu Microsoft Teams
Nejprve otevřete PowerShell a pomocí následujícího příkazu ověřte existenci modulu Teams:
Get-module *teams*
Pokud modul nevidíte MicrosoftTeams
, nejdřív ho nainstalujte. Pokud chcete nainstalovat modul, musíte spustit PowerShell jako správce. Pak spusťte následující příkaz:
Install-Module -Name MicrosoftTeams
Budete informováni o nainstalovaných modulech, které můžete potvrdit pomocí Y
odpovědi.A
Pokud je modul nainstalovaný, ale je zastaralý, můžete spuštěním následujícího příkazu modul aktualizovat:
Update-Module MicrosoftTeams
2. Připojení k modulu Microsoft Teams
Po instalaci a připravenosti modulu se můžete připojit k modulu MicrosoftTeams pomocí následujícího příkazu. Zobrazí se výzva k přihlášení pomocí interaktivního okna. Uživatelský účet, který budete používat, musí mít oprávnění správce Teams. V opačném případě můžete získat access denied
odpověď v dalších krocích.
Connect-MicrosoftTeams
3. Povolení konfigurace tenanta
Interoperabilita s prostředky komunikačních služeb se řídí prostřednictvím konfigurace tenanta a přiřazených zásad. Tenant Teams má jednu konfiguraci tenanta a uživatelé Teams přiřadili globální zásady nebo vlastní zásady. Další informace najdete v tématu Přiřazení zásad v Teams.
Po úspěšném přihlášení můžete spuštěním rutiny Set-CsTeamsAcsFederationConfiguration povolit prostředek Komunikační služby ve vašem tenantovi. Nahraďte text IMMUTABLE_RESOURCE_ID
neměnným ID prostředku v komunikačním prostředku. Další podrobnosti o tom, jak tyto informace získat, najdete tady.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Povolení zásad tenanta
Každý uživatel Teams přiřadil, External Access Policy
který určuje, jestli uživatelé komunikačních služeb mohou volat tohoto uživatele Teams. Pomocí rutiny Set-CsExternalAccessPolicy zajistěte, aby zásady přiřazené uživateli Teams byly nastaveny EnableAcsFederationAccess
na $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Vytvoření nebo výběr fronty volání v Teams
Fronta hovorů v Teams je funkce v Microsoft Teams, která efektivně distribuuje příchozí hovory mezi skupinu určených uživatelů nebo agentů. Je užitečné pro scénáře zákaznické podpory nebo call centra. Volání se umístí do fronty a přiřadí se k dalšímu dostupnému agentovi na základě předem určené metody směrování. Agenti přijímají oznámení a můžou zpracovávat hovory pomocí ovládacích prvků volání v Teams. Tato funkce nabízí vytváření sestav a analýzy pro sledování výkonu. Zjednodušuje zpracování hovorů, zajišťuje konzistentní uživatelské prostředí a optimalizuje produktivitu agentů. Můžete vybrat existující nebo vytvořit novou frontu volání prostřednictvím Centra pro správu Teams.
Přečtěte si další informace o tom, jak vytvořit frontu volání pomocí Centra pro správu Teams.
Vyhledání ID objektu pro frontu volání
Po vytvoření fronty volání potřebujeme najít korelované ID objektu, abychom ho mohli později použít pro volání. ID objektu je připojené k účtu prostředku připojenému k frontě volání – otevřete kartu Účty zdrojů v Aplikaci Teams Admin a vyhledejte e-mail.
Všechny požadované informace o účtu prostředků najdete v Microsoft Graph Exploreru pomocí tohoto e-mailu ve vyhledávání.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Ve výsledcích budeme moct najít pole ID.
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Abychom mohli v volající aplikaci používat, musíme k tomuto ID přidat předponu. V současné době jsou podporovány následující položky:
- Fronta volání veřejného cloudu:
28:orgid:<id>
- Fronta volání cloudu pro státní správu:
28:gcch:<id>
Požadavky
Pro absolvování tohoto kurzu musí být splněné následující požadavky:
Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
Nainstalujte sadu Visual Studio 2022 s Univerzální platforma Windows úlohou vývoje.
Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby. Pro účely tohoto rychlého startu musíte zaznamenat připojovací řetězec.
Přístupový token uživatele pro vaši službu Azure Communication Service. K vytvoření uživatele a přístupového tokenu můžete také použít Azure CLI a spustit příkaz se svým připojovací řetězec.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Podrobnosti najdete v tématu Použití Azure CLI k vytváření a správě přístupových tokenů.
Minimální podpora pro aplikace teams volající: 1.11.0
Nastavení
Vytvoření projektu
V sadě Visual Studio vytvořte nový projekt pomocí šablony Prázdná aplikace (Univerzální windows) pro nastavení jednostránka Univerzální platforma Windows (UPW).
Nainstalujte balíček .
Vyberte projekt pravým tlačítkem a přejděte na Manage Nuget Packages
instalaci Azure.Communication.Calling.WindowsClient
verze 1.4.0 nebo vyšší. Zkontrolujte, Include Prerelease
jestli je zaškrtnuté, jestli chcete zobrazit verze pro verzi Public Preview.
Vyžádat si přístup
Přejděte na Package.appxmanifest
a vyberte Capabilities
.
Zkontrolujte a Internet (Client & Server)
získejte Internet (Client)
příchozí a odchozí přístup k internetu. Zkontrolujte Microphone
, jestli chcete získat přístup ke zvukovému kanálu mikrofonu a Webcam
získat přístup k videokamerě.
Nastavení architektury aplikace
Potřebujeme nakonfigurovat základní rozložení pro připojení naší logiky. Abychom mohli umístit odchozí hovor, musíme TextBox
zadat ID uživatele volaného. Potřebujeme Start/Join call
také tlačítko a Hang up
tlačítko. Součástí Mute
této ukázky jsou také zaškrtávací políčka, BackgroundBlur
které demonstrují funkce přepínání zvukových stavů a efektů videa.
MainPage.xaml
Otevřete projekt a přidejte uzel Grid
do svéhoPage
:
<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
Otevřete a nahraďte obsah následující implementací:
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
}
}
Objektový model
V další tabulce jsou uvedené třídy a rozhraní, které zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Jedná se CallClient o hlavní vstupní bod volající sady SDK. |
CallAgent |
Slouží CallAgent ke spouštění a správě hovorů. |
CommunicationCall |
Slouží CommunicationCall ke správě probíhajícího hovoru. |
CallTokenCredential |
Slouží CallTokenCredential jako přihlašovací údaje tokenu k vytvoření instance CallAgent . |
CallIdentifier |
Slouží CallIdentifier k reprezentaci identity uživatele, což může být jedna z následujících možností: UserCallIdentifier atd PhoneNumberCallIdentifier . |
Ověření klienta
Inicializace CallAgent
instance pomocí přístupového tokenu uživatele, který nám umožňuje provádět a přijímat volání, a volitelně získat instanci DeviceManager pro dotazování na konfigurace klientských zařízení.
V kódu nahraďte <AUTHENTICATION_TOKEN>
přístupovým tokenem uživatele.
Pokud ještě token nemáte k dispozici, projděte si dokumentaci k přístupovým tokenům uživatele.
Přidejte InitCallAgentAndDeviceManagerAsync
funkci, která spouští sadu SDK. Tento pomocník je možné přizpůsobit tak, aby splňoval požadavky vaší aplikace.
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;
}
Zahájení hovoru
Jakmile se StartCallOptions
objekt získá, CallAgent
můžete ho použít k zahájení volání služby Azure Communication Services:
private async Task<CommunicationCall> StartCallAsync(string acsCallee)
{
var options = new StartCallOptions();
var call = await this.callAgent.StartCallAsync( new [] { new MicrosoftTeamsAppCallIdentifier(acsCallee) }, options);
return call;
}
Ukončení hovoru
Ukončení aktuálního hovoru po kliknutí na Hang up
tlačítko Přidejte implementaci do HangupButton_Click pro ukončení volání a zastavte streamy náhledu a videa.
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 });
}
}
Přepnutí ztlumení nebo zrušení ztlumení zvuku
Po kliknutí na Mute
tlačítko ztlumte odchozí zvuk. Přidejte implementaci do MuteLocal_Click pro ztlumení volání.
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
}
}
Přijetí příchozího hovoru
IncomingCallReceived
Jímka událostí je nastavena v pomocné rutině InitCallAgentAndDeviceManagerAsync
sdk bootstrap .
this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
Aplikace má příležitost ke konfiguraci způsobu přijetí příchozího hovoru, jako jsou druhy video a zvukového streamu.
private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
{
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() { };
call = await incomingCall.AcceptAsync(acceptCallOptions);
call.StateChanged += OnStateChangedAsync;
}
Monitorování a reakce na událost změny stavu volání
StateChanged
událost objektu CommunicationCall
se aktivuje, když probíhající volání transakcí z jednoho stavu do druhého. Aplikace nabízí příležitosti k vyjádření změn stavu v uživatelském rozhraní nebo vložení obchodní logiky.
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;
}
}
}
Make call button work
Callee ID
Jakmile hodnota null nebo není prázdná, můžete zahájit volání.
Stav volání se musí změnit pomocí OnStateChangedAsync
akce.
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;
}
}
Spuštění kódu
Kód můžete sestavit a spustit v sadě Visual Studio. Pro platformy řešení podporujeme ARM64
, x64
a x86
.
Ruční postup nastavení hovoru:
- Spusťte aplikaci pomocí sady Visual Studio.
- Zadejte ID objektu fronty volání (s předponou) a vyberte tlačítko Zahájit hovor. Aplikace spustí odchozí volání do fronty volání s daným ID objektu.
- Volání je připojené k frontě volání.
- Uživatel komunikačních služeb je směrován prostřednictvím fronty volání na základě své konfigurace.
Vyčištění prostředků
Pokud chcete vyčistit a odebrat předplatné služby Communication Services, můžete odstranit prostředek nebo skupinu prostředků. Odstraněním skupiny prostředků se odstraní také všechny ostatní prostředky, které jsou k ní přidružené. Přečtěte si další informace o čištění prostředků.
Další kroky
Další informace najdete v následujících článcích:
- Začínáme s voláním uživatelského rozhraní do hlasových aplikací Teams
- Informace o možnostech volání sady SDK
- Další informace o fungování volání