|
| 1 | +--- |
| 2 | +author: probableprime |
| 3 | +ms.service: azure-communication-services |
| 4 | +ms.topic: include |
| 5 | +ms.date: 03/26/2024 |
| 6 | +ms.author: jsaurezlee |
| 7 | +--- |
| 8 | +[!INCLUDE [Install SDK](../install-sdk/install-sdk-windows.md)] |
| 9 | + |
| 10 | +## Set up push notifications |
| 11 | + |
| 12 | +A push notification is the pop-up notification that you get in your device. For calling, we'll focus on VoIP (voice over Internet Protocol) push notifications. |
| 13 | + |
| 14 | +The following sections describe how to register for, handle, and show a Windows notification to answer/decline an incoming call. Before you start those tasks, complete these prerequisites: |
| 15 | + |
| 16 | +1. Follow [Tutorial: Send notifications to Universal Windows Platform apps using Azure Notification Hubs](/azure/notification-hubs/notification-hubs-windows-store-dotnet-get-started-wns-push-notification). After following this tutorial, you have: |
| 17 | + - An application that has the `WindowsAzure.Messaging.Managed` and `Microsoft.Toolkit.Uwp.Notifications` packages. |
| 18 | + - An Azure PNH (Push Notifications Hub) Hub name referenced as `<AZURE_PNH_HUB_NAME>` and the Azure PNH Connection String referenced as `<AZURE_PNH_HUB_CONNECTION_STRING>` in this quickstart. |
| 19 | + |
| 20 | +3. To register for a WNS (Windows Notification Service) channel on every application init, make sure you add the initialization code on your App.xaml.cs file: |
| 21 | + |
| 22 | +```C# |
| 23 | +// App.xaml.cs |
| 24 | +
|
| 25 | +protected override async void OnLaunched(LaunchActivatedEventArgs e) |
| 26 | +{ |
| 27 | + await InitNotificationsAsync(); |
| 28 | + |
| 29 | + ... |
| 30 | +} |
| 31 | + |
| 32 | +private async Task InitNotificationsAsync() |
| 33 | +{ |
| 34 | + if (AZURE_PNH_HUB_NAME != "<AZURE_PNH_HUB_NAME>" && AZURE_PNH_HUB_CONNECTION_STRING != "<AZURE_PNH_HUB_CONNECTION_STRING>") |
| 35 | + { |
| 36 | + var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); |
| 37 | + channel.PushNotificationReceived += Channel_PushNotificationReceived; |
| 38 | + |
| 39 | + var hub = new NotificationHub(AZURE_PNH_HUB_NAME, AZURE_PNH_HUB_CONNECTION_STRING); |
| 40 | + var result = await hub.RegisterNativeAsync(channel.Uri); |
| 41 | + |
| 42 | + if (result.ChannelUri != null) |
| 43 | + { |
| 44 | + PNHChannelUri = new Uri(result.ChannelUri); |
| 45 | + } |
| 46 | + else |
| 47 | + { |
| 48 | + Debug.WriteLine("Cannot register WNS channel"); |
| 49 | + } |
| 50 | + } |
| 51 | +} |
| 52 | +``` |
| 53 | +3. Register the event handler activated when a new push notification message arrives on App.xaml.cs: |
| 54 | + |
| 55 | +```C# |
| 56 | +// App.xaml.cs |
| 57 | +
|
| 58 | +private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args) |
| 59 | +{ |
| 60 | + switch (args.NotificationType) |
| 61 | + { |
| 62 | + case PushNotificationType.Toast: |
| 63 | + case PushNotificationType.Tile: |
| 64 | + case PushNotificationType.TileFlyout: |
| 65 | + case PushNotificationType.Badge: |
| 66 | + break; |
| 67 | + case PushNotificationType.Raw: |
| 68 | + var frame = (Frame)Window.Current.Content; |
| 69 | + if (frame.Content is MainPage) |
| 70 | + { |
| 71 | + var mainPage = frame.Content as MainPage; |
| 72 | + await mainPage.HandlePushNotificationIncomingCallAsync(args.RawNotification.Content); |
| 73 | + } |
| 74 | + break; |
| 75 | + } |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +### Register for push notifications |
| 80 | +To register for push notifications, call `RegisterForPushNotificationAsync()` on a `CallAgent` instance with the WNS registration channel obtained on application init. |
| 81 | + |
| 82 | +Registration for push notifications needs to happen after successful initialization. |
| 83 | + |
| 84 | +```C# |
| 85 | +// MainPage.xaml.cs |
| 86 | +
|
| 87 | +this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions); |
| 88 | + |
| 89 | +if ((Application.Current as App).PNHChannelUri != null) |
| 90 | +{ |
| 91 | + await this.callAgent.RegisterForPushNotificationAsync((Application.Current as App).PNHChannelUri.ToString()); |
| 92 | +} |
| 93 | + |
| 94 | +this.callAgent.CallsUpdated += OnCallsUpdatedAsync; |
| 95 | +this.callAgent.IncomingCallReceived += OnIncomingCallAsync; |
| 96 | +``` |
| 97 | + |
| 98 | +## Handle push notifications |
| 99 | +To receive push notifications for incoming calls, call `handlePushNotification()` on a `CallAgent` instance with a dictionary payload. |
| 100 | + |
| 101 | +```C# |
| 102 | +// MainPage.xaml.cs |
| 103 | +
|
| 104 | +public async Task HandlePushNotificationIncomingCallAsync(string notificationContent) |
| 105 | +{ |
| 106 | + if (this.callAgent != null) |
| 107 | + { |
| 108 | + PushNotificationDetails pnDetails = PushNotificationDetails.Parse(notificationContent); |
| 109 | + await callAgent.HandlePushNotificationAsync(pnDetails); |
| 110 | + } |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +This triggers an incoming call event on CallAgent that shows the incoming call notification. |
| 115 | + |
| 116 | +```C# |
| 117 | +// MainPage.xaml.cs |
| 118 | +
|
| 119 | +private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args) |
| 120 | +{ |
| 121 | + incomingCall = args.IncomingCall; |
| 122 | + (Application.Current as App).ShowIncomingCallNotification(incomingCall); |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +```C# |
| 127 | +// App.xaml.cs |
| 128 | +
|
| 129 | +public void ShowIncomingCallNotification(IncomingCall incomingCall) |
| 130 | +{ |
| 131 | + string incomingCallType = incomingCall.IsVideoEnabled ? "Video" : "Audio"; |
| 132 | + string caller = incomingCall.CallerDetails.DisplayName != "" ? incomingCall.CallerDetails.DisplayName : incomingCall.CallerDetails.Identifier.RawId; |
| 133 | + new ToastContentBuilder() |
| 134 | + .SetToastScenario(ToastScenario.IncomingCall) |
| 135 | + .AddText(caller + " is calling you.") |
| 136 | + .AddText("New Incoming " + incomingCallType + " Call") |
| 137 | + .AddButton(new ToastButton() |
| 138 | + .SetContent("Decline") |
| 139 | + .AddArgument("action", "decline")) |
| 140 | + .AddButton(new ToastButton() |
| 141 | + .SetContent("Accept") |
| 142 | + .AddArgument("action", "accept")) |
| 143 | + .Show(); |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +Add the code to handle the button press for the notification in the OnActivated method: |
| 148 | + |
| 149 | +```C# |
| 150 | +// App.xaml.cs |
| 151 | +
|
| 152 | +protected override async void OnActivated(IActivatedEventArgs e) |
| 153 | +{ |
| 154 | + // Handle notification activation |
| 155 | + if (e is ToastNotificationActivatedEventArgs toastActivationArgs) |
| 156 | + { |
| 157 | + ToastArguments args = ToastArguments.Parse(toastActivationArgs.Argument); |
| 158 | + string action = args?.Get("action"); |
| 159 | + |
| 160 | + if (!string.IsNullOrEmpty(action)) |
| 161 | + { |
| 162 | + var frame = Window.Current.Content as Frame; |
| 163 | + if (frame.Content is MainPage) |
| 164 | + { |
| 165 | + var mainPage = frame.Content as MainPage; |
| 166 | + await mainPage.AnswerIncomingCall(action); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +```C# |
| 174 | +// MainPage.xaml.cs |
| 175 | +
|
| 176 | +public async Task AnswerIncomingCall(string action) |
| 177 | +{ |
| 178 | + if (action == "accept") |
| 179 | + { |
| 180 | + var acceptCallOptions = new AcceptCallOptions() |
| 181 | + { |
| 182 | + IncomingVideoOptions = new IncomingVideoOptions() |
| 183 | + { |
| 184 | + StreamKind = VideoStreamKind.RemoteIncoming |
| 185 | + } |
| 186 | + }; |
| 187 | + |
| 188 | + call = await incomingCall?.AcceptAsync(acceptCallOptions); |
| 189 | + call.StateChanged += OnStateChangedAsync; |
| 190 | + call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync; |
| 191 | + } |
| 192 | + else if (action == "decline") |
| 193 | + { |
| 194 | + await incomingCall?.RejectAsync(); |
| 195 | + } |
| 196 | +} |
| 197 | +``` |
0 commit comments