Hi i want my app to navigate to a page when i receive a push toast notification. My code is as follows:-
ParsePush.ToastNotificationReceived += OnPushNotification;
This is to handle the event of push
private async void OnPushNotification(object sender, Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs e)
{
var AdFrame = Window.Current.Content as Frame;
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey("Suspended"))
{
String value = localSettings.Values["Suspended"].ToString();
if (value != null)
{
if (value == "false")
{
AdFrame.Navigate(typeof(Ad));
}
}
}
}
I get a Null Reference Error at var AdFrame = Window.Current.Content as Frame;
I have added this code in App.xaml.cs .I just want to navigate to the Ad Page from current page , whatever page maybe active. I am pretty new to windows , any help will be appreciated.
You will need to display a toast notification instead:
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(
ToastTemplateType.ToastImageAndText02);
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
stringElements.Item(0).AppendChild(toastXml.CreateTextNode("Hello world!"));
IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
XmlAttribute launchAttribute = toastXml.CreateAttribute("launch");
launchAttribute.Value = "pass data here"; // TODO: pass data here
toastNode.Attributes.SetNamedItem(launchAttribute);
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
When user clicks on the toast notification, you can handle the App launch event and then read the data.
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// ...
MainPage page = rootFrame.Content as MainPage;
page.ParseData(e.Arguments);
}
Related
I'm trying to make an app open a window for each file.
-- Code ---
App.cs:
protected async override void OnFileActivated(FileActivatedEventArgs Args)
{
//Opens Main Page
base.OnFileActivated(Args);
var RF = new Frame();
var MW = new MainPage();
AppWindow appWindow = await AppWindow.TryCreateAsync();
var TB = appWindow.TitleBar;
RF.Navigate(typeof(MainPage), Args);
ElementCompositionPreview.SetAppWindowContent(appWindow, RF);
appWindow.Equals(MW);
Window.Current.Equals(MW);
await appWindow.TryShowAsync();
TB.ButtonHoverBackgroundColor = Colors.White;
TB.ButtonHoverForegroundColor = Colors.Black;
TB.ButtonBackgroundColor = Colors.Transparent;
TB.ButtonPressedBackgroundColor = Colors.WhiteSmoke;
TB.ButtonPressedForegroundColor = Colors.Black;
TB.ButtonInactiveBackgroundColor = Colors.Transparent;
TB.ButtonInactiveForegroundColor = Color.FromArgb(1, 3, 165, 252);
TB.ExtendsContentIntoTitleBar = true;
Window.Current.Activate();
}
MainPage.cs:
protected override async void OnNavigatedTo(NavigationEventArgs EvArgs)
{
//File opened arguments
base.OnNavigatedTo(EvArgs);
var Args = EvArgs.Parameter as IActivatedEventArgs;
var FArgs = Args as FileActivatedEventArgs;
string Value = GetText(REB);
string SecValue = GetText(RTB);
if (Args != null)
{
//Check if the app is opened by file
if (Args.Kind == ActivationKind.File)
{
//Set file content
TXTFile = FArgs.Files[0] as StorageFile;
if (Value == "")
{
var Str = await TXTFile.OpenReadAsync();
ContentDialog ED2 = FileSaveDialog;
ED2.PrimaryButtonClick += ED2_PrimaryButtonClick;
void ED2_PrimaryButtonClick(ContentDialog Sender, ContentDialogButtonClickEventArgs DialogEvArgs)
{
//Save the file if it isn't saved
Save();
}
ED2.SecondaryButtonClick += ED2_SecondaryButtonClick;
void ED2_SecondaryButtonClick(ContentDialog Sender, ContentDialogButtonClickEventArgs DialogEvArgs)
{
//Don't save the file
//Set document content
REB.Document.LoadFromStream(TextSetOptions.FormatRtf, Str);
RTB.Document.LoadFromStream(TextSetOptions.FormatRtf, Str);
Str.Dispose();
}
ED2.CloseButtonClick += ED2_CloseButtonClick;
void ED2_CloseButtonClick(ContentDialog Sender, ContentDialogButtonClickEventArgs DialogEvArgs)
{
//Cancel the action
}
await ED2.ShowAsync();
Str.Dispose();
}
else
{
//Set document content
var Str = await TXTFile.OpenReadAsync();
REB.Document.LoadFromStream(TextSetOptions.FormatRtf, Str);
RTB.Document.LoadFromStream(TextSetOptions.FormatRtf, Str);
Str.Dispose();
}
}
}
else
{
//If there are no arguments, the file, and the RichEditBox should both remain empty
}
}
public string GetText(RichEditBox RichEditor)
{
RichEditor.Document.GetText(TextGetOptions.FormatRtf, out string Text);
var Range = RichEditor.Document.GetRange(0, Text.Length);
Range.GetText(TextGetOptions.FormatRtf, out string Value);
return Value;
}
Note:
the GetText method used is equivalent to RichEditBox.Document.GetText(TextGetOptions.FormatRtf, out string Value);
REB is the main workspace for the user to type in
RTB is the box that is compared with REB to see if the contents are saved or not (if the contents are saved, the GetText method should return their values equal)
Expected behavior:
If the app has a window active with text, the app should open a file on double click in a secondary window. Else, if the text is equal to "", the app should replace it with whatever is in the file.
Actual behavior:
The app overrides the text, crashes, makes windows randomly, or creates black windows that can only be killed with Task Manager or Visual Studio
I'm not sure what is the file type that you are using so I didn't check the text part. But I have to say that the way you are creating a new window is not correct. If you want to open a new window every time when you open a new file, you don't have to call Window.Current.Activate(); every time. I've made a simple demo that you could check.
In App.xaml.cs:
protected async override void OnFileActivated(FileActivatedEventArgs args)
{
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();
// Place the frame in the current Window
Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage), args.Files);
Window.Current.Activate();
}
else
{
AppWindow appWindow = await AppWindow.TryCreateAsync();
Frame appWindowContentFrame = new Frame();
appWindowContentFrame.Navigate(typeof(MainPage),args.Files);
ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
await appWindow.TryShowAsync();
}
}
When you launch the app for the first time, you should go through the normal launch process. When the app is launched more than onetime, then you could create a new window with AppWindow.
In MainPage.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// this is the file you need
var d = e.Parameter;
}
You could try this code first to make sure that your window is created and shown correctly.
I'm currently working on a winforms app which after certain action sends a notification to user, when activated(clicked) it opens a link. So I can send the notification, I can open the link with toast.Activated but when banner disappear and gets in to the action center when I click on the notification it doesn't activate. So, I have searched a lot but couldn't find a way to activate the notification on action center.
Here is the code I'm currently using to send notification.
{
public void Toasty()
{
// Get a toast XML template
Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText04);
// Fill in the text elements
Windows.Data.Xml.Dom.XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
stringElements[0].AppendChild(toastXml.CreateTextNode("Header"));
stringElements[1].AppendChild(toastXml.CreateTextNode("Message"));
stringElements[2].AppendChild(toastXml.CreateTextNode("From"));
ToastNotification toast = new ToastNotification(toastXml);
toast.Activated += toast_Activated;
//toast.SuppressPopup = true;
ToastNotificationManager.CreateToastNotifier("App").Show(toast);
}
async void toast_Activated(ToastNotification sender, object args)
{
await Launcher.LaunchUriAsync(new Uri("http://www.google.com"));
}
}
You don't need raw xml for this, get this nuget package :
Microsoft.Toolkit.Uwp.Notifications, then use the ToastContentBuilder to build a toast notification, it's easier and cleaner:
// Construct the visuals of the toast (using Notifications library)
ToastContent toastContent = new ToastContentBuilder()
.AddToastActivationInfo("action=viewConversation&conversationId=5", ToastActivationType.Foreground)
.AddText("Hello world!")
.GetToastContent();
// And create the toast notification
var toast = new ToastNotification(toastContent.GetXml());
// And then show it
DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
Now for the activation part:
//Another way of creating a notification
public void CreateAndShowPrompt(string message)
{
ToastContent toastContent = new ToastContent()
{
Launch = "bodyTapped",
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = message
},
}
}
},
Actions = new ToastActionsCustom()
{
Buttons = { new ToastButton("Yes", "Yes"), new ToastButton("No", "No") }
},
Header = new ToastHeader("header", "App", "header")
};
var doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
var promptNotification = new ToastNotification(doc);
promptNotification.Activated += PromptNotificationOnActivated;
DesktopNotificationManagerCompat.CreateToastNotifier().Show(promptNotification);
}
Event handler :
private void PromptNotificationOnActivated(ToastNotification sender, object args)
{
ToastActivatedEventArgs strArgs = args as ToastActivatedEventArgs;
switch (strArgs.Arguments)
{
case "Yes":
//stuff
break;
case "No":
//stuff
break;
case "bodyTapped":
//stuff
break;
}
}
This works in all cases, even when the toast is pushed back to the action center.
You can see it in action in an app that i made: NetStalker
This is the suggested code in the App class from the Template10 article on implementing a shell:
public override Task OnInitializeAsync(IActivatedEventArgs args)
{
var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include);
Window.Current.Content = new Views.Shell(nav);
return Task.FromResult<object>(null);
}
The new shell object is assigned to Windows.Current.Content.
This is the suggested code for opening a secondary window (not with a shell), from the Template10 Secondary window example code:
var control = await NavigationService.OpenAsync(typeof(MySecondaryPage), null, Guid.NewGuid().ToString());
control.Released += Control_Released;
What is the relationship between Windows.Current.Content and the secondary window?
What is the relationship between Windows.Current.Content and the secondary window?
Actually, The NavigationService.OpenAsync method internally invoke ViewService.OpenAsync.
public async Task<IViewLifetimeControl> OpenAsync(UIElement content, string title = null,
ViewSizePreference size = ViewSizePreference.UseHalf)
{
this.Log($"Frame: {content}, Title: {title}, Size: {size}");
var currentView = ApplicationView.GetForCurrentView();
title = title ?? currentView.Title;
var newView = CoreApplication.CreateNewView();
var dispatcher = DispatcherEx.Create(newView.Dispatcher);
var newControl = await dispatcher.Dispatch(async () =>
{
var control = ViewLifetimeControl.GetForCurrentView();
var newWindow = Window.Current;
var newAppView = ApplicationView.GetForCurrentView();
newAppView.Title = title;
// TODO: (Jerry)
// control.NavigationService = nav;
newWindow.Content = content;
newWindow.Activate();
await ApplicationViewSwitcher
.TryShowAsStandaloneAsync(newAppView.Id, ViewSizePreference.Default, currentView.Id, size);
return control;
}).ConfigureAwait(false);
return newControl;
}
From the above code, you could get the app's Window(Singleton) has not been changed, when the second window activated, the Content of Window was replaced with second page. And when the previous window activated the Windows.Current.Content will turn the fist page back. And you could verify this with Window.Current.Activated event.
Window.Current.Activated += Current_Activated;
private void Current_Activated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
{
// check the sender
}
I am currently working on Windows 8.1 Push Notification part. I have read different links and found that first we need to register the app and get all the information like SID and Client Secret and send to our server team so they can send push notification.
Then after this, I implemented the following code at my side to get channelUri and Expiration date of that Uri from WNS.
PushNotificationChannel channel = null;
try
{
channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
if (channel != null)
{
var notificationUri = channel.Uri;
var expiration_time = channel.ExpirationTime;
}
channel.PushNotificationReceived += channel_PushNotificationReceived;
}
catch (Exception ex)
{
if (ex != null)
{
System.Diagnostics.Debug.WriteLine(ex.HResult);
}
}
I have received all the values perfectly and my server team added a logic to send me push notification. Now, the problem which I am facing is that I am not aware how to display the received push notification sent by server to that user. Also, can we display the notification is the app is not running or is in background?
Background Tasks solved my problem.
First you need to create a WindowsRuntimeComponent Project and add the code below
public sealed class PushNotification:IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
RawNotification notification = (RawNotification)taskInstance.TriggerDetails as RawNotification;
if (notification != null)
{
ToastTemplateType toastTemplate = ToastTemplateType.ToastImageAndText01;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
var textElemets = toastXml.GetElementsByTagName("text");
textElemets[0].AppendChild(toastXml.CreateTextNode(notification.Content));
var imageElement = toastXml.GetElementsByTagName("image");
imageElement[0].Attributes[1].NodeValue = "ms-appx:///Assets/50.png";
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastXml));
}
}
}
Then register the background task in any of the page( i added in Home Page) using below code
private async void RegisterBackgroundTask()
{
await BackgroundExecutionManager.RequestAccessAsync();
try
{
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
try
{
task.Value.Unregister(false);
}
catch
{
//
}
}
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = "Push Notifcation Task";
builder.TaskEntryPoint = typeof(PushNotification).FullName;
builder.SetTrigger(new PushNotificationTrigger());
builder.Register();
}
catch(Exception e)
{
if(e != null)
{
System.Diagnostics.Debug.WriteLine(e.HResult);
System.Diagnostics.Debug.WriteLine(e.InnerException);
}
}
}
Please don't forget to add this background task in Declarations section in Package.appmanifest file and name of Entry Point should match with builder.TaskEntryPoint = typeof(PushNotification).FullName; else you will get exception.
Hope it helps someone.
I followed the msdn tutorial and another tutorial, but I don't know what I'm doing wrong. In app.xaml.cs, I have the code
protected override void OnFileActivated(FileActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
}
var p = rootFrame.Content as MainPage;
p.FileEvent = args;
Window.Current.Activate();
}
In MainPage.xaml.cs I have the code
private FileActivatedEventArgs _fileEventArgs = null;
public FileActivatedEventArgs FileEvent
{
get { return _fileEventArgs; }
set { _fileEventArgs = value; }
}
and
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//get the args
if (FileEvent != null && FileEvent.Files.Count > 0)
{
titleText.Text = FileEvent.Files[0].Path.ToString();
}
}
which is called in the MainPage constructor after this.InitializeComponent().
I'm not sure how to debug it. When I double click on an mp3 file that is associated with the app, the app opens but does not start, and the file has the waiting pointer icon until I close the app, then I receive an error that says The App didn't start in the required time. If the app is already open when I click on the file, nothing happens, and when I close the app it says The Remote procedure call failed.
I found the answer, I had put the entry point to MainPage.xaml, but changing it to App.xaml.cs fixed it so it actually called OnFileActivated(). I also changed the OnFileActivated code to
protected override void OnFileActivated(FileActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(MainPage)))
{
throw new Exception("Failed to create initial page");
}
}
var p = rootFrame.Content as MainPage;
if (p != null) p.FileEvent = args;
p.MainPage_Loaded(null, null);
Window.Current.Activate();
}
calling the public method p.MainPage_Loaded() in MainPage.xaml.cs from App.xaml.css was the final touch that allowed me to use the method without creating a new frame if the app was already open.