Mulai Cepat: Bergabung dengan aplikasi panggilan Anda ke Penjawab Otomatis Teams
Dalam mulai cepat ini, Anda akan mempelajari cara memulai panggilan dari pengguna Azure Communication Services ke Teams Auto Attendant. Anda akan mencapainya dengan langkah-langkah berikut:
- Aktifkan federasi sumber daya Azure Communication Services dengan Penyewa Teams.
- Pilih atau buat Penjawab Otomatis Teams melalui Pusat Admin Teams.
- Dapatkan alamat email Penjawab Otomatis melalui Pusat Admin Teams.
- Dapatkan ID Objek penjawab otomatis melalui Graph API.
- Mulai panggilan dengan Azure Communication Services Calling SDK.
Jika Anda ingin melompati ke bagian akhir, Anda dapat mengunduh mulai cepat ini sebagai sampel di GitHub.
Mengaktifkan interoperabilitas di penyewa Teams Anda
Pengguna Microsoft Entra dengan peran administrator Teams dapat menjalankan cmdlet PowerShell dengan modul MicrosoftTeams untuk mengaktifkan sumber daya Communication Services di penyewa.
1. Siapkan modul Microsoft Teams
Pertama, buka PowerShell dan validasi keberadaan modul Teams dengan perintah berikut:
Get-module *teams*
Jika Anda tidak melihat MicrosoftTeams
modul, instal terlebih dahulu. Untuk menginstal modul, Anda perlu menjalankan PowerShell sebagai administrator. Kemudian, jalankan perintah berikut:
Install-Module -Name MicrosoftTeams
Anda akan diberi tahu tentang modul yang akan diinstal, yang dapat Dikonfirmasi dengan Y
jawaban atau A
. Jika modul diinstal tetapi sudah kedaluarsa, Anda dapat menjalankan perintah berikut untuk memperbarui modul:
Update-Module MicrosoftTeams
2. Sambungkan ke modul Microsoft Teams
Ketika modul diinstal dan siap, Anda dapat terhubung ke modul MicrosftTeams dengan perintah berikut. Anda akan diminta dengan jendela interaktif untuk masuk. Akun pengguna yang akan Anda gunakan harus memiliki izin administrator Teams. Jika tidak, Anda mungkin mendapatkan access denied
respons di langkah berikutnya.
Connect-MicrosoftTeams
3. Aktifkan konfigurasi penyewa
Interoperabilitas dengan sumber daya Communication Services dikontrol melalui konfigurasi penyewa dan kebijakan yang ditetapkan. Penyewa Teams memiliki konfigurasi penyewa tunggal, dan pengguna Teams telah menetapkan kebijakan global atau kebijakan kustom. Untuk informasi selengkapnya, lihat Menetapkan Kebijakan di Teams.
Setelah berhasil masuk, Anda dapat menjalankan cmdlet Set-CsTeamsAcsFederationConfiguration untuk mengaktifkan sumber daya Communication Services di penyewa Anda. Ganti teks IMMUTABLE_RESOURCE_ID
dengan ID sumber daya yang tidak dapat diubah di sumber daya komunikasi Anda. Anda dapat menemukan detail selengkapnya tentang cara mendapatkan informasi ini di sini.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktifkan kebijakan penyewa
Setiap pengguna Teams telah menetapkan External Access Policy
yang menentukan apakah pengguna Communication Services dapat memanggil pengguna Teams ini. Gunakan cmdlet Set-CsExternalAccessPolicy untuk memastikan bahwa kebijakan yang ditetapkan ke pengguna Teams telah diatur EnableAcsFederationAccess
ke $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Membuat atau memilih Penjawab Otomatis Teams
Teams Auto Attendant adalah sistem yang menyediakan sistem penanganan panggilan otomatis untuk panggilan masuk. Ini berfungsi sebagai resepsionis virtual, memungkinkan penelepon untuk secara otomatis dirutekan ke orang atau departemen yang sesuai tanpa perlu operator manusia. Anda dapat memilih yang sudah ada atau membuat Penjawab Otomatis baru melalui Pusat Admin Teams.
Pelajari selengkapnya tentang cara membuat Penjawab Otomatis menggunakan Pusat Admin Teams di sini.
Temukan ID Objek untuk Penjawab Otomatis
Setelah Penjawab Otomatis dibuat, kita perlu menemukan ID Objek yang berkorelasi untuk menggunakannya nanti untuk panggilan. ID Objek tersambung ke Akun Sumber Daya yang dilampirkan ke Penjawab Otomatis - buka tab Akun Sumber Daya di Admin Teams dan temukan email akun. Semua informasi yang diperlukan untuk Akun Sumber Daya dapat ditemukan di Microsoft Graph Explorer menggunakan email ini dalam pencarian.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Dalam hasil kita akan dapat menemukan bidang "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Prasyarat
- Dapatkan akun Azure dengan langganan aktif. Buat akun secara gratis.
- Versi Node.js Active LTS dan Maintenance LTS (8.11.1 dan 10.14.1)
- Buat sumber daya Azure Communication Services. Buat sumber daya Azure Communication Services.
Menyiapkan
Membuat aplikasi Node.js baru
Buka terminal atau jendela perintah Anda, buat direktori baru untuk aplikasi Anda, dan navigasikan ke direktori.
mkdir calling-quickstart && cd calling-quickstart
Pasang paket
Gunakan perintah npm install
untuk memasang Azure Communication Services Calling SDK untuk JavaScript.
Penting
Mulai cepat ini menggunakan Azure Communication Services Calling SDK versi next
.
npm install @azure/communication-common@next --save
npm install @azure/communication-calling@next --save
Menyiapkan kerangka kerja aplikasi
Mulai cepat ini menggunakan webpack untuk memaketkan aset aplikasi. Jalankan perintah berikut untuk menginstal paket npm webpack
, webpack-cli
, dan webpack-dev-server
, serta cantumkan sebagai dependensi pengembangan di package.json
Anda:
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
Buat file index.html
di direktori akar proyek Anda. Kami akan menggunakan file ini untuk mengonfigurasi tata letak dasar yang akan memungkinkan pengguna melakukan panggilan video pribadi (1:1).
Berikut kodenya:
<!-- 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>
Model Objek Web SDK Panggilan Azure Communication Services
Kelas dan antarmuka berikut menangani beberapa fitur utama SDK Panggilan Azure Communication Services:
Nama | Deskripsi |
---|---|
CallClient |
Titik masuk utama ke Calling SDK. |
CallAgent |
Digunakan untuk memulai dan mengelola panggilan. |
DeviceManager |
Digunakan untuk mengelola perangkat media. |
Call |
Digunakan untuk mewakili Panggilan. |
LocalVideoStream |
Digunakan untuk membuat aliran video lokal untuk perangkat kamera pada sistem lokal. |
RemoteParticipant |
Digunakan untuk mewakili peserta jarak jauh dalam Panggilan. |
RemoteVideoStream |
Digunakan untuk mewakili aliran video jarak jauh dari Peserta Jarak Jauh. |
Buat file di direktori akar proyek Anda yang bernama client.js
guna memuat logika aplikasi untuk mulai cepat ini. Tambahkan kode berikut ke 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();
});
Menambahkan kode server lokal webpack
Buat file di direktori akar proyek Anda yang disebut webpack.config.js untuk memuat logika server lokal untuk mulai cepat ini. Tambahkan kode berikut ke 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'
]
}),
]
};
Menjalankan kode
Gunakan webpack-dev-server
untuk membuat dan menjalankan aplikasi Anda. Jalankan perintah berikut untuk membundel host aplikasi di webserver lokal:
npx webpack serve --config webpack.config.js
Langkah-langkah manual untuk menyiapkan panggilan:
- Buka browser Anda dan navigasi ke http://localhost:8080/.
- Masukkan token akses pengguna yang valid. Lihat dokumentasi token akses pengguna jika Anda belum memiliki token akses yang tersedia untuk digunakan.
- Klik tombol "Inisialisasi Agen Panggilan".
- Masukkan ID Objek Penjawab Otomatis, dan pilih tombol "Mulai Panggilan". Aplikasi akan memulai panggilan keluar ke Penjawab Otomatis dengan ID objek tertentu.
- Panggilan tersambung ke Penjawab Otomatis.
- Pengguna Communication Services dirutekan melalui Penjawab Otomatis berdasarkan konfigurasinya.
Penting
Fitur Azure Communication Services ini saat ini dalam pratinjau.
API pratinjau dan SDK disediakan tanpa perjanjian tingkat layanan. Kami menyarankan agar Anda tidak menggunakannya untuk beban kerja produksi. Beberapa fitur mungkin tidak didukung, atau mungkin memiliki kemampuan yang dibatasi.
Untuk informasi selengkapnya, tinjau Ketentuan Penggunaan Tambahan untuk Pratinjau Microsoft Azure.
Dalam mulai cepat ini, Anda akan mempelajari cara memulai panggilan dari pengguna Azure Communication Services ke Teams Auto Attendant. Anda akan mencapainya dengan langkah-langkah berikut:
- Aktifkan federasi sumber daya Azure Communication Services dengan Penyewa Teams.
- Pilih atau buat Penjawab Otomatis Teams melalui Pusat Admin Teams.
- Dapatkan alamat email Penjawab Otomatis melalui Pusat Admin Teams.
- Dapatkan ID Objek penjawab otomatis melalui Graph API.
- Mulai panggilan dengan Azure Communication Services Calling SDK.
Jika Anda ingin melompati ke bagian akhir, Anda dapat mengunduh mulai cepat ini sebagai sampel di GitHub.
Mengaktifkan interoperabilitas di penyewa Teams Anda
Pengguna Microsoft Entra dengan peran administrator Teams dapat menjalankan cmdlet PowerShell dengan modul MicrosoftTeams untuk mengaktifkan sumber daya Communication Services di penyewa.
1. Siapkan modul Microsoft Teams
Pertama, buka PowerShell dan validasi keberadaan modul Teams dengan perintah berikut:
Get-module *teams*
Jika Anda tidak melihat MicrosoftTeams
modul, instal terlebih dahulu. Untuk menginstal modul, Anda perlu menjalankan PowerShell sebagai administrator. Kemudian, jalankan perintah berikut:
Install-Module -Name MicrosoftTeams
Anda akan diberi tahu tentang modul yang akan diinstal, yang dapat Dikonfirmasi dengan Y
jawaban atau A
. Jika modul diinstal tetapi sudah kedaluarsa, Anda dapat menjalankan perintah berikut untuk memperbarui modul:
Update-Module MicrosoftTeams
2. Sambungkan ke modul Microsoft Teams
Ketika modul diinstal dan siap, Anda dapat terhubung ke modul MicrosftTeams dengan perintah berikut. Anda akan diminta dengan jendela interaktif untuk masuk. Akun pengguna yang akan Anda gunakan harus memiliki izin administrator Teams. Jika tidak, Anda mungkin mendapatkan access denied
respons di langkah berikutnya.
Connect-MicrosoftTeams
3. Aktifkan konfigurasi penyewa
Interoperabilitas dengan sumber daya Communication Services dikontrol melalui konfigurasi penyewa dan kebijakan yang ditetapkan. Penyewa Teams memiliki konfigurasi penyewa tunggal, dan pengguna Teams telah menetapkan kebijakan global atau kebijakan kustom. Untuk informasi selengkapnya, lihat Menetapkan Kebijakan di Teams.
Setelah berhasil masuk, Anda dapat menjalankan cmdlet Set-CsTeamsAcsFederationConfiguration untuk mengaktifkan sumber daya Communication Services di penyewa Anda. Ganti teks IMMUTABLE_RESOURCE_ID
dengan ID sumber daya yang tidak dapat diubah di sumber daya komunikasi Anda. Anda dapat menemukan detail selengkapnya tentang cara mendapatkan informasi ini di sini.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktifkan kebijakan penyewa
Setiap pengguna Teams telah menetapkan External Access Policy
yang menentukan apakah pengguna Communication Services dapat memanggil pengguna Teams ini. Gunakan cmdlet Set-CsExternalAccessPolicy untuk memastikan bahwa kebijakan yang ditetapkan ke pengguna Teams telah diatur EnableAcsFederationAccess
ke $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Membuat atau memilih Penjawab Otomatis Teams
Teams Auto Attendant adalah sistem yang menyediakan sistem penanganan panggilan otomatis untuk panggilan masuk. Ini berfungsi sebagai resepsionis virtual, memungkinkan penelepon untuk secara otomatis dirutekan ke orang atau departemen yang sesuai tanpa perlu operator manusia. Anda dapat memilih yang sudah ada atau membuat Penjawab Otomatis baru melalui Pusat Admin Teams.
Pelajari selengkapnya tentang cara membuat Penjawab Otomatis menggunakan Pusat Admin Teams di sini.
Temukan ID Objek untuk Penjawab Otomatis
Setelah Penjawab Otomatis dibuat, kita perlu menemukan ID Objek yang berkorelasi untuk menggunakannya nanti untuk panggilan. ID Objek tersambung ke Akun Sumber Daya yang dilampirkan ke Penjawab Otomatis - buka tab Akun Sumber Daya di Admin Teams dan temukan email akun. Semua informasi yang diperlukan untuk Akun Sumber Daya dapat ditemukan di Microsoft Graph Explorer menggunakan email ini dalam pencarian.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Dalam hasil kita akan dapat menemukan bidang "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Untuk digunakan dalam Aplikasi panggilan, kita perlu menambahkan awalan ke ID ini. Saat ini, berikut ini didukung:
- Penjawab Otomatis cloud publik:
28:orgid:<id>
- Penjawab Otomatis cloud pemerintah:
28:gcch:<id>
Prasyarat
Akun Azure dengan langganan aktif. Buat akun secara gratis.
Android Studio, untuk membuat aplikasi Android Anda.
Sumber daya Communication Services yang disebarkan. Buat sumber daya Azure Communication Services.
Token Akses Pengguna untuk Azure Communication Service. Anda juga dapat menggunakan Azure CLI dan menjalankan perintah dengan string koneksi Anda untuk membuat pengguna dan token akses.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Untuk detailnya, lihat Menggunakan Azure CLI untuk Membuat dan Mengelola Token Akses.
Dukungan minimum untuk aplikasi panggilan Teams: 2.12.0-beta.1
Menyiapkan
Membuat aplikasi Android dengan aktivitas kosong
Dari Android Studio, pilih Mulai proyek Android Studio baru.
Pilih templat proyek "Aktivitas Tampilan Kosong" di bagian "Telepon dan Tablet".
Pilih SDK Minimum "API 26: Android 8.0 (Oreo)" atau yang lebih tinggi.
Pasang paket
Temukan proyek settings.gradle.kts
Anda dan pastikan untuk melihat mavenCentral()
daftar repositori di bawah pluginManagement
dan dependencyResolutionManagement
pluginManagement {
repositories {
...
mavenCentral()
...
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
...
mavenCentral()
}
}
Kemudian, di build.gradle tingkat modul Anda, tambahkan baris berikut ke dependensi dan bagian android
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
implementation ("com.azure.android:azure-communication-calling:2.6.0")
...
}
Menambahkan izin ke manifes aplikasi
Untuk meminta izin yang diperlukan untuk melakukan panggilan, mereka harus dideklarasikan dalam Manifes Aplikasi (app/src/main/AndroidManifest.xml
). Ganti konten file dengan kode berikut:
<?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>
Menyiapkan tata letak untuk aplikasi
Dua input diperlukan: input teks untuk ID penerima panggilan, dan tombol untuk melakukan panggilan. Input ini dapat ditambahkan melalui perancang atau dengan mengedit xml tata letak. Buat tombol dengan ID call_button
dan input teks callee_id
. Navigasi ke (app/src/main/res/layout/activity_main.xml
) dan ganti konten file dengan kode berikut:
<?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>
Membuat perancah dan pengikatan aktivitas utama
Dengan tata letak yang sudah dibuat, pengikatan beserta perancah dasar aktivitas dapat ditambahkan. Aktivitas menangani permintaan izin runtime, membuat agen panggilan, dan melakukan panggilan saat tombol ditekan. Metode onCreate
ini ditimpa untuk memanggil getAllPermissions
dan createAgent
dan menambahkan pengikatan untuk tombol panggilan. Peristiwa ini hanya terjadi sekali ketika aktivitas dibuat. Untuk informasi selengkapnya, pada onCreate
, lihat panduan Memahami Siklus Hidup Aktivitas.
Buka MainActivity.java dan ganti konten dengan kode berikut:
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));
}
}
Meminta izin saat runtime
Untuk Android 6.0 dan yang lebih tinggi (API level 23) dan targetSdkVersion
23 atau yang lebih tinggi, izin diberikan saat runtime, bukan saat aplikasi diinstal. Untuk mendukungnya, getAllPermissions
dapat diimplementasikan untuk memanggil ActivityCompat.checkSelfPermission
dan ActivityCompat.requestPermissions
untuk setiap izin yang diperlukan.
/**
* 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);
}
}
Catatan
Saat merancang aplikasi Anda, pertimbangkan kapan izin ini harus diminta. Izin harus diminta saat dibutuhkan, bukan sebelumnya. Untuk informasi selengkapnya, lihat, Panduan Izin Android.
Model objek
Kelas dan antarmuka berikut menghandel beberapa fitur utama Azure Communication Services Calling SDK:
Nama | Deskripsi |
---|---|
CallClient |
CallClient adalah titik masuk utama ke SDK Panggilan. |
CallAgent |
CallAgent digunakan untuk memulai dan mengelola panggilan. |
CommunicationTokenCredential |
CommunicationTokenCredential digunakan sebagai kredensial token untuk membuat instans CallAgent . |
CommunicationIdentifier |
CommunicationIdentifier digunakan sebagai jenis peserta yang berbeda yang dapat menjadi bagian dari panggilan. |
Membuat agen dari token akses pengguna
Dengan token pengguna, agen panggilan terautentikasi dapat diinstansiasi. Umumnya token ini dihasilkan dari layanan dengan autentikasi khusus untuk aplikasi. Untuk informasi selengkapnya tentang token akses pengguna, periksa panduan Token Akses Pengguna.
Untuk mulai cepat, ganti <User_Access_Token>
dengan token akses pengguna yang dihasilkan untuk sumber daya Azure Communication Service Anda.
/**
* 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();
}
}
Menjalankan kode
Aplikasi sekarang dapat diluncurkan menggunakan tombol "Jalankan Aplikasi" pada toolbar.
Langkah-langkah manual untuk menyiapkan panggilan:
- Luncurkan aplikasi menggunakan Android Studio.
- Masukkan ID Objek Penjawab Otomatis (dengan awalan), dan pilih tombol "Mulai Panggilan". Aplikasi akan memulai panggilan keluar ke Penjawab Otomatis dengan ID objek tertentu.
- Panggilan tersambung ke Penjawab Otomatis.
- Pengguna Communication Services dirutekan melalui Penjawab Otomatis berdasarkan konfigurasinya.
Penting
Fitur Azure Communication Services ini saat ini dalam pratinjau.
API pratinjau dan SDK disediakan tanpa perjanjian tingkat layanan. Kami menyarankan agar Anda tidak menggunakannya untuk beban kerja produksi. Beberapa fitur mungkin tidak didukung, atau mungkin memiliki kemampuan yang dibatasi.
Untuk informasi selengkapnya, tinjau Ketentuan Penggunaan Tambahan untuk Pratinjau Microsoft Azure.
Dalam mulai cepat ini, Anda akan mempelajari cara memulai panggilan dari pengguna Azure Communication Services ke Teams Auto Attendant. Anda akan mencapainya dengan langkah-langkah berikut:
- Aktifkan federasi sumber daya Azure Communication Services dengan Penyewa Teams.
- Pilih atau buat Penjawab Otomatis Teams melalui Pusat Admin Teams.
- Dapatkan alamat email Penjawab Otomatis melalui Pusat Admin Teams.
- Dapatkan ID Objek penjawab otomatis melalui Graph API.
- Mulai panggilan dengan Azure Communication Services Calling SDK.
Jika Anda ingin melompati ke bagian akhir, Anda dapat mengunduh mulai cepat ini sebagai sampel di GitHub.
Mengaktifkan interoperabilitas di penyewa Teams Anda
Pengguna Microsoft Entra dengan peran administrator Teams dapat menjalankan cmdlet PowerShell dengan modul MicrosoftTeams untuk mengaktifkan sumber daya Communication Services di penyewa.
1. Siapkan modul Microsoft Teams
Pertama, buka PowerShell dan validasi keberadaan modul Teams dengan perintah berikut:
Get-module *teams*
Jika Anda tidak melihat MicrosoftTeams
modul, instal terlebih dahulu. Untuk menginstal modul, Anda perlu menjalankan PowerShell sebagai administrator. Kemudian, jalankan perintah berikut:
Install-Module -Name MicrosoftTeams
Anda akan diberi tahu tentang modul yang akan diinstal, yang dapat Dikonfirmasi dengan Y
jawaban atau A
. Jika modul diinstal tetapi sudah kedaluarsa, Anda dapat menjalankan perintah berikut untuk memperbarui modul:
Update-Module MicrosoftTeams
2. Sambungkan ke modul Microsoft Teams
Ketika modul diinstal dan siap, Anda dapat terhubung ke modul MicrosftTeams dengan perintah berikut. Anda akan diminta dengan jendela interaktif untuk masuk. Akun pengguna yang akan Anda gunakan harus memiliki izin administrator Teams. Jika tidak, Anda mungkin mendapatkan access denied
respons di langkah berikutnya.
Connect-MicrosoftTeams
3. Aktifkan konfigurasi penyewa
Interoperabilitas dengan sumber daya Communication Services dikontrol melalui konfigurasi penyewa dan kebijakan yang ditetapkan. Penyewa Teams memiliki konfigurasi penyewa tunggal, dan pengguna Teams telah menetapkan kebijakan global atau kebijakan kustom. Untuk informasi selengkapnya, lihat Menetapkan Kebijakan di Teams.
Setelah berhasil masuk, Anda dapat menjalankan cmdlet Set-CsTeamsAcsFederationConfiguration untuk mengaktifkan sumber daya Communication Services di penyewa Anda. Ganti teks IMMUTABLE_RESOURCE_ID
dengan ID sumber daya yang tidak dapat diubah di sumber daya komunikasi Anda. Anda dapat menemukan detail selengkapnya tentang cara mendapatkan informasi ini di sini.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktifkan kebijakan penyewa
Setiap pengguna Teams telah menetapkan External Access Policy
yang menentukan apakah pengguna Communication Services dapat memanggil pengguna Teams ini. Gunakan cmdlet Set-CsExternalAccessPolicy untuk memastikan bahwa kebijakan yang ditetapkan ke pengguna Teams telah diatur EnableAcsFederationAccess
ke $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Membuat atau memilih Penjawab Otomatis Teams
Teams Auto Attendant adalah sistem yang menyediakan sistem penanganan panggilan otomatis untuk panggilan masuk. Ini berfungsi sebagai resepsionis virtual, memungkinkan penelepon untuk secara otomatis dirutekan ke orang atau departemen yang sesuai tanpa perlu operator manusia. Anda dapat memilih yang sudah ada atau membuat Penjawab Otomatis baru melalui Pusat Admin Teams.
Pelajari selengkapnya tentang cara membuat Penjawab Otomatis menggunakan Pusat Admin Teams di sini.
Temukan ID Objek untuk Penjawab Otomatis
Setelah Penjawab Otomatis dibuat, kita perlu menemukan ID Objek yang berkorelasi untuk menggunakannya nanti untuk panggilan. ID Objek tersambung ke Akun Sumber Daya yang dilampirkan ke Penjawab Otomatis - buka tab Akun Sumber Daya di Admin Teams dan temukan email akun. Semua informasi yang diperlukan untuk Akun Sumber Daya dapat ditemukan di Microsoft Graph Explorer menggunakan email ini dalam pencarian.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Dalam hasil kita akan dapat menemukan bidang "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Untuk digunakan dalam Aplikasi panggilan, kita perlu menambahkan awalan ke ID ini. Saat ini, berikut ini didukung:
- Penjawab Otomatis cloud publik:
28:orgid:<id>
- Penjawab Otomatis cloud pemerintah:
28:gcch:<id>
Prasyarat
Dapatkan akun Azure dengan langganan aktif. Buat akun secara gratis.
Mac yang menjalankan Xcode, bersama dengan sertifikat pengembang valid yang diinstal ke rantai kunci Anda.
Sumber daya Communication Services yang disebarkan. Buat sumber daya Azure Communication Services. Anda perlu merekam string koneksi Anda untuk mulai cepat ini.
Token Akses Pengguna untuk Azure Communication Service. Anda juga dapat menggunakan Azure CLI dan menjalankan perintah dengan string koneksi Anda untuk membuat pengguna dan token akses.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Untuk detailnya, lihat Menggunakan Azure CLI untuk Membuat dan Mengelola Token Akses.
Dukungan minimum untuk aplikasi panggilan Teams: 2.14.0-beta.1
Menyiapkan
Membuat proyek Xcode
Di Xcode, buat proyek iOS baru dan pilih templat Aplikasi. Tutorial ini menggunakan kerangka kerja SwiftUI, jadi Anda harus mengatur Bahasa ke Swift dan Antarmuka Pengguna ke SwiftUI. Anda tidak akan membuat tes selama mulai cepat ini. Jangan ragu untuk menghapus centang Sertakan Pengujian.
Memasang paket dan dependensi dengan CocoaPods
Untuk membuat Podfile untuk aplikasi Anda, buka terminal dan navigasikan ke folder proyek dan jalankan:
pod init
Tambahkan kode berikut ke Podfile dan simpan (pastikan "target" cocok dengan nama proyek Anda):
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 2.14.0-beta.1' end
Jalankan
pod install
.Buka
.xcworkspace
dengan Xcode.
Minta akses ke mikrofon
Untuk mengakses mikrofon perangkat, Anda perlu memperbarui Daftar Properti Informasi aplikasi Anda dengan NSMicrophoneUsageDescription
. Anda mengatur nilai terkait ke string
yang disertakan dalam dialog yang digunakan sistem untuk meminta akses dari pengguna.
Klik kanan Info.plist
entri pohon proyek dan pilih Buka Sebagai>Kode Sumber. Tambahkan baris berikut ke bagian <dict>
tingkat atas, lalu simpan file.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Menyiapkan kerangka kerja aplikasi
Buka file ContentView.swift proyek Anda dan tambahkan deklarasi import
ke bagian atas file untuk mengimpor AzureCommunicationCalling library
. Selain itu, impor AVFoundation
, kita memerlukan kode ini untuk permintaan izin audio dalam kode.
import AzureCommunicationCalling
import AVFoundation
Ganti implementasi struct ContentView
dengan beberapa kontrol antarmuka pengguna sederhana yang memungkinkan pengguna memulai dan mengakhiri panggilan. Kami melampirkan logika bisnis ke kontrol ini dalam mulai cepat ini.
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
}
}
Model objek
Kelas dan antarmuka berikut menghandel beberapa fitur utama Azure Communication Services Calling SDK:
Nama | Deskripsi |
---|---|
CallClient |
CallClient adalah titik masuk utama ke SDK Panggilan. |
CallAgent |
CallAgent digunakan untuk memulai dan mengelola panggilan. |
CommunicationTokenCredential |
CommunicationTokenCredential digunakan sebagai kredensial token untuk membuat instans CallAgent . |
CommunicationUserIdentifier |
CommunicationUserIdentifier digunakan untuk mewakili identitas pengguna, yang dapat menjadi salah satu opsi berikut: CommunicationUserIdentifier ,PhoneNumberIdentifier atauCallingApplication. |
Mengautentikasi klien
Menginisialisasi CallAgent
instans dengan Token Akses Pengguna, yang memungkinkan kami melakukan dan menerima panggilan.
Dalam kode berikut, Anda perlu mengganti <USER ACCESS TOKEN>
dengan token akses pengguna yang valid untuk sumber daya Anda. Lihat dokumentasi token akses pengguna jika Anda belum memiliki token yang tersedia.
Tambahkan kode berikut ke panggilan balik onAppear
di 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.")
}
}
Memulai panggilan
Metode startCall
ini diatur sebagai tindakan yang dilakukan saat tombol Mulai Panggilan diketuk. Perbarui implementasi untuk memulai panggilan dengan 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")
}
}
}
}
}
Anda juga dapat menggunakan properti di StartCallOptions
untuk mengatur opsi awal untuk panggilan (yaitu, memungkinkan memulai panggilan dengan mikrofon dibisukan).
Mengakhiri panggilan
Terapkan metode endCall
untuk mengakhiri panggilan saat ini saat tombol Akhiri Panggilan diketuk.
func endCall()
{
self.call!.hangUp(options: HangUpOptions()) { (error) in
if (error != nil) {
print("ERROR: It was not possible to hangup the call.")
}
}
}
Menjalankan kode
Anda dapat membuat dan menjalankan aplikasi di simulator iOS dengan memilih Eksekusi Produk>atau dengan menggunakan pintasan keyboard (⌘-R).
Catatan
Saat Anda melakukan panggilan untuk pertama kalinya, sistem akan meminta akses ke mikrofon kepada Anda. Dalam aplikasi produksi, Anda harus menggunakan API AVAudioSession
untuk memeriksa status izin dan memperbarui perilaku aplikasi dengan baik saat izin tidak diberikan.
Langkah-langkah manual untuk menyiapkan panggilan:
- Luncurkan aplikasi menggunakan Xcode
- Masukkan ID Objek Penjawab Otomatis (dengan awalan), dan pilih tombol "Mulai Panggilan". Aplikasi akan memulai panggilan keluar ke Penjawab Otomatis dengan ID objek tertentu.
- Panggilan tersambung ke Penjawab Otomatis.
- Pengguna Communication Services dirutekan melalui Penjawab Otomatis berdasarkan konfigurasinya.
Penting
Fitur Azure Communication Services ini saat ini dalam pratinjau.
API pratinjau dan SDK disediakan tanpa perjanjian tingkat layanan. Kami menyarankan agar Anda tidak menggunakannya untuk beban kerja produksi. Beberapa fitur mungkin tidak didukung, atau mungkin memiliki kemampuan yang dibatasi.
Untuk informasi selengkapnya, tinjau Ketentuan Penggunaan Tambahan untuk Pratinjau Microsoft Azure.
Dalam mulai cepat ini, Anda akan mempelajari cara memulai panggilan dari pengguna Azure Communication Services ke Teams Auto Attendant. Anda akan mencapainya dengan langkah-langkah berikut:
- Aktifkan federasi sumber daya Azure Communication Services dengan Penyewa Teams.
- Pilih atau buat Penjawab Otomatis Teams melalui Pusat Admin Teams.
- Dapatkan alamat email Penjawab Otomatis melalui Pusat Admin Teams.
- Dapatkan ID Objek penjawab otomatis melalui Graph API.
- Mulai panggilan dengan Azure Communication Services Calling SDK.
Jika Anda ingin melompati ke bagian akhir, Anda dapat mengunduh mulai cepat ini sebagai sampel di GitHub.
Mengaktifkan interoperabilitas di penyewa Teams Anda
Pengguna Microsoft Entra dengan peran administrator Teams dapat menjalankan cmdlet PowerShell dengan modul MicrosoftTeams untuk mengaktifkan sumber daya Communication Services di penyewa.
1. Siapkan modul Microsoft Teams
Pertama, buka PowerShell dan validasi keberadaan modul Teams dengan perintah berikut:
Get-module *teams*
Jika Anda tidak melihat MicrosoftTeams
modul, instal terlebih dahulu. Untuk menginstal modul, Anda perlu menjalankan PowerShell sebagai administrator. Kemudian, jalankan perintah berikut:
Install-Module -Name MicrosoftTeams
Anda akan diberi tahu tentang modul yang akan diinstal, yang dapat Dikonfirmasi dengan Y
jawaban atau A
. Jika modul diinstal tetapi sudah kedaluarsa, Anda dapat menjalankan perintah berikut untuk memperbarui modul:
Update-Module MicrosoftTeams
2. Sambungkan ke modul Microsoft Teams
Ketika modul diinstal dan siap, Anda dapat terhubung ke modul MicrosftTeams dengan perintah berikut. Anda akan diminta dengan jendela interaktif untuk masuk. Akun pengguna yang akan Anda gunakan harus memiliki izin administrator Teams. Jika tidak, Anda mungkin mendapatkan access denied
respons di langkah berikutnya.
Connect-MicrosoftTeams
3. Aktifkan konfigurasi penyewa
Interoperabilitas dengan sumber daya Communication Services dikontrol melalui konfigurasi penyewa dan kebijakan yang ditetapkan. Penyewa Teams memiliki konfigurasi penyewa tunggal, dan pengguna Teams telah menetapkan kebijakan global atau kebijakan kustom. Untuk informasi selengkapnya, lihat Menetapkan Kebijakan di Teams.
Setelah berhasil masuk, Anda dapat menjalankan cmdlet Set-CsTeamsAcsFederationConfiguration untuk mengaktifkan sumber daya Communication Services di penyewa Anda. Ganti teks IMMUTABLE_RESOURCE_ID
dengan ID sumber daya yang tidak dapat diubah di sumber daya komunikasi Anda. Anda dapat menemukan detail selengkapnya tentang cara mendapatkan informasi ini di sini.
$allowlist = @('IMMUTABLE_RESOURCE_ID')
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $True -AllowedAcsResources $allowlist
4. Aktifkan kebijakan penyewa
Setiap pengguna Teams telah menetapkan External Access Policy
yang menentukan apakah pengguna Communication Services dapat memanggil pengguna Teams ini. Gunakan cmdlet Set-CsExternalAccessPolicy untuk memastikan bahwa kebijakan yang ditetapkan ke pengguna Teams telah diatur EnableAcsFederationAccess
ke $true
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
Membuat atau memilih Penjawab Otomatis Teams
Teams Auto Attendant adalah sistem yang menyediakan sistem penanganan panggilan otomatis untuk panggilan masuk. Ini berfungsi sebagai resepsionis virtual, memungkinkan penelepon untuk secara otomatis dirutekan ke orang atau departemen yang sesuai tanpa perlu operator manusia. Anda dapat memilih yang sudah ada atau membuat Penjawab Otomatis baru melalui Pusat Admin Teams.
Pelajari selengkapnya tentang cara membuat Penjawab Otomatis menggunakan Pusat Admin Teams di sini.
Temukan ID Objek untuk Penjawab Otomatis
Setelah Penjawab Otomatis dibuat, kita perlu menemukan ID Objek yang berkorelasi untuk menggunakannya nanti untuk panggilan. ID Objek tersambung ke Akun Sumber Daya yang dilampirkan ke Penjawab Otomatis - buka tab Akun Sumber Daya di Admin Teams dan temukan email akun. Semua informasi yang diperlukan untuk Akun Sumber Daya dapat ditemukan di Microsoft Graph Explorer menggunakan email ini dalam pencarian.
https://graph.microsoft.com/v1.0/users/lab-test2-cq-@contoso.com
Dalam hasil kita akan dapat menemukan bidang "ID"
"userPrincipalName": "lab-test2-cq@contoso.com",
"id": "31a011c2-2672-4dd0-b6f9-9334ef4999db"
Untuk digunakan dalam Aplikasi panggilan, kita perlu menambahkan awalan ke ID ini. Saat ini, berikut ini didukung:
- Penjawab Otomatis cloud publik:
28:orgid:<id>
- Penjawab Otomatis cloud pemerintah:
28:gcch:<id>
Prasyarat
Untuk menyelesaikan tutorial ini, Anda memerlukan prasyarat berikut:
Akun Azure dengan langganan aktif. Buat akun secara gratis.
Instal Visual Studio 2022 dengan beban kerja pengembangan Platform Windows Universal.
Sumber daya Communication Services yang disebarkan. Buat sumber daya Azure Communication Services. Anda perlu merekam string koneksi Anda untuk mulai cepat ini.
Token Akses Pengguna untuk Azure Communication Service. Anda juga dapat menggunakan Azure CLI dan menjalankan perintah dengan string koneksi Anda untuk membuat pengguna dan token akses.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Untuk detailnya, lihat Menggunakan Azure CLI untuk Membuat dan Mengelola Token Akses.
Dukungan minimum untuk aplikasi panggilan Teams: 1.10.0-beta.1
Menyiapkan
Membuat proyek
Di Visual Studio, buat proyek baru dengan templat Blank App (Universal Windows) untuk menyiapkan aplikasi Universal Windows Platform (UWP) satu halaman.
Pasang paket
Pilih kanan proyek Anda dan buka Manage Nuget Packages
untuk menginstal Azure.Communication.Calling.WindowsClient
1.4.0 atau lebih unggul. Pastikan Include Prerelease
dicentang jika Anda ingin melihat versi untuk pratinjau publik.
Meminta akses
Package.appxmanifest
Buka dan pilih Capabilities
.
Periksa Internet (Client)
dan Internet (Client & Server)
untuk mendapatkan akses masuk dan keluar ke Internet. Periksa Microphone
untuk mengakses umpan audio mikrofon, dan Webcam
untuk mengakses umpan video kamera.
Menyiapkan kerangka kerja aplikasi
Kita perlu mengonfigurasi tata letak dasar untuk melampirkan logika. Untuk melakukan panggilan keluar, kita perlu TextBox
memberikan ID Pengguna dari penerima panggilan. Kita juga butuh tombol Start/Join call
dan tombol Hang up
. Mute
Kotak centang dan BackgroundBlur
juga disertakan dalam sampel ini untuk menunjukkan fitur mengubah status audio dan efek video.
Buka MainPage.xaml
proyek Anda dan tambahkan node Grid
ke 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>
Buka MainPage.xaml.cs
dan ganti konten dengan implementasi berikut:
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
}
}
Model objek
Tabel berikutnya mencantumkan kelas dan antarmuka menangani beberapa fitur utama SDK Panggilan Azure Communication Services:
Nama | Deskripsi |
---|---|
CallClient |
CallClient adalah titik masuk utama ke SDK Panggilan. |
CallAgent |
CallAgent digunakan untuk memulai dan mengelola panggilan. |
CommunicationCall |
CommunicationCall digunakan untuk mengelola panggilan yang sedang berlangsung. |
CallTokenCredential |
CallTokenCredential digunakan sebagai kredensial token untuk membuat instans CallAgent . |
CallIdentifier |
CallIdentifier digunakan untuk mewakili identitas pengguna, yang dapat menjadi salah satu opsi berikut: UserCallIdentifier , PhoneNumberCallIdentifier dll. |
Mengautentikasi klien
Menginisialisasi CallAgent
instans dengan Token Akses Pengguna yang memungkinkan kami melakukan dan menerima panggilan, dan secara opsional mendapatkan instans DeviceManager untuk mengkueri konfigurasi perangkat klien.
Dalam kode, ganti <AUTHENTICATION_TOKEN>
dengan Token Akses Pengguna. Lihat dokumentasi token akses pengguna jika Anda belum memiliki token yang tersedia.
Tambahkan InitCallAgentAndDeviceManagerAsync
fungsi, yang mem-bootstrap SDK. Pembantu ini dapat disesuaikan untuk memenuhi persyaratan aplikasi Anda.
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;
}
Memulai panggilan
StartCallOptions
Setelah objek diperoleh, CallAgent
dapat digunakan untuk memulai panggilan 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;
}
Mengakhiri panggilan
Akhiri panggilan saat ini ketika tombol Hang up
diklik. Tambahkan implementasi ke HangupButton_Click untuk mengakhiri panggilan, dan hentikan pratinjau dan streaming video.
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 });
}
}
Matikan suara/nyalakan suara pada audio
Matikan suara audio keluar saat tombol Mute
diklik. Tambahkan implementasi ke MuteLocal_Click untuk mematikan suara panggilan.
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
}
}
Menerima panggilan masuk
IncomingCallReceived
sink peristiwa disiapkan di pembantu bootstrap InitCallAgentAndDeviceManagerAsync
SDK .
this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
Aplikasi memiliki kesempatan untuk mengonfigurasi bagaimana panggilan masuk harus diterima, seperti jenis streaming video dan audio.
private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
{
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() { };
call = await incomingCall.AcceptAsync(acceptCallOptions);
call.StateChanged += OnStateChangedAsync;
}
Memantau dan merespons peristiwa perubahan status panggilan
StateChanged
peristiwa pada CommunicationCall
objek diaktifkan ketika transaksi panggilan yang sedang berlangsung dari satu status ke status lainnya. Aplikasi ditawarkan peluang untuk mencerminkan perubahan status pada UI atau menyisipkan logika bisnis.
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;
}
}
}
Membuat tombol panggilan berfungsi
Callee ID
Setelah tidak null atau kosong, Anda dapat memulai panggilan.
Status panggilan harus diubah menggunakan OnStateChangedAsync
tindakan .
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;
}
}
Menjalankan kode
Anda dapat membangun dan menjalankan kode di Visual Studio. Untuk platform solusi, kami mendukung ARM64
, x64
, dan x86
.
Langkah-langkah manual untuk menyiapkan panggilan:
- Luncurkan aplikasi menggunakan Visual Studio.
- Masukkan ID Objek Penjawab Otomatis (dengan awalan), dan pilih tombol "Mulai Panggilan". Aplikasi akan memulai panggilan keluar ke Penjawab Otomatis dengan ID objek tertentu.
- Panggilan tersambung ke Penjawab Otomatis.
- Pengguna Communication Services dirutekan melalui Penjawab Otomatis berdasarkan konfigurasinya.
Membersihkan sumber daya
Jika ingin membersihkan dan menghapus langganan Azure Communication Services, Anda bisa menghapus sumber daya atau grup sumber daya. Menghapus grup sumber daya juga menghapus sumber daya apa pun yang terkait dengannya. Pelajari selengkapnya tentang membersihkan sumber daya.
Langkah berikutnya
Untuk informasi lebih lanjut, baca artikel berikut:
- Mulai menggunakan Panggilan UI ke Aplikasi Suara Teams
- Pelajari kemampuan SDK Panggilan
- Pelajari lebih lanjut cara kerja panggilan