WP7/8 Call a DispatcherTimer tick event in the background/lock screen - c#

I am working on a timer application for Windows Phone, and I am trying to make it so that if the remaining time on the timer is zero, a sound from a BackgroundAudioPlayer will play, regardless of whether or not the application is active, inactive, or under lock.
Currently, my issue is that the tick events don't actually do anything while the application isn't active. As soon as the user goes back into the application, the tick events run to the point that they would've otherwise, but the sound effect (or anything else) wont actually play unless the application is active, or switches to being active.
I do have in my Page.xaml.cs:
PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
The relevant code is:
void dispatcherTimer_Tick(object sender, EventArgs e)
{
var remaining = this.EndTime - DateTime.Now;
int remainingSeconds = (int)remaining.TotalSeconds;
this.timeSpan.Value = TimeSpan.FromSeconds(remainingSeconds);
if (remaining.TotalSeconds <= 0)
{
this.dispatcherTimer.Stop();
button1.Visibility = Visibility.Collapsed;
button6.Visibility = Visibility.Visible;
this.EndTime = DateTime.MinValue;
this.timeSpan.Value = TimeSpan.FromSeconds(0);
BackgroundAudioPlayer.Instance.Play();
}
}
What can I do to make the tick events run while the application is under the lockscreen, or other wise not active?

Windows Phone has strict limits on background working. May be you need permission to work under lockscreen?
http://developer.nokia.com/community/wiki/Run_Windows_Phone_application_under_lock_screen
But it only stays application active under lockscreen, but not when user press windows or closes your app.

Related

WPF - Pop a Loading window when busy

I have to show a Window on an application that is not very well thought. The calls from every window are made from the same thread, no background workers. The application is rather yuge, so I can't just go around implementing BW pattern. Problem is, some of those actions take a while (around 5-10 seconds) and the whole app would turn Not Responding while waiting.
My idea was to implement some kind of watchdog on a background thread that would pop a window whenever I set a flag (App.Loading) in order to let the user know that something is going on.
In order to do that, I put this in the main menu
public Menu()
{
ShowInTaskbar = true;
InitializeComponent();
Debug.Ventana = "Menu";
App.Menu = this;
Loading = new Thread(new ThreadStart(CheckLoading));
Loading.SetApartmentState(ApartmentState.STA);
Loading.Start();
}
private void CheckLoading()
{
Loading load = new Andrei.Loading("Cargando datos")
{
ShowInTaskbar = false,
Topmost = true
};
while(true)
{
if (App.Loading && !load.IsVisible)
load.Show();
if (!App.Loading && load.IsVisible)
load.Hide();
}
}
Problem is, sometimes the window does not show up, and when it does, the animation isn't working (it's a small window with a string and an Indeterminate Progress Bar), which must be because the main thread is frozen by the while(true). I've tried putting the loop in yet another thread, but I can't access the window from another thread to hide and show it. I've tried putting a BW on the window to check for progress, but of course, after completing the first cycle, it doesn't go looking for the flag anymore.
Any other suggestions than completely redesigning the application to use BW for any and all time-taking processes?

UWP: Detect app gaining/losing focus

I want to be able to prevent the screen saver from triggering while my app is in use by using the DisplayRequest class, but I only want to do this while it's the active app. If the user switches to another window/app then I want to act like a good citizen and allow the screensaver again.
I can't see an obvious way to detect when a UWP app gets/loses focus (or is activated/deactivated) and a quick search around doesn't offer any insights. Can anyone point me in the right direction?
It's actually quite simple:
Window.Current.Activated += Current_Activated;
private void Current_Activated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
{
if (e.WindowActivationState == CoreWindowActivationState.Deactivated)
{
// do stuff
}
else
{
// do different stuff
}
}
We can use CoreWindow.Activated event to detect when a UWP app is activated or deactivated. This method is fired when the window completes activation or deactivation. And for a UWP app, we usually only have one window. So we can add some code like following in Application.OnLaunched method to detect:
Window.Current.CoreWindow.Activated += (sender, args) =>
{
if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
{
System.Diagnostics.Debug.WriteLine("Deactivated " + DateTime.Now);
}
else
{
System.Diagnostics.Debug.WriteLine("Activated " + DateTime.Now);
}
};
Besides this, you can also use CoreApplication.GetCurrentView method or CoreWindow.GetForCurrentThread method to get the CoreWindow.
You should not handle the changes of app's activation state.
Please, refer to How to prevent screen locks in your UWP apps.
Automatic request handling
Without any additional coding, though, your RequestActive() call will also be deactivated when your app no longer has the focus—in other words, when your app goes into a suspended state. On Windows Phone mobile and on a Windows 10 PC or Surface Pro in Tablet mode, “your app no longer having focus” means whenever your app is no longer in the foreground (snapped apps still count as being in the foreground, by the way). On a Windows 10 PC in desktop mode, however, it will mean whenever your app is minimized. In desktop mode, note that even when another app window covers up your app window, your app is still considered by the UWP app lifecycle to be running in the foreground.
The really cool thing is that when your app comes back into the foreground or gets de-minimized, the RequestActive() call will automatically get reactivated. You don’t have to do a thing!
This also means that if another app happens to make a request to keep the display active, it cannot hijack the behavior of every other app on the same device. The request is only good as long as the user is working with that app. Once the app is dismissed or minimized, Windows 10 goes back to its regular power conservation habits, even if the app forgets to call RequestRelease().
Finally, when your app is terminated, all remaining display active requests are automatically cleaned up for you.
It's all made for your needs.
I use the visibility changed event on the home window. The event is not fired when opening or closing a new window within the app.
Window.Current.VisibilityChanged += OnVisibilityChanged;
/// <summary>
/// When the window visibility changes, the stuff happens
/// </summary>
/// <param name="sender">object sender</param>
/// <param name="e">VisibilityChangedEventArgs e</param>
private void OnVisibilityChanged(object sender, VisibilityChangedEventArgs e)
{
if (!e.Visible)
{
// do stuff
}
else
{
// do other stuff
}
}

Windows Phone alarm constantly turning itself back on

I'm trying to write an alarm clock app for Windows Phone that requires the user to solve a math problem upon the ringing of the alarm. Right now I'm stuck, I've got the MainPage containing the settings for turning on the alarm, and when the alarm rings the user is redirected to another xaml page, one that requires the user to enter the answer to a randomly generated math problem in order to turn off the alarm. My problem is, once the user solves the problem and taps the check box, the app is supposed to first set the alarmSet value to false, and redirect the user back to the mainPage:
private void Solve_Click(object sender, EventArgs e)
{
this.userSolve = Convert.ToInt32(answerInput.Text);
if (userSolve != answer)
{
MessageBox.Show("Incorrect");
//userAnswerInt = Convert.ToInt32(answerInput.Text);
}
else if (userSolve == answer)
{
MainPage.alarmSet.Value = false;
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}
And then when the user arrives at the mainPage, the OnLoaded method is supposed to stop the alarm sound and reset everything back to normal:
public async void OnLoaded(object sender, EventArgs e)
{
this.timer.Stop();
this.alarmSound.Stop();
alarmSet.Value = false;
this.notificationSwitch.IsChecked = alarmSet.Value;
this.timePicker.Value = new DateTime(1, 1, 1,
alarmTime.Value.Hours,
alarmTime.Value.Minutes,
0
);
if (alarmSet.Value == true)
this.alarmTimeText.Text = alarmTimeString;
else if (alarmSet.Value == false)
this.alarmTimeText.Text = "alarm off";
But the problem is, every time the user solves the math problem, they're taken back to the main page and immediately redirected back to the alarm ringing page, because the alarm is still turned on. This creates an infinite loop of alarms overlapping each other, and I can't figure out why, even though I set alarmSet.Value to false before navigating back to the main page, the alarm is still seen as on... is there something more I need to be doing? How can I have the alarm on and set to the current minute the clock is at without it ringing immediately?
I do not see an "OnLoaded" event on the Application life cycle for Windows Phone.
Refer: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff817008(v=vs.105).aspx
You may do the following:
In Mainpage.xaml, see if the alarm is running and if the alarmSet is true, redirect user to next page under onNavigatedTo Event.
In next page, set alarmSet as false and redirect user to MainPage.xaml. The onNavigatedTo will again be fired, however, since alarmSet is false, user wont be redirected anywhere. You may do the else case of stopping alarm or anything further here.

Sleep method doesn't work properly

Ok, I have a chess board application. The application has 64 panels within a groupbox. These panels are identified with the expression CHessBoardPanels{x,y). I am using this to change the background color of the panels. I want a small delay in between where the chessPanel.BackGround changes to red and when the panels turn back to white.(approximately 1 to 2 second delay)
I have tried the Sleep function but it basically locks the application up till the task have been complete
Here is the code which I have tried:
for (int Row = 7; Row > 3; --Row)
{
chessBoardPanels[ Column ,Row].BackColor = Color.Red;
++Column;
//Add text to Moves TextBox
MovesText.AppendFormat("WhtB {0} {1}{2}", ColumnText, RowText, Environment.NewLine);
MovesTxt.Text = MovesText.ToString();
++ColumnText;
--RowText;
}
//Start White Horizonal Drill
Column = 0;
Thread.Sleep(5000); //This does not delay proerperly
for (int Row = 7; Row > 4; --Row)
{
chessBoardPanels[Column, Row].BackColor = Color.White;
++Column;
//Add text to Moves TextBox
MovesText.AppendFormat("WhtB {0} {1}{2}", ColumnText, RowText, Environment.NewLine);
MovesTxt.Text = MovesText.ToString();
++ColumnText;
--RowText;
}
I am using .Net framework 4.0 because Visual Studio 2010 doesn't support 4.5
That's what Sleep does, it pauses the thread.
What you need is to use a Timer control, and create a queue with color changes, and let the timer control call an event handler periodically, like so:
(in your Form class):
Timer timer = new Timer();
(in your Form's constructor):
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 500; // every 1/2 second
timer.Enabled = true;
timer.Start();
Then your event handler would do something like this:
void timer_Tick(object sender, EventArgs e)
{
// Read a queue, that contains timings
var nextItem = PeekAtQueue();
if ((nextItem != null) && (nextItem.WhenToChangeColor <= DateTime.Now))
{
var item = TakeFromQueue(); // as opposed to just peeking
ChangeColor(item);
}
}
What does this do? (Of course this code is not 100% complete, you'll have to add the queue-accessing methods yourself, it depends on what you want/can use)
Seeing that Sleep() freezes your application temporarily, you need a
solution that allows you to still interact with your form, while
still having a delay and doing something after that delay.
So you
need to use a timer to execute something at a later date. The timer
in this example gets executed every 1/2 second but you can use any
interval you choose.
Point is, because of this timer and this
configuration, a certain method -- the event handler -- is executed
every 1/2 second, or the interval of your choice.
So what you can
then do is, when you want a certain color change to happen later, to
queue an object that describes the color change, for instance {E5, "red", today at 04:20:30 PM}.
The event handler executed by the
timer peeks every time to see if there is something in the queue, and
to have a look at what it is. It checks whether the "moment to change
the color", as described in the queued object, is now or has already
passed. If so, it changes the color. If not, it leaves the item at
the top of the queue, and the next time the event handler gets
executed again (1/2 second later), it will perform the same check
again.
Once a color change is done, the object is taken off the
queue.
Consider using a Timer class instead. That should allow you to delay your application without locking the thread.
I have tried the Sleep function but it basically locks the application
up till the task have been complete
You need to move the logic of your application our of the main (or UI) thread. Your application will "freeze" if you call a Thread.Sleep in the main (UI) thread as the Windows event-handling loop is blocked.
Things you can use:
New Thread, Task, Background worker to execute logic of the game
Timers
Update the GUI from another thread
Sleep will lock the current thread, meaning if it's the main UI thread then no user input will be processed - and ideally you should set an hourglass cursor at that point.
To do what you want I think you need to start a background timer and then set the colours on the callback, then cancel the timer.
While the timer is ticking down the main UI will still be responsive.
You might also find that over 1 second delay will feel like too long a delay for users, but the timer period is in milliseconds so you can define a shorter delay.
Try following:
Task.Run(() => Thread.Sleep(5000)).Wait();

Unobtrusive alert notification that can timeout

In the application I am working with, if the user changes the value in a cell that is say positive to negative and the value is supposed to be positive at all times, the application forces the positive value. Right now, when this happens there is no alert shown to the user.
I would like to show a little unobtrusive alert, like the one that shows up when a new mail arrives in outlook, or something similar, so that the user can be alerted that the application did something on her behalf.
I tried using the NotifyIcon class to do this. But the problem with that class seems to be that the timeout on it doesn't work as expected. I want to show this alert for not more than 2s and the BallonTipText lasts for longer than 10s.
Is there a .NET class for this purpose?
If not, is there an alternate way to do something like this?
Using a notification icon for this case seems wrong to me. The user's attention is, when entering something into a cell, on the cell. If you display the notification on the lower right of the screen the user is very likely to miss it, or worse, it disrupts his work flow.
You might instead consider adding a balloon tip to the cell the user is editing. Kinda like the balloon tip Windows Explorer is showing on Vista and Windows 7 on renaming a file when you try entering a character that is disallowed in file names:
I have had this problem in the past. I gather that the timeout problem is because the operating system fixes a minimum value of 10 seconds and a maximum value of 30 seconds (or something like that).Edit Oh and this doesn't include time that a user is idle.Edit
I have used the following code in the past to get around this.
Just to clarify
Declare a public variable, say called ballonTipActive with a value of 0.
Insert a timer control disabled with 100ms delay and create an event from BalloonTipShown from the notifyicon control.
Then
private void ptNotifyIcon_BalloonTipShown(object sender, EventArgs e)
{
timer1.Enabled = true;
balloonTipActive = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
balloonTipActive++;
if (balloonTipActive == 40)
{
ptNotifyIcon.Visible = false;
ptNotifyIcon.Visible = true;
balloonTipActive = 0;
timer1.Enabled = false;
}
}
Setting the visible property to false then true gets rid of the balloon.

Categories

Resources