From cb15f3e967dcee312d6c44d72dbdc152ae17b8ee Mon Sep 17 00:00:00 2001 From: DjArt Date: Sat, 27 Jul 2019 07:11:28 +0700 Subject: [PATCH] improved notification system, also need HUGE refactoring --- Internal.Windows.Calls | 2 +- WoADialer/App.xaml.cs | 98 ++++++++++++++-- WoADialer/Background/BackgroungCallMonitor.cs | 56 ---------- WoADialer/Background/CallWaiter.cs | 49 ++++++++ WoADialer/Background/NotificationHelper.cs | 50 --------- WoADialer/Background/NotificationShredder.cs | 54 +++++++++ WoADialer/Background/TaskManager.cs | 105 ++++++++++++++++-- WoADialer/Model/MainEntities.cs | 35 +++--- WoADialer/Package.appxmanifest | 11 +- WoADialer/UI/Pages/InCallUI.xaml.cs | 16 +-- WoADialer/UI/Pages/MainPage.xaml.cs | 13 +-- WoADialer/WoADialer.csproj | 9 +- WoADialer/WoADialer.csproj.user | 12 +- 13 files changed, 336 insertions(+), 174 deletions(-) delete mode 100644 WoADialer/Background/BackgroungCallMonitor.cs create mode 100644 WoADialer/Background/CallWaiter.cs delete mode 100644 WoADialer/Background/NotificationHelper.cs create mode 100644 WoADialer/Background/NotificationShredder.cs diff --git a/Internal.Windows.Calls b/Internal.Windows.Calls index 6b21eee..555aca4 160000 --- a/Internal.Windows.Calls +++ b/Internal.Windows.Calls @@ -1 +1 @@ -Subproject commit 6b21eee3622444d038cde6aeb0b7103cf46f8dc8 +Subproject commit 555aca4a8c2c7290662c21bc98eef0eb049a04fa diff --git a/WoADialer/App.xaml.cs b/WoADialer/App.xaml.cs index 515bcd4..befc494 100644 --- a/WoADialer/App.xaml.cs +++ b/WoADialer/App.xaml.cs @@ -1,14 +1,21 @@ -using System; +using Internal.Windows.Calls; +using Microsoft.QueryStringDotNET; +using Microsoft.Toolkit.Uwp.Notifications; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using System.Threading.Tasks; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Background; using Windows.ApplicationModel.Calls; +using Windows.ApplicationModel.Calls.Background; using Windows.Foundation; using Windows.Foundation.Collections; +using Windows.UI.Notifications; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; @@ -25,12 +32,18 @@ namespace WoADialer { sealed partial class App : Application { + private NotificationShredder Shredder; + private CallWaiter Waiter; + private ManualResetEvent Event; + private Call Incoming; + public App() { this.InitializeComponent(); this.Suspending += OnSuspending; - if(SettingsManager.isFirstTimeRun()) SettingsManager.setDefaultSettings(); + if (SettingsManager.isFirstTimeRun()) SettingsManager.setDefaultSettings(); + MainEntities.Initialize(); } protected override void OnActivated(IActivatedEventArgs args) @@ -56,6 +69,23 @@ protected override void OnActivated(IActivatedEventArgs args) case ActivationKind.LockScreenCall: + break; + case ActivationKind.ToastNotification: + var toastActivationArgs = args as ToastNotificationActivatedEventArgs; + + QueryString str = QueryString.Parse(toastActivationArgs.Argument); + + switch (str["action"]) + { + case "answer": + uint callID = uint.Parse(str["callId"]); + MainEntities.CallManager.CurrentCalls.FirstOrDefault(x => x.ID == callID)?.AcceptIncomingEx(); + break; + } + if (rootFrame.BackStack.Count == 0) + { + rootFrame.BackStack.Add(new PageStackEntry(typeof(MainPage), null, null)); + } break; default: rootFrame.Navigate(typeof(InCallUI)); @@ -95,20 +125,74 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) } } - protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args) + protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args) { base.OnBackgroundActivated(args); BackgroundTaskDeferral deferral = args.TaskInstance.GetDeferral(); switch (args.TaskInstance.Task.Name) { - case TaskManager.USER_NOTIFICATION_CHANGED: - NotificationHelper.RemoveSystemCallNotification(); + default: + deferral.Complete(); break; case TaskManager.LINE_STATE_CHANGED: - + PhoneLineChangedTriggerDetails details = args.TaskInstance.TriggerDetails as PhoneLineChangedTriggerDetails; + if (Shredder == null && Waiter == null && Incoming == null) + { + Event = new ManualResetEvent(false); + Shredder = new NotificationShredder(); + Waiter = new CallWaiter(); + Shredder.NotificationRemoved += Shredder_NotificationRemoved; + Waiter.CallAppeared += Waiter_CallAppeared; + Shredder.RegisterListener(); + Waiter.RegisterListener(); + await Task.Run(() => Event.WaitOne(5000)); + //TaskManager.ShowToast("Registered"); + Event = null; + Incoming = null; + Waiter = null; + Shredder = null; + goto default; + } + else + { + //TaskManager.ShowToast("Not registered"); + goto default; + } break; } - deferral.Complete(); + } + + private void Waiter_CallAppeared(object sender, Call e) + { + Incoming = e; + Waiter.UnregisterListener(); + Waiter.CallAppeared -= Waiter_CallAppeared; + ToastNotification notification = TaskManager.ShowCallToast(e); + e.StateChanged += E_StateChanged; + notification.Activated += Notification_Activated; + } + + private void E_StateChanged(Call sender, CallState args) + { + sender.StateChanged -= E_StateChanged; + if (args == CallState.Disconnected) + { + TaskManager.ShowToast($"Missed call: {sender.Number}"); + } + Event.Set(); + } + + private void Notification_Activated(ToastNotification sender, object args) + { + Incoming.StateChanged -= E_StateChanged; + Event.Set(); + } + + private void Shredder_NotificationRemoved(object sender, EventArgs e) + { + Shredder.UnregisterListener(); + Shredder.NotificationRemoved -= Shredder_NotificationRemoved; + //TaskManager.ShowToast($"{MainEntities.CallManager.CurrentCalls.FirstOrDefault(x => x.State == CallState.Incoming)?.Number}"); } void OnNavigationFailed(object sender, NavigationFailedEventArgs e) diff --git a/WoADialer/Background/BackgroungCallMonitor.cs b/WoADialer/Background/BackgroungCallMonitor.cs deleted file mode 100644 index 8326be8..0000000 --- a/WoADialer/Background/BackgroungCallMonitor.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Internal.Windows.Calls; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.Background; -using Windows.ApplicationModel.LockScreen; - -using Microsoft.Toolkit.Uwp.Notifications; -using Windows.UI.Notifications; -using Windows.ApplicationModel.Calls.Background; - -namespace WoADialer.Model -{ - public sealed class BackgroungCallMonitor : IBackgroundTask - { - BackgroundTaskDeferral _Deferral; - - public void Run(IBackgroundTaskInstance taskInstance) - { - _Deferral = taskInstance.GetDeferral(); - string text = "????"; - if (taskInstance.TriggerDetails is PhoneLineChangedTriggerDetails lineDetails) - { - text = "lineDetails"; - } - ToastVisual toast = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "TEST" - }, - - new AdaptiveText() - { - Text = text - } - } - } - }; - ToastContent toastContent = new ToastContent() - { - Visual = toast, Scenario = ToastScenario.IncomingCall - }; - ToastNotification notification = new ToastNotification(toastContent.GetXml()); - ToastNotificationManager.CreateToastNotifier().Show(notification); - _Deferral.Complete(); - } - } -} diff --git a/WoADialer/Background/CallWaiter.cs b/WoADialer/Background/CallWaiter.cs new file mode 100644 index 0000000..220e4b3 --- /dev/null +++ b/WoADialer/Background/CallWaiter.cs @@ -0,0 +1,49 @@ +using Internal.Windows.Calls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.ApplicationModel.Background; +using Windows.ApplicationModel.LockScreen; + +using Microsoft.Toolkit.Uwp.Notifications; +using Windows.UI.Notifications; +using Windows.ApplicationModel.Calls.Background; + +namespace WoADialer.Model +{ + public sealed class CallWaiter + { + public event EventHandler CallAppeared; + + public CallWaiter() + { + + } + + private void CallManager_CallAppeared(CallManager sender, Call args) + { + if (args.State == CallState.Incoming) + { + CallAppeared?.Invoke(this, args); + } + } + + public void RegisterListener() + { + MainEntities.CallManager.CallAppeared += CallManager_CallAppeared; + Call call = MainEntities.CallManager.CurrentCalls.FirstOrDefault(x => x.State == CallState.Incoming); + if (call?.State == CallState.Incoming) + { + CallAppeared?.Invoke(this, call); + } + } + + public void UnregisterListener() + { + MainEntities.CallManager.CallAppeared -= CallManager_CallAppeared; + } + } +} diff --git a/WoADialer/Background/NotificationHelper.cs b/WoADialer/Background/NotificationHelper.cs deleted file mode 100644 index 0bb5c7e..0000000 --- a/WoADialer/Background/NotificationHelper.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.Toolkit.Uwp.Notifications; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Windows.UI.Notifications; -using Windows.UI.Notifications.Management; - -namespace WoADialer.Background -{ - public static class NotificationHelper - { - public static async void RemoveSystemCallNotification() - { - UserNotificationListener listener = UserNotificationListener.Current; - IReadOnlyList userNotifications = await listener.GetNotificationsAsync(NotificationKinds.Toast); - UserNotification f = userNotifications.FirstOrDefault(x => (x.Notification.Visual.GetBinding(KnownNotificationBindings.ToastGeneric)?.GetTextElements()?.FirstOrDefault()?.Text ?? "") == "Tele2"); - if (f != null) - { - listener.RemoveNotification(f.Id); - ToastVisual toast = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "TEST" - }, - - new AdaptiveText() - { - Text = $"modelId: {f.AppInfo?.AppUserModelId}, id: {f.AppInfo?.Id}" - } - } - } - }; - ToastContent toastContent = new ToastContent() - { - Visual = toast, - Scenario = ToastScenario.IncomingCall - }; - ToastNotification notification = new ToastNotification(toastContent.GetXml()); - ToastNotificationManager.CreateToastNotifier().Show(notification); - } - } - } -} diff --git a/WoADialer/Background/NotificationShredder.cs b/WoADialer/Background/NotificationShredder.cs new file mode 100644 index 0000000..90f2ff9 --- /dev/null +++ b/WoADialer/Background/NotificationShredder.cs @@ -0,0 +1,54 @@ +using Microsoft.Toolkit.Uwp.Notifications; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.ApplicationModel.Background; +using Windows.UI.Notifications; +using Windows.UI.Notifications.Management; + +namespace WoADialer.Background +{ + public sealed class NotificationShredder + { + private const string WINDOWS_SYSTEM_TOAST_CALLING = "Windows.SystemToast.Calling"; + + public event EventHandler NotificationRemoved; + + public NotificationShredder() + { + + } + + public async void RegisterListener() + { + UserNotificationListener.Current.NotificationChanged += Listener_NotificationChanged; + IReadOnlyList notifications = await UserNotificationListener.Current.GetNotificationsAsync(NotificationKinds.Toast); + UserNotification callToast = notifications.FirstOrDefault(x => x.AppInfo.AppUserModelId == WINDOWS_SYSTEM_TOAST_CALLING); + if (callToast != null) + { + UserNotificationListener.Current.RemoveNotification(callToast.Id); + NotificationRemoved?.Invoke(this, null); + } + } + + public void UnregisterListener() + { + UserNotificationListener.Current.NotificationChanged -= Listener_NotificationChanged; + } + + private void Listener_NotificationChanged(UserNotificationListener sender, UserNotificationChangedEventArgs args) + { + if (args.ChangeKind == UserNotificationChangedKind.Added) + { + UserNotification notification = sender.GetNotification(args.UserNotificationId); + if (notification.AppInfo.AppUserModelId == WINDOWS_SYSTEM_TOAST_CALLING) + { + sender.RemoveNotification(notification.Id); + NotificationRemoved?.Invoke(this, null); + } + } + } + } +} diff --git a/WoADialer/Background/TaskManager.cs b/WoADialer/Background/TaskManager.cs index 8cd5dad..c430307 100644 --- a/WoADialer/Background/TaskManager.cs +++ b/WoADialer/Background/TaskManager.cs @@ -1,4 +1,6 @@ -using System; +using Internal.Windows.Calls; +using Microsoft.Toolkit.Uwp.Notifications; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,33 +8,112 @@ using Windows.ApplicationModel.Background; using Windows.ApplicationModel.Calls.Background; using Windows.UI.Notifications; +using WoADialer.Model; namespace WoADialer.Background { public static class TaskManager { - public const string USER_NOTIFICATION_CHANGED = "UserNotificationChanged"; public const string LINE_STATE_CHANGED = "LineStateChanged"; public static async Task RegisterBackgroudTasks() { await BackgroundExecutionManager.RequestAccessAsync(); - foreach (var task3 in BackgroundTaskRegistration.AllTasks) + //I know that stupid + if (BackgroundTaskRegistration.AllTasks.Count != 1) { - task3.Value.Unregister(true); + foreach (var task3 in BackgroundTaskRegistration.AllTasks) + { + task3.Value.Unregister(true); + } + + var builder = new BackgroundTaskBuilder(); + + builder.Name = LINE_STATE_CHANGED; + builder.SetTrigger(new PhoneTrigger(PhoneTriggerType.LineChanged, false)); + BackgroundTaskRegistration task = builder.Register(); } + } - var builder = new BackgroundTaskBuilder(); + public static void ShowToast(string msg) + { + ToastVisual toast = new ToastVisual() + { + BindingGeneric = new ToastBindingGeneric() + { + Children = + { + new AdaptiveText() + { + Text = "Notification Test" + }, - builder.Name = LINE_STATE_CHANGED; - builder.SetTrigger(new PhoneTrigger(PhoneTriggerType.LineChanged, false)); - BackgroundTaskRegistration task = builder.Register(); + new AdaptiveText() + { + Text = msg + } + } + } + }; + ToastContent toastContent = new ToastContent() + { + Visual = toast, + Scenario = ToastScenario.Default + }; + ToastNotification notification = new ToastNotification(toastContent.GetXml()); + MainEntities.ToastNotifier.Show(notification); + } - builder = new BackgroundTaskBuilder(); + public static ToastNotification ShowCallToast(Call call) + { + var toastContent = new ToastContent() + { + Visual = new ToastVisual() + { + BindingGeneric = new ToastBindingGeneric() + { + Children = + { + new AdaptiveText() + { + Text = "Incoming Call" + }, + new AdaptiveText() + { + Text = new BindableString($"{call.Number}") + } + } + } + }, + Actions = new ToastActionsCustom() + { + Buttons = + { + new ToastButton("Text reply", $"action=textReply&callId={call.ID}") + { + ActivationType = ToastActivationType.Foreground + }, + new ToastButton("Reminder", $"action=reminder&callId={call.ID}") + { + ActivationType = ToastActivationType.Background + }, + new ToastButton("Ignore", $"action=ignore&callId={call.ID}") + { + ActivationType = ToastActivationType.Background + }, + new ToastButton("Answer", $"action=answer&callId={call.ID}") + { + ActivationType = ToastActivationType.Foreground + } + } + }, + Launch = $"action=answer&callId={call.ID}", + Scenario = ToastScenario.IncomingCall + }; - builder.Name = USER_NOTIFICATION_CHANGED; - builder.SetTrigger(new UserNotificationChangedTrigger(NotificationKinds.Toast)); - task = builder.Register(); + ToastNotification notification = new ToastNotification(toastContent.GetXml()); + MainEntities.ToastNotifier.Show(notification); + return notification; } } } diff --git a/WoADialer/Model/MainEntities.cs b/WoADialer/Model/MainEntities.cs index d546f1c..55b53d0 100644 --- a/WoADialer/Model/MainEntities.cs +++ b/WoADialer/Model/MainEntities.cs @@ -12,6 +12,7 @@ using Windows.ApplicationModel.Calls.Background; using Windows.UI.Notifications.Management; using WoADialer.Background; +using Windows.UI.Notifications; namespace WoADialer.Model { @@ -23,28 +24,30 @@ internal static class MainEntities public static PhoneCallStore CallStore { get; private set; } public static PhoneCallHistoryStore CallHistoryStore { get; private set; } public static ProximitySensor ProximitySensor { get; private set; } + public static ToastNotifier ToastNotifier { get; private set; } public static async Task Initialize() { - DeviceInformationCollection devices; - CallManager = await CallManager.GetSystemPhoneCallManagerAsync(); - CallStore = await PhoneCallManager.RequestStoreAsync(); - Windows.ApplicationModel.Calls.Provider.PhoneCallOriginManager.ShowPhoneCallOriginSettingsUI(); - CallHistoryStore = await PhoneCallHistoryManager.RequestStoreAsync(PhoneCallHistoryStoreAccessType.AllEntriesReadWrite); - devices = await DeviceInformation.FindAllAsync(ProximitySensor.GetDeviceSelector()); - ProximitySensor = devices.Count > 0 ? ProximitySensor.FromId(devices.First().Id) : null; - UserNotificationListener listener = UserNotificationListener.Current; - UserNotificationListenerAccessStatus accessStatus = await listener.RequestAccessAsync(); - await TaskManager.RegisterBackgroudTasks(); - try - { - DefaultLine = await PhoneLine.FromIdAsync(await CallStore.GetDefaultLineAsync()); - } - catch + if (!Initialized) { + DeviceInformationCollection devices; + CallManager = await CallManager.GetCallManagerAsync(); + CallStore = await PhoneCallManager.RequestStoreAsync(); + CallHistoryStore = await PhoneCallHistoryManager.RequestStoreAsync(PhoneCallHistoryStoreAccessType.AllEntriesReadWrite); + devices = await DeviceInformation.FindAllAsync(ProximitySensor.GetDeviceSelector()); + ProximitySensor = devices.Count > 0 ? ProximitySensor.FromId(devices.First().Id) : null; + ToastNotifier = ToastNotificationManager.CreateToastNotifier(); + await TaskManager.RegisterBackgroudTasks(); + try + { + DefaultLine = await PhoneLine.FromIdAsync(await CallStore.GetDefaultLineAsync()); + } + catch + { + } + Initialized = true; } - Initialized = true; } } } diff --git a/WoADialer/Package.appxmanifest b/WoADialer/Package.appxmanifest index ff53d65..70f08d3 100644 --- a/WoADialer/Package.appxmanifest +++ b/WoADialer/Package.appxmanifest @@ -5,16 +5,16 @@ xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2" + xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10" - xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" - IgnorableNamespaces="uap mp uap2 uap5 rescap iot uap3"> + IgnorableNamespaces="mp uap uap2 uap3 uap5 rescap iot"> + Version="0.1.140.0" /> @@ -61,10 +61,9 @@ - + - @@ -74,7 +73,7 @@ WoADialer.exe - + diff --git a/WoADialer/UI/Pages/InCallUI.xaml.cs b/WoADialer/UI/Pages/InCallUI.xaml.cs index d31c029..2a7dff9 100644 --- a/WoADialer/UI/Pages/InCallUI.xaml.cs +++ b/WoADialer/UI/Pages/InCallUI.xaml.cs @@ -111,10 +111,10 @@ private async void CurrentCall_StateChanged(Call sender, CallState args) protected async override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - if (!MainEntities.Initialized) - { - await MainEntities.Initialize(); - } + //if (!MainEntities.Initialized) + //{ + // await MainEntities.Initialize(); + //} CurrentCall = MainEntities.CallManager.CurrentCalls.FirstOrDefault(x => x.State == CallState.Dialing || x.State == CallState.ActiveTalking || x.State == CallState.OnHold); MainEntities.CallManager.CurrentCallsChanged += CallManager_CurrentCallsChanged; } @@ -141,10 +141,10 @@ private async void Page_Loaded(object sender, RoutedEventArgs e) { try { - if (!MainEntities.Initialized) - { - await MainEntities.Initialize(); - } + //if (!MainEntities.Initialized) + //{ + // await MainEntities.Initialize(); + //} } catch (Exception ex) { diff --git a/WoADialer/UI/Pages/MainPage.xaml.cs b/WoADialer/UI/Pages/MainPage.xaml.cs index 687997e..915a0ef 100644 --- a/WoADialer/UI/Pages/MainPage.xaml.cs +++ b/WoADialer/UI/Pages/MainPage.xaml.cs @@ -136,18 +136,7 @@ private async void AboutButton_Click(object sender, RoutedEventArgs e) private async void Page_Loaded(object sender, RoutedEventArgs e) { - try - { - if (!MainEntities.Initialized) - { - await MainEntities.Initialize(); - } - PhoneCallManager.CallStateChanged += UpdateState; - } - catch (Exception ex) - { - await new MessageDialog($"{ex}").ShowAsync(); - } + PhoneCallManager.CallStateChanged += UpdateState; } } } diff --git a/WoADialer/WoADialer.csproj b/WoADialer/WoADialer.csproj index a09e71c..013d253 100644 --- a/WoADialer/WoADialer.csproj +++ b/WoADialer/WoADialer.csproj @@ -23,7 +23,7 @@ True False Always - arm64 + arm 0 OnApplicationRun D6D3DD7876C96E04FB6FEC716E0918CC849C1802 @@ -130,7 +130,7 @@ App.xaml - + @@ -155,7 +155,7 @@ MainPage.xaml - + @@ -312,6 +312,9 @@ 5.1.1 + + 1.0.0 + diff --git a/WoADialer/WoADialer.csproj.user b/WoADialer/WoADialer.csproj.user index 43b0e79..68b9835 100644 --- a/WoADialer/WoADialer.csproj.user +++ b/WoADialer/WoADialer.csproj.user @@ -2,10 +2,10 @@ 30F105C9-681E-420b-A277-7C086EAD8A4E - false + true 10.8.0.2 Universal - true + false false false false @@ -17,7 +17,7 @@ SideloadOnly False - arm64 + arm True @@ -26,6 +26,12 @@ 10.8.0.2 Universal true + CopyToDevice + + + false + false + D:\Projects\woadialer\WoADialer\bin\ARM\Debug\AppX 192.168.1.3