Windows Phone. Alarmas.

En ocasiones nos interesará que nuestra aplicación pueda realizar una notificación programa en un determinado momento aun cuando este cerrada.

En Windows Phone contamos con dos tipos de notificaciones programadas:

  • Alarmas

  • Recordatorios

Ambas son un popup que sale en la parte superior de la pantalla (podéis echarle un vistazo a las capturas de arriba). Pueden contener un texto que podemos personalizar y ambas nos permitirán dos opciones:

  • Desestimar
  • Posponer

La diferencia básica entre las alarmas y los recordatorios son:

  • Las alarmas pueden reproducir un sonido personalizado, los recordatorios no.
  • Los recordatorios puede utilizar una URL que le indiquemos (incluso usando parámetros) para redirigirnos a una página en concreto.  Al tocar encima de la alarma nos abre la aplicación pero no podemos hacer que el usuario sea guiado a una página concreta.

Alarmas

Vamos a centrarnos en esta entrada en analizar las alarmas. Para ello, como en la mayoría de ocasiones, vamos a realizar un ejemplo prático.

Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo y concentrar toda la atención en la alarma en si.

Agregamos dentro del Grid principal de la página MainPage.xaml:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
          <TextBlock Text="Texto:" />
          <TextBox x:Name="txtContenido" Text="Ejemplo de alarma!" />
          <TextBlock Text="Comenzará en 5 segundos" />
          <StackPanel Orientation="Horizontal">
               <Button x:Name="btnCrear" Content="Crear Alarma"/>
          </StackPanel>
     </StackPanel>
</Grid>

Hemos creado una pequeña interfaz donde permitimos al usuario modificar el texto que aparecerá en la alarma, le informamos que la alarma aparecerá en 5 segundos (este tiempo es totalmente personalizable, lo hemos colocado de manera fija en este primer ejemplo para simplificar el proceso) y añadimos un botón que será el encargado de crear la alarma al ser pulsado.

Agregamos a continuación el evento Click del botón:

<Button x:Name="btnCrear" Content="Crear Alarma" Click="btnCrear_Click"/>

Por último, vamos a la parte más interesante. Vamos a añadir la lógica que se ejecutará al pulsar sobre el botón (en MainPage.xaml.cs):

private void btnCrear_Click(object sender, RoutedEventArgs e)
{
     Alarm alarma = new Alarm("Ejemplo Alarma");
     alarma.BeginTime = DateTime.Now.AddSeconds(5);
     alarma.Content = txtContenido.Text;
     alarma.RecurrenceType = RecurrenceInterval.None;

     ScheduledActionService.Add(alarma);
}

Lo primero que hacemos es crear una instancia de un objeto Alarm indicando en el constructor el nombre de la alarma. Es importante resaltar que el nombre de la alarma ha de ser único. No pueden existir dos alarmas con el mismo nombre. En caso contrario obtendríamos una excepción de tipo InvalidOperationException.

La primera de las propiedades utilizadas es BeginTime. Indica la fecha y hora en la cual la alarma comenzará. Debe ser siempre una fecha posterior a la actual.

A continuación, hemos utilizado la propiedad Content. Es el texto que aparecerá en la alarma.

RecurrenceType toma su valor de una enumeración del tipo RecurrenceType. Los valores posibles son:

  • None. No hay repetición. Solo se lanzará la alarma en la fecha y hora indicada.
  • Daily. Se lanzará todos los días a la hora indicada.
  • Weekly. Se lanzará cada semana en el día y la hora indicada.
  • Monthly. Se lanzará cada mes en el día y hora indicada.
  • Yearly. Se lanzará cada año en el día y hora indicada.
  • EndOfMonth. Esta opción es interesante. La alarma se lanzará a la hora indicada cada mes en el último día del mismo.

Como ya hemos mencionado no pueden existir dos alarmas con el mismo nombre. Para comprobarlo podemos modificar el ejemplo para verificarlo:

private void btnCrear_Click(object sender, RoutedEventArgs e)
{
     Alarm alarma = new Alarm("Ejemplo Alarma");
     alarma.BeginTime = DateTime.Now.AddSeconds(5);
     alarma.Content = txtContenido.Text;
     alarma.RecurrenceType = RecurrenceInterval.None;

     ScheduledActionService.Add(alarma);

    Alarm alarma2 = new Alarm("Ejemplo Alarma");
    alarma2.BeginTime = DateTime.Now.AddSeconds(5);
    alarma2.Content = txtContenido.Text;
    alarma2.RecurrenceType = RecurrenceInterval.None;

    ScheduledActionService.Add(alarma2);
}

Si ejecutamos el código anterior obtendremos una excepción (InvalidOperationException).

¿Qué podemos hacer?

Vamos a utilizar el servicio ScheduledActionService. Dicho servicio tiene un método llamado Find al que le pasaremos una cadena como parámetro que será el nombre de una alarma. El método nos devolverá la alarma en caso de existir. Si no existe creamos la alarma, si existe podemos eliminarla y volver a crearla con los nuevos parámetros.

Veamos como sería:

private void btnCrear_Click(object sender, RoutedEventArgs e)
{
     Alarm alarma = new Alarm("Ejemplo Alarma");
     alarma.BeginTime = DateTime.Now.AddSeconds(5);
     alarma.Content = txtContenido.Text;
     alarma.RecurrenceType = RecurrenceInterval.None;

     if (ScheduledActionService.Find("Ejemplo Alarma") != null)
          ScheduledActionService.Remove("Ejemplo Alarma");

     ScheduledActionService.Add(alarma);
}

A continuación, vamos a centrarnos en una de las posibilidades más interesantes que podemos realizar con las alarmas, utilizar sonidos personalizados para las mismas. Para ello, lo primero que debemos hacer es añadir al proyecto un archivo de audio.

Hacemos clic derecho sobre el proyecto para seleccionar la opción “Añadir – Archivo existente”. Podemos utilizar archivos de audio con las siguientes extensiones:

  • MP3
  • WMA
  • WAV

Para el proyecto de ejemplo que estamos utilizando yo he utilizado un archivo mp3 llamado “alarma.mp3”. A continuación, veremos la línea añadida al código para utilizar un sonido personalizado en la alarma:

alarma2.Sound = new Uri("alarma.mp3", UriKind.Relative);

Como podemos ver en el código anterior, hemos utilizado la propiedad Sound del objeto Alarm para establecer el sonido. Esta propiedad espera una URI hacia el fichero de audio.

Sencillo, ¿verdad?.

Por último en esta entrada vamos a ver otro detalle muy interesante. Hemos hablado anteriormente que no podemos tener dos alarmas con el mismo nombre. Hemos tenido que averiguar si la alarma ya existe y en caso afirmativo eliminarla antes de volver a crearla.

Entonces, ¿existe alguna manera de saber que alarmas hay creadas en cola?

Si. Gracias al servicio ya utilizado ScheduledActionService. Veamos como sería. Agregamos una nueva página llamada “Alarmas.xaml”. Agregamos a dicha página el siguiente código:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <Grid.RowDefinitions>
          <RowDefinition Height="*" />
          <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <ListBox x:Name="lbAlarmas" Grid.Row="0">
          <ListBox.ItemTemplate>
               <DataTemplate>
                    <StackPanel Height="80">
                         <TextBlock Text="{Binding Content}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                         <TextBlock Text="{Binding BeginTime}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                    </StackPanel>
               </DataTemplate>
          </ListBox.ItemTemplate>
     </ListBox>
     <Button Grid.Row="1" Content="Volver" Height="100" VerticalAlignment="Bottom" Click="Button_Click"/>
</Grid>

Para navegar de la página principal a esta página agregamos un botón a la página principal:

<Button x:Name="btnVerAlarmas" Content="Ver Alarmas" Click="btnVerAlarmas_Click"/>

El evento Click del botón nos guiará hacia nuestra nueva página “Alarmas.xaml”:

private void btnVerAlarmas_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/Alarmas.xaml", UriKind.Relative));
}

Llegamos a la parte más interesante. Vamos a rellenar la lista que hemos añadido a nueva página “Alarmas.xaml”. Para ello vamos a utilizar el método GetActions del servicio ScheduledActionService. Este método nos devuelve una colección de objetos con el tipo que le hayamos especificado. Sería algo asi:

IEnumerable<Alarm> alarmas = ScheduledActionService.GetActions<Alarm>();
lbAlarmas.ItemsSource = alarmas;

Como podemos ver, obtenemos una colección de alarmas que asignamos como fuente de datos de nuestro ListBox.

Puedes ver en video el resultado de nuestro ejemplo a continuación:

También puedes descargar el ejemplo realizado:

En resumen, hemos aprendido como crear alarmas, que no pueden existir dos alarmas con el mismo nombre, como comprobar si una alarma existe y si es así, eliminarla antes de su creación, como utilizar sonidos personalizados y por último como saber que alarmas están creadas.

Espero que la entrada os sea utilidad. Como siempre me gusta recordar, cualquier duda o sugerencia la podéis dejar en los comentarios. Próximamente analizaremos paso a paso los recordatorios asi que . . . estad atentos!

5 pensamientos en “Windows Phone. Alarmas.

    • He verificado los enlaces y parecen estar todos correctamente. Si encuentras más problemas avísame y lo tendre en cuenta. Se podrían subir los ficheros a dos fuentes distintas si fuese necesario.
      Espero que el ejemplo te haya sido de utilidad.

      Un saludo.

  1. Me ha servido mucho esta entrada de tu blog, pero tengo una duda, si quisiera que la recurrencia no fuera de un día o semanal sino un tiempo especificado por mi, por ejemplo cada 8 horas o cada 48 sería posible? en caso de no ser posible que posible solución me puedes recomendar.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s