要使敬酒通知在屏幕上可见,我要创建敬酒通知类型
Scenario = ToastScenario.Reminder
首先,我通过使用CoreDispatcher
对象在主线程中创建Toast通知,然后使用计时器更新Toast通知上的进度条。
我正在通过CoreDispatcher
对象进行的所有更新。
第一次运行正常。
当我发出导致显示新的Toast通知的请求时,首先我使用ToastNotificationManager.History.Remove(TAG,GROUP);
方法隐藏旧的通知,然后显示新的Toast通知。
隐藏第二个吐司之后,我再次启用第一个吐司通知。因此,首先,我打电话给节目再次显示第一个吐司通知,然后启用计时器,以与我一开始相同的方式发送关于吐司通知的更新。
问题是,当我的吐司通知再次出现在屏幕上时,它不断地消失。我可以看到烤面包通知持续闪烁。
仅当我将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吐司和Text吐司之间切换(多次切换,然后您将看到ProgressBar吐司开始闪烁)。从ProgressBar Toast开始。 对不起一些糟糕的代码,我不确定为什么最初不重现。