推播通知會將應用程式的信息傳送至使用者的裝置。 您可以使用推播通知來顯示對話框、播放音效,或在應用程式的 UI 層上顯示來電通知。
在本文中,您將瞭解如何啟用 Azure 通訊服務 通話的推播通知。 通訊服務提供與 Azure 事件方格 與 Azure 通知中樞的整合,可讓您將推播通知新增至您的應用程式。
TTL 令牌概觀
存留時間 (TTL) 令牌是一項設定,可決定通知令牌在變成無效之前保持有效的時間長度。 此設定對於用戶參與不需要日常互動但在較長時期內仍然至關重要的應用程式非常實用。
TTL 設定允許管理推播通知的生命週期。 這可減少頻繁更新令牌的需求,同時協助確保應用程式與其使用者之間的通道在延長期間保持開放且可靠。
目前,TTL 的最大值為180天(15,552,000秒),最小值為5分鐘(300秒)。 您可以輸入此值並加以調整,以符合您的需求。 如果不提供值,則預設值為 [24 小時 (86,400 秒)]。
呼叫註冊推播通知 API 之後,裝置令牌資訊會儲存在註冊機構中。 TTL 持續時間結束后,裝置端點資訊會被刪除。 如果這些裝置未再次呼叫註冊推播通知 API,則這些裝置上的任何連入呼叫都無法傳遞至裝置。
如果您想要撤銷身分識別,請遵循 此程式。 撤銷身分識別之後,應該刪除登記條目。
注意事項
對於Microsoft Teams 使用者,最大 TTL 值為 24 小時(86,400 秒)。 沒有可新增此值的方法。 您應該每24小時定時在背景中喚醒應用程式,並完成裝置令牌註冊程序。
必要條件
具有有效訂用帳戶的 Azure 帳戶。 免費建立帳戶。
已部署的通訊服務資源。 建立通訊服務資源。
用來啟用通話用戶端的使用者存取權杖。 如需詳細資訊,請參閱建立和管理存取權杖。
選擇性:完成快速入門以將語音通話新增至您的應用程式。
遵循快速入門
透過 Azure 通訊服務 Web 通話 SDK 的 Web 推播通知處於預覽狀態,並可在 1.12.0-beta.2+ 版中取得。
重要
此 Azure 通訊服務功能目前處於預覽狀態。 預覽中的功能可供公開使用,而且可供所有新的和現有的Microsoft客戶使用。
提供的預覽 API 和 SDK 並無服務等級協定。 建議您不要將其用於生產工作負載。 某些功能可能不受支援,或功能可能會受到限制。
如需詳細資訊,請參閱 Microsoft Azure 預覽版增補使用條款。
如需逐步指示,請參閱 GitHub 上的快速入門。
啟用了 Firebase 雲端通訊(FCM)功能的 Firebase 帳戶,其 FCM 服務已連接到一個 Azure 通知中心實例。 如需詳細資訊,請參閱通訊服務通知。
Android Studio 3.6 版或更新版本可建置您的應用程式。
一組許可權,可讓Android應用程式接收來自 FCM 的通知訊息。 在您的
AndroidManifest.xml
檔案中,於標籤後面<manifest ...>
或下方</application>
新增下列許可權:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
重要
2023 年 6 月 20 日,Google 宣佈已 淘汰使用 FCM 舊版 API 來傳送訊息,並將於 2024 年 6 月開始從服務中移除舊版 FCM。 Google 建議 [從舊版 FCM API 移轉至 FCM HTTP v1]。
如果您的通訊服務資源仍在使用 FCM 舊版 API,請遵循 此移轉指南。
行動推播通知的考量
行動推播通知是出現在行動裝置上的快顯通知。 針對通話,本文著重於 voice over Internet Protocol (VoIP) 推播通知。
注意事項
當應用程式註冊推播通知並處理 Teams 使用者的傳入推播通知時,API 會相同。 本文描述的 API 也可以在 CommonCallAgent
或 TeamsCallAgent
類別上叫用。
安裝 SDK
找出專案層級 build.gradle
檔案,並將 mavenCentral()
新增至 buildscript
和 allprojects
下的存放庫清單:
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
然後,在您的模組層級 build.gradle
檔案中,將下列幾行新增至 dependencies
區段:
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
初始化必要的物件
若要建立 CallAgent
執行個體,您必須在 createCallAgent
執行個體上呼叫 CallClient
方法。 此通話會以非同步方式傳回 CallAgent
執行個體物件。
createCallAgent
方法會採用 CommunicationUserCredential
作為引數,用來封裝存取權杖。
若要存取 DeviceManager
,您必須先建立 callAgent
執行個體。 然後,您可以使用 CallClient.getDeviceManager
方法取得 DeviceManager
。
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential).get();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
若要設定來電者的顯示名稱,請使用下列替代方法:
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisplayName("Alice Bob");
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential, callAgentOptions).get();
註冊推播通知
若要註冊推播通知,應用程式必須使用裝置註冊權杖在 registerPushNotification()
執行個體上呼叫 CallAgent
。
若要取得裝置註冊令牌,請在 區段中新增下列幾行,將 Firebase SDK 新增至應用程式模組的 build.gradle
檔案(如果這些行 dependencies
還不存在):
// Add the SDK for Firebase Cloud Messaging
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.google.firebase:firebase-messaging:20.2.4'
在專案層級的 build.gradle
檔案中的 dependencies
區段中,如果尚未存在這一行,請新增下列這一行:
classpath 'com.google.gms:google-services:4.3.3'
如果檔案尚未存在,請將下列外掛程式新增至檔案的開頭:
apply plugin: 'com.google.gms.google-services'
在工具列上,選取 [ 立即同步處理]。 新增下列代碼段,以取得 Firebase 雲端傳訊 SDK 針對用戶端應用程式實例產生的裝置註冊令牌。 請務必將以下匯入新增至主要活動的標頭中,以便執行個體可以擷取權杖。
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
新增此程式碼片段以擷取權杖:
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(@NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w("PushNotification", "getInstanceId failed", task.getException());
return;
}
// Get the new instance ID token
String deviceToken = task.getResult().getToken();
// Log
Log.d("PushNotification", "Device Registration token retrieved successfully");
}
});
向通話服務 SDK 註冊裝置註冊權杖,以取得來電的推播通知:
String deviceRegistrationToken = "<Device Token from previous section>";
try {
callAgent.registerPushNotification(deviceRegistrationToken).get();
}
catch(Exception e) {
System.out.println("Something went wrong while registering for Incoming Calls Push Notifications.")
}
處理推播通知
若要接收來電的推播通知,請在具有承載的 handlePushNotification()
執行個體上呼叫 CallAgent
。
若要從 Firebase Cloud Messaging 取得承載,請先建立新的服務 (選取 [檔案]>[新增]>[服務]>[服務]),以延伸 FirebaseMessagingService
Firebase SDK 類別並覆寫 onMessageReceived
方法。 此方法是 Firebase 雲端傳訊將推播通知傳遞至應用程式時所呼叫的事件處理程式。
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private java.util.Map<String, String> pushNotificationMessageDataFromFCM;
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if the message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("PushNotification", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
else {
pushNotificationMessageDataFromFCM = remoteMessage.getData();
}
}
}
將下列服務定義新增至 AndroidManifest.xml
檔案的 <application>
標籤內:
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
在擷取承載後,您可以將其傳遞給通訊服務 SDK 以剖析為內部 IncomingCallInformation
物件。 這個物件會處理在 handlePushNotification
執行個體上呼叫 CallAgent
方法的作業。 您要在 CallAgent
類別上呼叫 createCallAgent(...)
方法,以建立 CallClient
執行個體。
try {
IncomingCallInformation notification = IncomingCallInformation.fromMap(pushNotificationMessageDataFromFCM);
Future handlePushNotificationFuture = callAgent.handlePushNotification(notification).get();
}
catch(Exception e) {
System.out.println("Something went wrong while handling the Incoming Calls Push Notifications.");
}
當推播通知訊息的處理成功,且所有事件處理程式都已正確註冊時,應用程式會響鈴。
取消註冊推播通知
應用程式可以隨時取消註冊推播通知。 若要取消註冊,請在unregisterPushNotification()
上呼叫callAgent
方法。
try {
callAgent.unregisterPushNotification().get();
}
catch(Exception e) {
System.out.println("Something went wrong while un-registering for all Incoming Calls Push Notifications.")
}
停用來電的內部推播通知
來電的推播承載可以透過兩種方式傳遞給被呼叫者:
- 使用 FCM 並在
registerPushNotification
或CallAgent
上向前述 APITeamsCallAgent
註冊裝置權杖 - 在建立
CallAgent
或TeamsCallAgent
時向內部服務註冊 SDK 以便能傳遞推播承載
藉由在 setDisableInternalPushForIncomingCall
或 CallAgentOptions
中使用 TeamsCallAgentOptions
屬性,您可以指示 SDK 停用透過內部推播服務傳遞推播承載的功能:
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisableInternalPushForIncomingCall(true);
行動推播通知的考量
行動推播通知是出現在行動裝置上的快顯通知。 針對通話,本文著重於 voice over Internet Protocol (VoIP) 推播通知。 如需 iOS 應用程式中 CallKit 整合的指南,請參閱 與 CallKit 整合。
注意事項
當應用程式註冊推播通知並處理 Teams 使用者的傳入推播通知時,API 會相同。 本文描述的 API 也可以在 CommonCallAgent
或 TeamsCallAgent
類別上叫用。
設定您的系統
請遵循下列步驟來設定系統。
建立 Xcode 專案
在 Xcode 中建立新的 iOS 專案,並選取 [單一檢視應用程式] 範本。 本文使用 SwiftUI 架構,因此您應該將 Language 設定為 Swift,並將 Interface 設定為 SwiftUI。
您不會建立本文中的測試。 請放心清除 [包含測試] 核取方塊。
使用 CocoaPods 安裝套件及其相依項目
為您的應用程式建立 Podfile,如以下範例所示:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
執行
pod install
。使用 Xcode 開啟
.xcworkspace
。
要求存取麥克風
若要存取裝置的麥克風,您必須使用 NSMicrophoneUsageDescription
更新應用程式的資訊屬性清單。 將相關的值設定為系統用來向使用者請求存取權時包含在對話框中的字串。
以滑鼠右鍵按一下專案樹狀結構的 Info.plist 項目,接著選取 [開啟為]>[原始程式碼]。 將以下幾行新增至最上層 <dict>
區段中,然後儲存檔案。
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
設定應用程式架構
開啟項目的 ContentView.swift
檔案。 將 import
宣告新增至檔案頂端,以匯入 AzureCommunicationCalling
程式庫。 此外,匯入 AVFoundation
。 您需要它才能在程式代碼中要求音訊許可權。
import AzureCommunicationCalling
import AVFoundation
初始化 CallAgent
若要從 CallAgent
建立 CallClient
執行個體,您必須使用 callClient.createCallAgent
方法,在 CallAgent
物件初始化後以非同步方式傳回該物件。
若要建立通話用戶端,請傳遞 CommunicationTokenCredential
物件:
import AzureCommunication
let tokenString = "token_string"
var userCredential: CommunicationTokenCredential?
do {
let options = CommunicationTokenRefreshOptions(initialToken: token, refreshProactively: true, tokenRefresher: self.fetchTokenSync)
userCredential = try CommunicationTokenCredential(withOptions: options)
} catch {
updates("Couldn't created Credential object", false)
initializationDispatchGroup!.leave()
return
}
// tokenProvider needs to be implemented by Contoso, which fetches a new token
public func fetchTokenSync(then onCompletion: TokenRefreshOnCompletion) {
let newToken = self.tokenProvider!.fetchNewToken()
onCompletion(newToken, nil)
}
將您建立的 CommunicationTokenCredential
物件傳遞至 CallClient
,並設定顯示名稱:
self.callClient = CallClient()
let callAgentOptions = CallAgentOptions()
options.displayName = " iOS Azure Communication Services User"
self.callClient!.createCallAgent(userCredential: userCredential!,
options: callAgentOptions) { (callAgent, error) in
if error == nil {
print("Create agent succeeded")
self.callAgent = callAgent
} else {
print("Create agent failed")
}
})
設定推播通知
開始註冊、處理和取消註冊推播通知的工作之前,請先完成此設定工作:
- 在 Xcode 中,移至 [簽署與功能]。 選取 [+ 功能] 以新增功能,然後選取 [推播通知]。
- 選取 [+ 功能],然後選取 [背景模式],以新增另一個功能。
- 在 [背景模式] 底下,選取 [透過 IP 的語音] 和 [遠端通知] 核取方塊。
註冊推播通知
若要註冊推播通知,請使用裝置註冊權杖在 registerPushNotification()
執行個體上呼叫 CallAgent
。
成功初始化之後,必須註冊推播通知。 當callAgent
對象被銷毀時,會呼叫logout
,這會自動取消註冊推播通知。
let deviceToken: Data = pushRegistry?.pushToken(for: PKPushType.voIP)
callAgent.registerPushNotifications(deviceToken: deviceToken!) { (error) in
if(error == nil) {
print("Successfully registered to push notification.")
} else {
print("Failed to register push notification.")
}
}
處理推播通知
若要接收來電的推播通知,請在具有字典承載的 handlePushNotification()
執行個體上呼叫 CallAgent
:
let callNotification = PushNotificationInfo.fromDictionary(pushPayload.dictionaryPayload)
callAgent.handlePush(notification: callNotification) { (error) in
if (error == nil) {
print("Handling of push notification was successful")
} else {
print("Handling of push notification failed")
}
}
取消註冊推播通知
應用程式可以隨時取消註冊推播通知。 若要取消註冊,請在unregisterPushNotification
上呼叫CallAgent
方法。
注意事項
應用程式不會在登出時自動從推播通知取消註冊。
callAgent.unregisterPushNotification { (error) in
if (error == nil) {
print("Unregister of push notification was successful")
} else {
print("Unregister of push notification failed, please try again")
}
}
停用來電的內部推播通知
來電的推播承載可以透過兩種方式傳遞給被呼叫者:
- 使用 Apple Push Notification service (APNS),並在
registerPushNotification
或CallAgent
上向前述 APITeamsCallAgent
註冊裝置權杖 - 在建立
CallAgent
或TeamsCallAgent
時向內部服務註冊 SDK 以便能傳遞推播承載
藉由在 disableInternalPushForIncomingCall
或 CallAgentOptions
中使用 TeamsCallAgentOptions
屬性,您可以指示 SDK 停用透過內部推播服務傳遞推播承載的功能:
let options = CallAgentOptions()
options.disableInternalPushForIncomingCall = true
Windows 推送通知的注意事項
行動推播通知是出現在行動裝置上的快顯通知。 針對通話,本文著重於 voice over Internet Protocol (VoIP) 推播通知。
Windows 平臺上的推播通知會透過 Windows 推播通知服務 (WNS) 傳遞。
注意事項
當應用程式註冊推播通知並處理自定義 Teams 端點 (CTE) 的推播通知時,API 會相同。 本文描述的 API 也可以在 CTE 的 CommonCallAgent
或 TeamsCallAgent
類別上叫用。
設定您的系統
請遵循下列步驟來設定系統。
建立 Visual Studio 專案
針對 通用 Windows 平台 應用程式,請在 Visual Studio 2022 中建立新的空白應用程式 (通用 Windows) 專案。 在輸入專案名稱之後,隨意選擇高於 10.0.17763.0 的任何 Windows SDK。
針對 WinUI 3 應用程式,使用空白應用程式、封裝 (桌面中的 WinUI 3) 範本建立新專案,以設定單頁 WinUI 3 應用程式。 需要 Windows App SDK 1.3 版或更新版本。
使用 NuGet 套件管理員來安裝套件和相依性
通話 SDK API 和程式庫可透過 NuGet 套件公開取得。
若要尋找、下載並安裝呼叫 SDK NuGet 套件:
- 藉由選取 [工具]>[NuGet 套件管理員]>[管理解決方案的 NuGet 套件],開啟 NuGet 套件管理員。
- 選取 [ 瀏覽],然後在搜尋方塊中輸入 Azure.Communication.Calling.WindowsClient 。
- 確定已選取 [包含發行前版本] 核取方塊。
- 選取 Azure.Communication.Calling.WindowsClient 套件,然後選取 [Azure.Communication.Calling.WindowsClient 1.4.0-beta.1] 或更新版本。
- 選取對應至右窗格中 Azure 通訊服務 項目的複選框。
- 選擇 [安裝]。
設定推播通知
開始註冊、處理及顯示 Windows 通知以接聽或拒絕來電的工作之前,請先完成此設定工作:
遵循 [教學課程:使用 Azure 通知中樞向通用 Windows 平台應用程式傳送通知]。 遵循本教學課程之後,您有:
- 具有
WindowsAzure.Messaging.Managed
和Microsoft.Toolkit.Uwp.Notifications
套件的應用程式。 - 本文中以
<AZURE_PNH_HUB_NAME>
形式參考的「Azure 通知中樞」中樞名稱,以及以<AZURE_PNH_HUB_CONNECTION_STRING>
形式參考的「Azure 通知中樞」連接字串。
- 具有
若要在每個應用程式初始化上註冊 WNS 通道,請務必在檔案
App.xaml.cs
中新增初始化程式代碼:// App.xaml.cs protected override async void OnLaunched(LaunchActivatedEventArgs e) { await InitNotificationsAsync(); ... } private async Task InitNotificationsAsync() { if (AZURE_PNH_HUB_NAME != "<AZURE_PNH_HUB_NAME>" && AZURE_PNH_HUB_CONNECTION_STRING != "<AZURE_PNH_HUB_CONNECTION_STRING>") { var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); channel.PushNotificationReceived += Channel_PushNotificationReceived; var hub = new NotificationHub(AZURE_PNH_HUB_NAME, AZURE_PNH_HUB_CONNECTION_STRING); var result = await hub.RegisterNativeAsync(channel.Uri); if (result.ChannelUri != null) { PNHChannelUri = new Uri(result.ChannelUri); } else { Debug.WriteLine("Cannot register WNS channel"); } } }
註冊在
App.xaml.cs
上收到新推播通知訊息時所啟動的事件處理常式:// App.xaml.cs private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args) { switch (args.NotificationType) { case PushNotificationType.Toast: case PushNotificationType.Tile: case PushNotificationType.TileFlyout: case PushNotificationType.Badge: break; case PushNotificationType.Raw: var frame = (Frame)Window.Current.Content; if (frame.Content is MainPage) { var mainPage = frame.Content as MainPage; await mainPage.HandlePushNotificationIncomingCallAsync(args.RawNotification.Content); } break; } }
註冊推播通知
若要註冊推播通知,請使用在應用程式初始化時取得的 WNS 註冊通道在 RegisterForPushNotificationAsync()
執行個體上呼叫 CallAgent
。
成功初始化之後,必須註冊推播通知。
// MainPage.xaml.cs
this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
if ((Application.Current as App).PNHChannelUri != null)
{
await this.callAgent.RegisterForPushNotificationAsync((Application.Current as App).PNHChannelUri.ToString());
}
this.callAgent.CallsUpdated += OnCallsUpdatedAsync;
this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
處理推播通知
若要接收來電的推播通知,請在具有字典承載的 handlePushNotification()
執行個體上呼叫 CallAgent
:
// MainPage.xaml.cs
public async Task HandlePushNotificationIncomingCallAsync(string notificationContent)
{
if (this.callAgent != null)
{
PushNotificationDetails pnDetails = PushNotificationDetails.Parse(notificationContent);
await callAgent.HandlePushNotificationAsync(pnDetails);
}
}
此呼叫會在 CallAgent
上觸發一個來電事件,顯示來電通知。
// MainPage.xaml.cs
private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
{
incomingCall = args.IncomingCall;
(Application.Current as App).ShowIncomingCallNotification(incomingCall);
}
// App.xaml.cs
public void ShowIncomingCallNotification(IncomingCall incomingCall)
{
string incomingCallType = incomingCall.IsVideoEnabled ? "Video" : "Audio";
string caller = incomingCall.CallerDetails.DisplayName != "" ? incomingCall.CallerDetails.DisplayName : incomingCall.CallerDetails.Identifier.RawId;
new ToastContentBuilder()
.SetToastScenario(ToastScenario.IncomingCall)
.AddText(caller + " is calling you.")
.AddText("New Incoming " + incomingCallType + " Call")
.AddButton(new ToastButton()
.SetContent("Decline")
.AddArgument("action", "decline"))
.AddButton(new ToastButton()
.SetContent("Accept")
.AddArgument("action", "accept"))
.Show();
}
在 OnActivated
方法中新增用來處理通知按鈕按下動作的程式碼:
// App.xaml.cs
protected override async void OnActivated(IActivatedEventArgs e)
{
// Handle notification activation
if (e is ToastNotificationActivatedEventArgs toastActivationArgs)
{
ToastArguments args = ToastArguments.Parse(toastActivationArgs.Argument);
string action = args?.Get("action");
if (!string.IsNullOrEmpty(action))
{
var frame = Window.Current.Content as Frame;
if (frame.Content is MainPage)
{
var mainPage = frame.Content as MainPage;
await mainPage.AnswerIncomingCall(action);
}
}
}
}
// MainPage.xaml.cs
public async Task AnswerIncomingCall(string action)
{
if (action == "accept")
{
var acceptCallOptions = new AcceptCallOptions()
{
IncomingVideoOptions = new IncomingVideoOptions()
{
StreamKind = VideoStreamKind.RemoteIncoming
}
};
call = await incomingCall?.AcceptAsync(acceptCallOptions);
call.StateChanged += OnStateChangedAsync;
call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync;
}
else if (action == "decline")
{
await incomingCall?.RejectAsync();
}
}