Handling suspend, resume, and activation in windows 10 UWP - c#

In the windows 8.1 universal apps, the suspend/resume modes were handled using the NavigationHelper.cs ans SuspensionManager.cs classes included in the APP template. These classes doesn't seem to be there in the windows 10 UWP apps. Is there a way by which we can handle the suspend/resume states?

There's an interesting framework being developed by the community (but mostly I think Jerry Nixon, Andy Wigley etc.) called Template10. Template10 has a Bootstrapper class with OnSuspending and OnResuming virtual methods that you can override. I am not sure that there's an exact example of doing suspension/resuming yet with Template10, but the idea seems to be to make App.xaml.cs inherit from this Bootstrapper class so you can easily override the methods I mentioned.
sealed partial class App : Common.BootStrapper
{
public App()
{
InitializeComponent();
this.SplashFactory = (e) => null;
}
public override Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
// start the user experience
NavigationService.Navigate(typeof(Views.MainPage), "123");
return Task.FromResult<object>(null);
}
public override Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
// handle suspending
}
public override void OnResuming(object s, object e)
{
// handle resuming
}
}

The above solution will only work for people who install Template10.
The generic solution is,
paste these lines in the constructor of App.xaml.cs
this.LeavingBackground += App_LeavingBackground;
this.Resuming += App_Resuming;
It will look like this
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.LeavingBackground += App_LeavingBackground;
this.Resuming += App_Resuming;
}
These are the methods, although you can press TAB and they will autogenerate.
private void App_LeavingBackground(object sender, LeavingBackgroundEventArgs e)
{
}
private void App_Resuming(object sender, object e)
{
}
The methods LeavingBackground and the one not mentioned here EnteredBackground are newly added to uwp.
Before these methods we would use resuming and suspending to save and restore ui, but now the recommended place to do that work is here.Also these are the last places to perform work before the app is resumed. So the work on these methods should be small ui or other stuff like remaking values which are stale as a long held method here will affect app startup time while resuming.
Source
Windows dev material ,
Windoes dev material 2
Thanks , and have a good day.

Related

Alert Dialog in ViewModel - MVVMCross

In the ViewModel, I have Save method where I check isValid property.
If isValid is false, then I want to display an error message.
Since AlertDialog is platform specific, I wonder how do you handle that situation in the ViewModel?
public void Save()
{
if (isValid)
{
OnExit(this, null);
}
else
{
//issue an alert dialog here
}
}
Update
I have used the following plugin and added the following line of code as follows, but it throws an error.
else
{
Mvx.Resolve<IUserInteraction>().Alert("it is not valid");
}
Update 2
Chance.MvvmCross.Plugins.UserInteraction is a namespace but it is used as a type error.
Update 3
I have added Acr.UserDialogs plugin and called as follows, but I have got the same error.
Mvx.Resolve<IUserDialogs>().Alert("it is not valid");
Using ACR User Dialogs is the simplest approach.
In your App.cs (Core/PCL) you will need to register the interface:
public class App : MvxApplication
{
public override void Initialize()
{
// Example Other registrations
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
Mvx.RegisterSingleton<IUserDialogs>(() => UserDialogs.Instance);
}
}
Then you can call your alert form your ViewModel.
Mvx.Resolve<IUserDialogs>().Alert("it is not valid");
Note for Android Platform support
Then if you are supporting Android you will need to initialize UserDialog with an instance of the activity context. This will have to be done in each activity that you will be making use of UserDialogs or if you have a shared base activity you can do it there.
[Activity]
public class MainActivity : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.activity_main);
// Initialize Acr UserDialogs
UserDialogs.Init(this);
}
}
Alternatively
You can follow the Mvvmcross document on using platform specific implementations of an interface if you need a more custom modal implementation.
This is how I handle the Alert messages in the viewmodel. Try this.
await App.Current.MainPage.DisplayAlert("Active subscription required", "You do not have an active subscription for Part 2 exams", "OK");
There is an existing MvvmCross plugin called User Interaction that allows displaying alerts and collecting inputs from ViewModels.
From the author BrianChance:
Really simple, easy, beautiful ways to show a message box or to collect user input from your ViewModels
Check it out here and NuGet Link Here.
To install the plugin, make sure you override LoadPlugins in your SetUp Class on iOS and Android (and windows phone) like so:
public override void LoadPlugins(MvvmCross.Platform.Plugins.IMvxPluginManager pluginManager)
{
base.LoadPlugins(pluginManager);
pluginManager.EnsurePluginLoaded<Chance.MvvmCross.Plugins.UserInteraction>();
}
My approach is that i use an event for this scenario. My base class for my view models has a EventHandler OnUserNotification, where the views can kinda subscribe to. The UserNotificationType is just an enum and i let the view kinda decide how it reacts to the situation.
The property:
public EventHandler<UserNotificationType> OnUserNotification { get; set; }
The call:
if (OnUserNotification != null)
{
OnUserNotification.Invoke(this, UserNotificationType.ENetworkError);
}
In the view:
private void onUserNotification(object sender, UserNotificationType userNotificationType)
{
// Do Something like showing a Snackbar, AlertDialog, etc...
}
Of course you can make the eventtype more complex if needed.
Didnt try the plugin which got suggested by wishmaster though, so that might be a smoother implementation?
Use Acr.UserDialogs. There is a great examples on github
You can grab it on nuget
It works well with dependency injection or a static singleton UserDialogs.Instance

MMVM Light NavigationService vs NavigationHelper in Universal App

I was wondering if someone could shed some light on how best handle the navigation service in a universal app as I'm confused on how to handle this.
If I create a blank application and just use a basic NavigationService as suggested in tutorial for mvvmlight and universal app, it doesn't handle the windows phone hardware back key and when I click it, it just closes the wp8.1 app.
I found an article that suggest to add the HardwareButtons.BackPressed to the app.cs, but I don't like the idea to be honest. Maybe it's ok? Let me know.
The basic IHavigationService is registered in the SimpleIocand is injected in via the constructor but as mentioned, this does not handle the back key for wp8 apps.
When I create a universal hub app, it doesn't use mvvmlight and it creates a navigationHelper class which contains the necessary code to handle both windows and wp apps but every time it is used, the declaration is done in the code behind of the relevant page rather than in the ViewModel.
Any suggestions on how best handle this?
Thanks.
You can combine the best of both world:
In App.xaml.cs, you subscribe to HardwareButtons.BackPressed event:
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
if(NavigationService.CanGoBack)
{
NavigationService.GoBack();
e.Handled = true;
}
}
Create NavigationService class:
public static class NavigationService
{
public static Dictionary<Pages, Type> PageDictionary = new Dictionary<Pages, Type>();
public static Frame MainFrame;
public static void Configure(Frame frame)
{
PageDictionary.Add(Pages.MainPage, typeof(MainPage));
PageDictionary.Add(Pages.Setting, typeof(SettingPage));
MainFrame = frame;
}
internal static void GoBack()
{
if (MainFrame.CanGoBack)
MainFrame.GoBack();
}
internal static bool CanGoBack
{
get
{
return MainFrame.CanGoBack;
}
}
internal static void NavigateTo(Pages page, object parameter)
{
MainFrame.Navigate(PageDictionary[page], parameter);
}
}
Pages is an enum
In App.xaml.cs, after you initiate rootFrame, config the navigation service:
NavigationService.Configure(rootFrame);

Windows Mobile Application exiting unexpectedly

I have a fairly complex c# application that runs on Windows Mobile 5.0 and later. It includes code that uses SQL CE, updates GPS coordinatess on a seperate thread, and also uses Microsoft Sync Framework in a seperate thread to sync to a server in the background. The application generally runs fairly well, but every so often out in production, the application main window disappears.
I have a code like to the following in the Program.cs file:
static class Program
{
private static NLog.Logger _logger = NLog.LogManager.GetLogger("Program");
[MTAThread]
static void Main()
{
try
{
_logger.Info("Program V {0} starting.", Utility.AppVersion);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new MainForm());
_logger.Info("After Application.Run().");
}
catch (Exception ex)
{
_logger.ErrorException("Exception occurred.", ex);
}
}
static void MobileDevice_Hibernate(object sender, EventArgs e)
{
_logger.Info("Hibernate was received.");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_logger.ErrorException("Unhandled exception was thrown", e.ExceptionObject as Exception);
}
}
I see the starting info log as expected, and when the application disappears, I also get the After Application.Run() message. But I do not get the messages logged in the MainForm.Closing event, so it seems that it is never called. I also do not get any exception logged from either the exception handler around the Application.Run or the UnhandledException handler. I thought it might be related to running low/out of memory and that is why I have the Hibernate event wired up as well. But I do not get the Hibernate event either.
Any help, or suggestions would be appreciated as I am out of ideas and things to check.
Well, at the risk of stating the obvious, something is crashing your app that is preventing your Closing Event from firing.
For your items that run on separate threads (most likely suspects), can you create class containers for them that implement IDisposable? Then, you could place NLog references in your Dispose() methods to record your data.
public class FirstClass : IDisposable {
private bool isDisposed;
public FirstClass() {
isDisposed = false;
}
public void Dispose() {
_logger.Info("FirstClass is done.");
isDisposed = true;
}
public void Method1() {
while (!isDisposed) {
// your code here
}
}
}
You would need to create a way so that _logger can be accessible to this class, however.
Bugs in threads can be hard to catch.

Sharing Media Playback Between Pages with Windows Phone 7 Media Player

What I want to achieve:
I want to initiate audio playback from an mp3 and/or aac HTTP stream in a WP7 application
I want to initiate playback from a specific 'PhoneApplicationPage' instance, but still allow navigation to other pages whilst maintaining playback without any interuption - i.e. I want playback to be 'application-scope'
I want to be able to 'seek' within my media
I playback to continue whilst the phone is locked
What I have tried:
MediaElement:
If the MediaElement is not owned by a page, no sound is produced when Play() is called, despite no exceptions being thrown.
After following 'http://blog.jayway.com/2010/10/04/enable-background-audio-for-multiple-pages-in-windows-phone-7/', playback still resets between page transitions
It also seems like a quite a hacky way of doing things...
Microsoft.Xna.Framework.MediaPlayer:
Works, but "MediaPlayer.PlayPosition" is read-only, and there is no seek method.
See post: 'http://forums.create.msdn.com/forums/t/17318.aspx' - Apparently this is by design due to XBox constraints with Xna (?!)
Microsoft Silverlight Media Framework:
http://smf.codeplex.com/
My favourite option, as it seems very comprehensive
Downloaded 'Silverlight Media Framework 2.3, WP7 specific' assemblies from:
http://smf.codeplex.com/releases/view/57991#DownloadId=190196
I know this is hacky, but to get something working, in the code below, the 'SMFPlayer' is static, and added to each page's layout on navigation.
If the 'SMFPlayer' is not owned by a page, no sound is produced when Play() is called, despite no exceptions being thrown.
Playback still resets between page transitions...
Code:
using System;
using System.Diagnostics;
using Microsoft.Phone.Controls;
using Microsoft.SilverlightMediaFramework.Core;
using Microsoft.SilverlightMediaFramework.Core.Media;
using Microsoft.SilverlightMediaFramework.Plugins.Primitives;
namespace WindowsPhoneApplication1
{
public partial class MainPage : PhoneApplicationPage
{
public static readonly SMFPlayer Player = new SMFPlayer();
static MainPage()
{
Player.VolumeLevel = 1.0f;
Player.Playlist.Add(new PlaylistItem {MediaSource = new Uri("http://smf.vertigo.com/videos/wildlife.wmv", UriKind.Absolute)});
Player.LogLevel = LogLevel.All;
Player.LogEntryReceived += PlayerLogEntryReceived;
}
// Constructor
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
LayoutRoot.Children.Add(Player);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
LayoutRoot.Children.Remove(Player);
}
private static void PlayerLogEntryReceived(object sender, CustomEventArgs<LogEntry> e)
{
Debug.WriteLine(e.Value.Severity + e.Value.Message + e.Value.Type);
}
private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.RelativeOrAbsolute));
}
}
}
Does anyone have any idea how I can satisfy my requirements?
Example code?
From an architectural point of view, what I really want is a Media Service which i can send streaming URLs to without caring about which page is currently shown.
I eventually found a simple, but effective solution:
http://blog.reis.se/post/Enable-background-audio-for-multiple-pages-in-Windows-Phone-7-e28093-Take-2.aspx
In App.xaml:
<APPLICATION.RESOURCES>
<MEDIAELEMENT x:key="GlobalMedia"></MEDIAELEMENT>
</APPLICATION.RESOURCES>
In App.xaml.cs:
public static MediaElement GlobalMediaElement
{
get { return Current.Resources["GlobalMedia"] as MediaElement; }
}
In your page:
public partial class MyPage : PhoneApplicationPage
{
MediaElement MEAudio;
public MainPage()
{
InitializeComponent();
MEAudio = App.GlobalMediaElement;
}
private void OnSomeEvent(object sender, RoutedEventArgs e)
{
MEAudio.xxxxx();

How to create a Task Scheduler App

I have been task with (ha) creating an application that will allow the users to schedule a command line app we have with a parameter.
So the command line app takes an xml and "runs it"
So bottom line I either need to create a windows service or learn how to interact with the Task Scheduler service already running on the box (version 1 Xp /2003)
At first I though it would be easy have a service run and when a job is submitted, calculate the time between now and run and set up a timer to wait that amount of time. This is better then checking every minute if it's time to run.
Were I hit a wall is I relized I do not know how to communicate with a running windows service. Except maybe create a file with details and have the service with a file watcher to load the file and modify the schedule.
So the underlying questions are how can I execute this psedo code
from client
serviceThatIsRunning.Add(Job)
Or ineracting with the task schedule or creating .job files using c# 3.5
Edit:
To clarify I created a small sample to get my thoughts on "paper"
So I have a Job Class
public class Job
{
#region Properties
public string JobName { get; set; }
public string JobXML { get; set; }
private Timer _JobTimer;
public Timer JobTimer
{
get
{
return _JobTimer;
}
}
#endregion
public void SetJobTimer(TimeSpan time)
{
if (_JobTimer != null)
{
_JobTimer.Dispose();
}
_JobTimer = new Timer(new TimerCallback(RunJob), null, time, time);
}
private void RunJob(Object state)
{
System.Diagnostics.Debug.WriteLine(String.Format("The {0} Job would have ran with file {1}", JobName, JobXML));
}
public override string ToString()
{
return JobName;
}
public void StopTimer()
{
_JobTimer.Dispose();
}
}
Now I need to create an App to house these Jobs that is constantly running, that is why I though of Windows Services, and then a Windows app to allow the user to work with the Job List.
So the question is if I create a Windows Service how do I interact with methods in that service so I can change the JobList, add, delete, change.
Here is a small windows app I created to show that the Job class does run. Interesting point, If I am doing this correctly, I do not add the Job to a listbox and the Add method exits the Job Timer portion still runs and does not get picked up by the Garbage Collector.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnAddJob_Click(object sender, EventArgs e)
{
Job job = new Job();
job.JobName = txtJobName.Text;
job.JobXML = txtJobXML.Text;
job.SetJobTimer(new TimeSpan(0, 0, Convert.ToInt32(JobTime.Value)));
// ??Even If I don't add the Job to a list or ListBox it seems
// ??to stay alive and not picked up by the GC
listBox1.Items.Add(job);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
Job job = listBox1.Items[listBox1.SelectedIndex] as Job;
txtJobName.Text = job.JobName;
txtJobXML.Text = job.JobXML;
}
}
private void btnRemove_Click(object sender, EventArgs e)
{
Job job = listBox1.Items[listBox1.SelectedIndex] as Job;
job.StopTimer();
listBox1.Items.Remove(job);
}
private void btnCollect_Click(object sender, EventArgs e)
{
GC.Collect();
}
}
If you want to schedule a task using the task scheduler it could be as simple as below. You just need to customize the command line arguments that you pass to schtasks for your needs. See this link for a detailed explanation of command line arguments.
Process p = Process.Start("schtasks", commandArgs);
p.WaitForExit();
If you want to start multiple tasks that run at different time intervals, you can
create for instance a class JobThread that defines a timer that is initialized using the Initialize method:
m_timer = new Timer(new TimerCallback(this.timerHandler), null, this.Interval, this.Interval);
Furthermore, this class defines a List of Job objects. These jobs are executed from the timerHandler.
Finally, you create a singleton JobManager class that defines a Start and Stop method.
In the Start method you do something like this:
foreach (var jobThread in this.m_jobThreads)
{
jobThread.Initialize();
}
This JobManager has also a Initiliaze method that accepts a XmlNode parameter. This method will parse the Xml-job you pass from the command-line.
There was an answer on this thread that is no longer there but, I am going to try to create a listener by keeping a port open
WCF through Windows Services
http://msdn.microsoft.com/en-us/library/ms733069.aspx
Also adding the attribute
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
Helps to keep state of the service.

Categories