I have a timer app and I want to vibrate the phone once the timer has finished. I can currently play a sound until the OK button is pressed, but it only vibrates once. How can repeat the vibration until the user presses the OK button?
This is my current code
SoundEffectInstance alarmSound = PlaySound(@"Alarms/"+alarmSoundString);
VibrateController vibrate = VibrateController.Default;
vibrate.Start(new TimeSpan(0,0,0,0,1000));
MessageBoxResult alarmBox = MessageBox.Show("Press OK to stop alarm", "Timer Finished", MessageBoxButton.OK);
if (alarmBox == MessageBoxResult.OK)
{
alarmSound.Stop();
vibrate.Stop();
}
UPDATE: I have tried Joe's response, which works if I don't call MessageBox.Show()
It seems to stop at this point until OK is pressed.
VibrateController.Start(Timespan)
will throw an error if you pass a value greater than 5 seconds in, so you need to do some trickery to keep it going. Create a timer, and set it to restart the vibration. For example:
edited
Silly me, I forgot that both Messagebox, and DispatcherTimer will run on the same thread. The Messagebox will block it. Try this.
public partial class MainPage : PhoneApplicationPage
{
TimeSpan vibrateDuration = new TimeSpan(0, 0, 0, 0, 1000);
System.Threading.Timer timer;
VibrateController vibrate = VibrateController.Default;
int timerInterval = 1300;
SoundEffectInstance alarmSound = PlaySound(@"Alarms/"+alarmSoundString);
TimeSpan alramDuration; //used to make it timeout after a while
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
timer = new Timer(new TimerCallback(timer_Tick), null, 0, timerInterval);
alramDuration = TimeSpan.FromSeconds(0);
alarmSound.Play();
MessageBoxResult alarmBox = MessageBox.Show("Press OK to stop alarm", "Timer Finished", MessageBoxButton.OK);
if (alarmBox == MessageBoxResult.OK)
{
StopAll();
}
}
void timer_Tick(object sender)
{
//keep track of how long it has been running
//stop if it has gone too long
//otheriwse restart
alramDuration = alramDuration.Add(TimeSpan.FromMilliseconds(timerInterval));
if (alramDuration.TotalMinutes > 1)
StopAll();
else
vibrate.Start(vibrateDuration);
}
void StopAll()
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
vibrate.Stop();
alarmSound.Stop();
}
}
So I am using a System.Threading.Timer instead of the Dispatcher. It is mainly the same, only a little less of an obvious API. Instead of calling Start() and Stop()
you have to pass in a delay amount. To start it, pass in 0. It will keep going off every 1.3 seconds until you call Change()
passing in Timeout.Infinite
A few things to note:
vibrate.Start(vibrateDuration)
is only called from the tick event. That is because the Timer will immediately kick off.