Уведомление Toasted с прогресс-баром не работает - PullRequest
0 голосов
/ 04 апреля 2019

Для того, чтобы всплывающие уведомления были видны на экране, я создаю всплывающее уведомление типа

Scenario = ToastScenario.Reminder

Сначала я создаю уведомление о тосте в главном потоке, используя объект CoreDispatcher, а затем использую таймер для обновления индикатора выполнения в моем уведомлении о тосте. Все обновления, которые я делаю, через CoreDispatcher объект.

В первый раз все работает нормально. Когда я делаю любой запрос, который вызывает отображение нового тост-уведомления, сначала я скрываю старое уведомление с помощью метода ToastNotificationManager.History.Remove(TAG,GROUP);, а затем я показываю новое тост-уведомление.

После сокрытия второго тоста я снова включаю уведомление о первом тосте. Поэтому сначала я вызываю шоу, чтобы снова отобразить первое уведомление о тосте, затем включаю таймер, который отправляет обновление уведомления о тосте точно так же, как я делал вначале.

Проблема в том, что когда мое всплывающее уведомление снова появляется на экране, оно непрерывно приходит и уходит. Я вижу непрерывное мерцание уведомления о тостах. Этот случай происходит, только когда я установил Scenario на ToastScenario.Reminder.

По умолчанию Scenario работает нормально.

Что именно я делаю неправильно в случае ToastScenario.Reminder.

необходимый код

 using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Background;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace App2
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }
        private void RegisterBackgroundTasks()
        {
            const string taskName = "ToastBackgroundTask";

            // If background task is already registered, then unregister it
            foreach (var bgTask in BackgroundTaskRegistration.AllTasks)
            {
                if (bgTask.Value.Name == taskName)
                {
                    bgTask.Value.Unregister(true);
                }
            }

            // Create the background task
            BackgroundTaskBuilder builder = new BackgroundTaskBuilder()
            {
                Name = taskName,
            };

            // Assign the toast action trigger
            builder.SetTrigger(new ToastNotificationActionTrigger());

            // And register the task
            BackgroundTaskRegistration registration = builder.Register();
        }
        protected override void OnActivated(IActivatedEventArgs args)
        {
            RegisterBackgroundTasks();
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // Ensure the current window is active
                Window.Current.Activate();
            }
            RegisterBackgroundTasks();
        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }
    }
}

MainPage.xaml

<Page
    x:Class="App2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


    <StackPanel>
        <Button  Width="200" Height="200" Click="Button_Click">Progress Bar Toast</Button>
        <Button  Width="200" Height="200" Click="Button_Click_1">Text Toast</Button>

    </StackPanel>

</Page>

MainPage.cs

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.Tasks;
using System.Timers;
using Windows.ApplicationModel.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;


// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace App2
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private Timer  playingTimeElapsedTimer;
        CoreDispatcher coreDispatcher;
        static NotificationManager aNotificationManager = new NotificationManager();
        public MainPage()
        {

            this.InitializeComponent();
            playingTimeElapsedTimer = new Timer(500);
            playingTimeElapsedTimer.Elapsed += PlayingTimeElapsedTimer_Elapsed;
        }


        private void PlayingTimeElapsedTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            count++;
            //Task.Run(()=> {
            //  coreDispatcher.TryRunAsync(CoreDispatcherPriority.Normal, () =>
            //{
            //System.Threading.Thread t1 = new System.Threading.Thread(() =>
            //{
                PlayerNotificationMessage aPlayerNotificationMessage = CreatToast();
                aNotificationManager.UpdatePlayerToastNotification(aPlayerNotificationMessage);
            //});
            //t1.Start();
            if (count == Total)
            {
                count = 0;
            }
        }


        double count = 0;
        double Total = 1000;

        private PlayerNotificationMessage CreatToast() {

            PlayerNotificationMessage aPlayerNotificationMessage = new PlayerNotificationMessage()
            {
                PlayPauseImage = "https://raw.githubusercontent.com/windows-toolkit/WindowsCommunityToolkit/master/build/nuget.png",
                PlayPauseText = "https://raw.githubusercontent.com/windows-toolkit/WindowsCommunityToolkit/master/build/nuget.png",
                SongImageUrl = "https://raw.githubusercontent.com/windows-toolkit/WindowsCommunityToolkit/master/build/nuget.png",
                NotificationMessage = new Windows.UI.Notifications.NotificationData()
                {
                    //SequenceNumber =0,
                    Values = {
                     { "progressValue", Math.Round(count/Total,2).ToString() },

                    { "progressValueString", count.ToString()+"/"+Total },
                    { "progressStatus", "" },
                    { "songTitle", "pawan" },
                    { "songTitle1", "tiwari" },
                    { "songTitle2", "test" },
                    }
                }

            };
            return aPlayerNotificationMessage;
        }
        private   void Button_Click(object sender, RoutedEventArgs e)
        {
            //System.Threading.Thread t = new System.Threading.Thread(() => {

                PlayerNotificationMessage aPlayerNotificationMessage = CreatToast();
                aNotificationManager.ShowPlayerToastNotification(aPlayerNotificationMessage);

                playingTimeElapsedTimer.Start();
            //});
            //t.Start();



        }

        private void  Button_Click_1(object sender, RoutedEventArgs e)
        {
                    NotificationMessage aPlayerNotificationMessage = new NotificationMessage();
                    aNotificationManager.ShowCards(aPlayerNotificationMessage);

        }


    }
}

PlayerNotificationMessage

using Microsoft.QueryStringDotNET;
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;

namespace App2
{
    public class PlayerNotificationMessage : NotificationMessage
    {

        public NotificationData NotificationMessage { get; set; }
        public string SongImageUrl { get; set; }
        public string PlayPauseText { get; set; }
        public string PlayPauseImage { get; set; }

        public override ToastContent CreateToastedContent()
        {
            return new ToastContent
            {
                //Scenario is type of call, so that user can not dismiss the music player on lock screen.
                Scenario = ToastScenario.Reminder,
                Launch = "action=dismiss",
                ActivationType = ToastActivationType.Background,
                Audio = new ToastAudio() { Silent = true },
                Visual = new ToastVisual
                {
                    BindingGeneric = new ToastBindingGeneric
                    {
                        Children =
                        {
                            new AdaptiveText()
                            {
                                HintWrap = false,
                                HintMaxLines = 1,
                                HintStyle = AdaptiveTextStyle.Title,
                                Text = new BindableString("songTitle")
                            },
                            new AdaptiveText
                            {
                                HintWrap = false,
                                HintMaxLines = 1,
                                HintStyle = AdaptiveTextStyle.Caption,
                                Text =  new BindableString("songTitle1")
                            },
                            new AdaptiveProgressBar()
                            {
                                Title = new BindableString("songTitle2"),
                                Value = new BindableProgressBarValue("progressValue"),
                                ValueStringOverride = new BindableString("progressValueString"),
                                Status = new BindableString("progressStatus")
                            }
                        },

                        AppLogoOverride = new ToastGenericAppLogo()
                        {
                            AlternateText = new BindableString("songTitle"),
                            Source = SongImageUrl
                        },
                        HeroImage = new ToastGenericHeroImage()
                        {
                            Source = SongImageUrl,
                            AlternateText = new BindableString("songTitle"),

                        }
                    }
                },
                Actions = new ToastActionsCustom()
                {
                    Buttons =
                    {
                        new ToastButton("Prev", new QueryString()
                        {
                            { "action", "previous" }

                        }.ToString() )
                        {
                                ActivationType = ToastActivationType.Background,
                                ActivationOptions = new ToastActivationOptions()
                                {
                                    AfterActivationBehavior = ToastAfterActivationBehavior.PendingUpdate
                            },
                            ImageUri = SongImageUrl,


                        },
                        new ToastButton(PlayPauseText, new QueryString()
                        {
                            { "action", PlayPauseText }

                        }.ToString() )
                        {
                            ActivationType = ToastActivationType.Background,
                            ActivationOptions = new ToastActivationOptions()
                            {
                                AfterActivationBehavior = ToastAfterActivationBehavior.PendingUpdate
                            },
                            ImageUri = PlayPauseImage

                        },
                        new ToastButton("Next", new QueryString()
                        {
                            { "action", "next" }

                        }.ToString() )
                        {
                            ActivationType = ToastActivationType.Background,
                            ActivationOptions = new ToastActivationOptions()
                            {
                                AfterActivationBehavior = ToastAfterActivationBehavior.PendingUpdate
                            },
                            ImageUri = SongImageUrl
                        },

                    },
                }
            };
        }
    }
}

NotificationMessage, IToastNotification, AudioPlayerNotifier

using Microsoft.QueryStringDotNET;
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;

namespace App2
{
    public  class NotificationMessage
    {
        public string Image => "https://cdn.builtinseattle.com/sites/www.builtinseattle.com/files/styles/company_logo/public/2018-06/Drift.png";
        /// <summary>
        /// Notification Tag identifier for toasted notification. 
        /// </summary>
        public string Tag => "TAG";
        /// <summary>
        /// Notification Group identifier for toasted notification. 
        /// </summary>
        public string Group => "GROUP";
        /// <summary>
        /// Create Toast notification object of give data.
        /// </summary>
        /// <returns>Toast content XML</returns>
        public virtual ToastContent CreateToastedContent() {
            ToastContent content = new ToastContent()
            {
                Launch = "app-defined-string",
                Duration = ToastDuration.Long,
                //ActivationType = ToastActivationType.Background,
                Scenario = ToastScenario.Reminder,
                Visual = new ToastVisual()
                {
                    BindingGeneric = new ToastBindingGeneric()
                    {
                        Children =
    {
        new AdaptiveText()
        {
            Text =  new BindableString("text"),
            HintMaxLines = 1
        },

        new AdaptiveText()
        {
            Text =  new BindableString("text")
        },

        new AdaptiveText()
        {
            Text = new BindableString("text")
        },

    },AppLogoOverride = new ToastGenericAppLogo() {
        Source = this.Image
    }
                    }
                },


            };
            return content;
        }

    }
    public interface IToastNotification<T> where T : NotificationMessage
    {
        void Show(T aNotificationMessage);
        void Update(T aNotificationMessage);
        void Hide();
    }
    public class AudioPlayerNotifier : IToastNotification<PlayerNotificationMessage>
    {
        /// <summary>
        /// Toast notifier
        /// </summary>
        private ToastNotifier toastNotifier;
        private PlayerNotificationMessage aPlayerNotificationMessage;

        /// <summary>
        /// 
        /// </summary>
        public AudioPlayerNotifier()
        {
            toastNotifier = ToastNotificationManager.CreateToastNotifier();
        }
        /// <summary>
        /// Hide toast notification.
        /// </summary>
        /// <param name="toastNotification"></param>
        public void Hide()
        {
        }
        /// <summary>
        /// Show the Audio Player toast notification.
        /// </summary>
        /// <param name="aNotificationModel"></param>
        public void Show(PlayerNotificationMessage aPlayerNotificationMessage)
        {
            var toastContent = aPlayerNotificationMessage.CreateToastedContent();
            var toastNotification = new ToastNotification(toastContent.GetXml())
            {
                Tag = aPlayerNotificationMessage.Tag,
                Group = aPlayerNotificationMessage.Group,
                Data = aPlayerNotificationMessage.NotificationMessage,
            };
            toastNotification.Dismissed += ToastNotification_Dismissed;
            this.aPlayerNotificationMessage = aPlayerNotificationMessage;
            this.toastNotifier.Show(toastNotification);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void ToastNotification_Dismissed(ToastNotification sender, ToastDismissedEventArgs args)
        {
            if (args.Reason == ToastDismissalReason.UserCanceled || args.Reason == ToastDismissalReason.TimedOut)
            {
                this.Show(aPlayerNotificationMessage);
            }
        }

        /// <summary>
        /// Update music player timeline.
        /// </summary>
        /// <param name="aNotificationMessage"></param>
        public void Update(PlayerNotificationMessage aNotificationMessage)
        {
            this.toastNotifier.Update(aNotificationMessage.NotificationMessage, aNotificationMessage.Tag, aNotificationMessage.Group);
        }
    }
}

CardsNotifier

using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;

namespace App2
{
    internal class CardsNotifier : IToastNotification<NotificationMessage>
    {
        /// <summary>
        /// Toast notifier
        /// </summary>
        private ToastNotifier toastNotifier;

        private ToastNotification toastedNotification;

        public CardsNotifier()
        {
            toastNotifier = ToastNotificationManager.CreateToastNotifier();
        }
        public void Hide()
        {

        }

        public void Show(NotificationMessage aNotificationMessage)
        {
            ToastContent toastContent = aNotificationMessage.CreateToastedContent();
            //show the notification.
            toastedNotification = new ToastNotification(toastContent.GetXml())
            {
                Tag = aNotificationMessage.Tag,
                Group = aNotificationMessage.Group,
            };
            this.toastNotifier.Show(toastedNotification);
        }

        public void Update(NotificationMessage aNotificationMessage)
        {
            //throw new System.NotImplementedException();
        }
    }
}

NotificationManager

public class NotificationManager
    {
        private IToastNotification<PlayerNotificationMessage> audioPlayerNotifier;
        private IToastNotification<NotificationMessage> cardsNotifier;

        private const string TAG = "TAG";
        private const string GROUP = "GROUP";
        private ToastNotifier toastNotifier;
        private bool IsPlayerActive = false;
        public NotificationManager( IToastNotification<PlayerNotificationMessage> audioPlayerNotifier, IToastNotification<NotificationMessage> cardsNotifier)
        {
            toastNotifier = ToastNotificationManager.CreateToastNotifier();
            this.audioPlayerNotifier = audioPlayerNotifier;
            this.cardsNotifier = cardsNotifier;
        }

        public NotificationManager()
        {
            toastNotifier = ToastNotificationManager.CreateToastNotifier();

            this.audioPlayerNotifier = new AudioPlayerNotifier();
            this.cardsNotifier = new CardsNotifier();
        }

        public void HideNotification()
        {
            ToastNotificationManager.History.Remove(TAG, GROUP);
            //ToastNotificationManager.History.Clear();
            //this.cardsNotifier.Hide();
            //this.audioPlayerNotifier.Hide();
        }

        public void ShowCards(NotificationMessage notificationMessage)
        {
            System.Diagnostics.Debug.WriteLine("####ShowCards");
            this.HideNotification();
            IsPlayerActive = false;
            cardsNotifier.Show(notificationMessage);
        }

        public void ShowPlayerToastNotification(PlayerNotificationMessage aNotificationModel)
        {
            System.Diagnostics.Debug.WriteLine("####ShowPlayerToastNotification");
            this.HideNotification();
            IsPlayerActive = true;
            this.audioPlayerNotifier.Show(aNotificationModel);
        }

        private object lockObject = new object();
        public void UpdatePlayerToastNotification(PlayerNotificationMessage aNotificationViewModel)
        {
            lock (lockObject)
            {
                if (!IsPlayerActive)
                {
                    IsPlayerActive = true;
                    System.Diagnostics.Debug.WriteLine("####UpdatePlayerToastNotification");
                    //If player is not active, only update toast will not work.
                    //First we need to show the toast notification.
                    //System.Diagnostics.Debug.WriteLine("Date before "+System.DateTime.Now);
                    //this.ShowPlayerToastNotification(aNotificationViewModel);
                    //Task.Delay(10).Wait();
                    //System.Diagnostics.Debug.WriteLine("Date after"+System.DateTime.Now);
                }
                else
                {
                    this.audioPlayerNotifier.Update(aNotificationViewModel);
                }
            }
        }
    }

Чтобы воспроизвести проблему, переключайтесь между тостами ProgressBar и Toast Text (несколько раз переключитесь, и тост ProgressBar начнет мигать). Начните с ProgressBar Тост. Извините за какой-то дерьмовый код, я не уверен, почему он изначально не воспроизводился.

...