Chris
Chris

Reputation: 3076

Vibrate until message box closed Windows Phone 7

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.

Upvotes: 5

Views: 1224

Answers (2)

user60456
user60456

Reputation:

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.
  • Per Mystere Man's suggestion, I added a timeout. you will want something like this.
  • You might want to refactor, and clean up my sample

Upvotes: 2

msarchet
msarchet

Reputation: 15242

SoundEffectInstance alarmSound = PlaySound(@"Alarms/"+alarmSoundString);

VibrateController vibrate = VibrateController.Default;

var vibrationLength = 1000;
var startTime = DateTime.Now;
vibrate.Start(new TimeSpan(0,0,0,0,vibrationLength));

MessageBoxResult alarmBox = MessageBox.Show("Press OK to stop alarm", "Timer Finished", MessageBoxButton.OK);
var ok = false;

While (!ok){
  if (alarmBox == MessageBoxResult.OK)
  {
    ok = true;
  }
  else{
     if(startTime.AddMilliseconds(vibrationLength * 1.2) < DateTime.Now)
     {
        startTime = DateTimne.Now;
        vibrate.Start(new TimeSpan(0,0,0,0,vibrationLength));
     }
  }
}

alarmSound.Stop();
vibrate.Stop();

Roughly

I don't write code for windows phone so this may cause the phone to become unresponsive. But the general Idea is keep checking to see if the user has hit okay and if not if enough time has elasped since the last vibration has started to start a new one.

If you want it to pulse I would suggest using AddMilliseconds and add a length greater than the pulse length you want.

Using a timer instead

pretending you class looks like this

public class buzzz
{

   MessageBoxResult alarmBox;
   DispatchTimer alarmTimer = new DispatchTimer();
   var vibrationLength = 1000.0;
   var timerIncrease = 1.2;
   VibrateController vibrate = VibrateController.Default;

   public buzz()
   {
      alarmTimer.Interval = TimeSpan.FromMillseconds(vibrationLegnth * timerIncrease);
      alarmTimer.Tick += alarmTimer_Tick
   }
   public void startBuzz()
   {
       SoundEffectInstance alarmSound = PlaySound(@"Alarms/"+alarmSoundString);
       vibrate.Start(new TimeSpan(0,0,0,0,vibrationLength));
       alarmTimer.Start();
       alarmBox = MessageBox.Show("Press OK to stop alarm", "Timer Finished", MessageBoxButton.OK);
    }

    void alarmTimer_Tick(object sender, EventArgs e)
        {
           if(alarmBox == MessageBoxResult.OK)
           {
              alarmTimer.Stop();
              vibrate.Stop();
           }
           else
           {
               vibrate.Start(new TimeSpan(0,0,0,0,vibrationLength));
           }
        }
}

Upvotes: 0

Related Questions