Una de las políticas de publicación de la tienda de Windows Phone para las aplicaciones que manejan cualquier tipo de audio es que si hay música reproduciéndose en segundo plano, esta debe ser detenida para permitir que el audio de tu aplicación se ejecute. Esta política es un punto en donde muchos desarrolladores caemos al momento de publicar nuestras apps.
Para solucionarlo, basta hacer un par de pasos muy sencillos. Utiliza este proyecto de inicio, ábrelo en Visual Studio y dirígete hacia el manejador del evento Tap del botón.
private void btnPlay_Tap(object sender, System.Windows.Input.GestureEventArgs e) { } |
Aquí solo basta verificar primero si existe algún audio en reproducción y en caso de que así sea, pausarlo antes de comenzar a reproducir nuestro sonido.
private void btnPlay_Tap(object sender, System.Windows.Input.GestureEventArgs e) { if (MediaPlayer.State == MediaState.Playing) { MediaPlayer.Pause(); } player.Play(); } |
Hasta aquí todo va sencillo, solo que el segundo paso debe ser restaurar la reproducción de audio que originalmente estaba siendo reproducido. Para hacerlo hay un manejador de eventos para el control MediaElement que notifica cuando ha terminado de reproducirse, ese manejador de eventos puedes colocarlo en el método sobre escrito OnNavigatedTo de la página.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); player.MediaEnded += player_MediaEnded; } |
Dentro del manejador de eventos puedes restaurar la reproducción del audio original.
void player_MediaEnded(object sender, RoutedEventArgs e) { MediaPlayer.Resume(); } |
Al ejecutar hasta aquí el proyecto probablemente te aparecerá una excepción como la de la imagen siguiente.
Esta excepción puede ser evitada, para que puedas hacerlo, crea una nueva clase, para este ejemplo, llamada XNAFrameworkDispatcherService. Esta clase debe heredar de IApplicationService.
using System.Windows.Threading; using Microsoft.Xna.Framework; using System.Windows; using System; namespace BackgroundAudio { public class XNAFrameworkDispatcherService : IApplicationService { } } |
Dentro de la clase, implementa la interfaz, agrega el constructor de la clase y un temporizador, así como la configuración para poder utilizar el temporizador.
public class XNAFrameworkDispatcherService : IApplicationService { private DispatcherTimer frameworkDispatcherTimer; public XNAFrameworkDispatcherService() { this.frameworkDispatcherTimer = new DispatcherTimer(); this.frameworkDispatcherTimer.Interval = TimeSpan.FromTicks(333333); this.frameworkDispatcherTimer.Tick += frameworkDispatcherTimer_Tick; FrameworkDispatcher.Update(); } void frameworkDispatcherTimer_Tick(object sender, EventArgs e) { FrameworkDispatcher.Update(); } void IApplicationService.StartService(ApplicationServiceContext context) { this.frameworkDispatcherTimer.Start(); } void IApplicationService.StopService() { this.frameworkDispatcherTimer.Stop(); } } |
Compila tu aplicación para que después, en el archivo App.xaml puedas agregar la referencia a tu nueva clase, la referencia debe ir dentro del campo ApplicationLifetimeObject.
<Application.ApplicationLifetimeObjects> <local:XNAFrameworkDispatcherService/> <shell:PhoneApplicationService Launching="Application_Launching" Closing="Application_Closing" Activated="Application_Activated" Deactivated="Application_Deactivated"/> </Application.ApplicationLifetimeObjects> |
Ahora, de nuevo, ejecuta tu aplicación y notarás que ahora si hará su tarea de manera natural. El escenario más normal para hacer pruebas es poner música a reproducir y al presionar tu botón la música en segundo plano se deberá pausar, después de que el sonido se termine, la música deberá seguir siendo reproducida.
Puedes descargar el código de ejemplo desde aquí.