[Windows Phone 8] Ejecución de código en segundo plano (II)

Hola a todos!

Vuelvo a la carga con el segundo artículo de la serie sobre código en segundo plano:

En esta ocasión nos toca hablar de las tareas programadas en segundo plano. En Windows Phone 8 podemos crear un tipo especial de proyecto llamado “Windows Phone Scheduled Task Agent”, este proyecto se podrá ejecutar cuando nuestra aplicación no esté activa, ejecutando código. Lo más importante es que comparte espacio de aplicación con nuestra app, por lo que podremos compartir archivos entre ambos proyectos de forma muy sencilla. Además, dispondremos de dos formas de registrar nuestro agente: Como una tarea intensiva o periódica. Su ejecución es la misma, pero contarán con diferentes limitaciones.

Pero no todo es precioso. Antes de ver como usar este tipo de proyecto, repasemos sus limitaciones:

Limitación Intensivo Periódico
Memoria (Sistema 1Gb) Máximo 20Mb hasta GDR2/ 25Mb en GDR3  Máximo 20Mb hasta GDR2/ 25Mb en GDR3
Memoria (Sistema 512Mb) Máximo 11Mb Máximo 11Mb
APIs Algunas APIs no están soportadas Algunas APIs no están soportadas
Caducidad Cada 2 semanas Cada 2 semanas
Desactivación por fallos Tras 2 fallos Tras 2 fallos
Periodo entre ejecuciones   30 minutos
Duración de ejecución 10 minutos 25 segundos
Batería Solo se ejecutan con +90% de batería.
Dispositivo conectado a red eléctrica.
Solo se paran si el dispositivo entra en ahorro de batería.
Conexión Solo pueden usar WiFi  
LockScreen Solo se ejecutan bajo lockscreen  
Límite de agentes por dispositivo   Varía por configuración, pero por encima de 6

Como podemos ver, esto no es como si nuestra aplicación estuviese en segundo plano constantemente. Existen muchas restricciones y debemos ser muy conscientes de ellas. La realidad nos dice que hay muy pocas aplicaciones que usen agentes intensivos. Casi siempre usaremos agentes periódicos. Tareas como actualizar el Live tile, descargar datos de un servicio web o comprobar datos, pueden ser realizadas sin problemas por este tipo de agentes.

Vamos al turrón! Empezamos a ensuciarnos las manos, creando un nuevo proyecto Windows Phone 8 normal. Con este proyecto se creará una solución, a la que añadiremos un proyecto del tipo “Windows Phone Scheduled Task Agent”, que encontraremos al final de la lista de proyectos de Windows Phone 8:

image

Una recomendación, no llaméis a vuestro proyecto ScheduledTask, ya que hay un tipo de dato que es precisamente ScheduledTask y tendréis que resolver conflictos de nombres. Llamadlo de alguna otra forma descriptiva.

Una vez que hemos creado el proyecto, por defecto nos añade una clase llamada ScheduledAgent, que hereda a su vez de la clase ScheduledTaskAgent. Esta clase base nos da métodos que sobre escribir para trabajar con nuestro agente. Por defecto se crea un constructor estático, que se suscribe al evento UnhandledException de la aplicación, y un método OnInvoke.

El método OnInvoke será el que se encargue de ejecutar nuestro código en background. Por defecto en este método vemos que se llama al método NotifyComplete. Este método notifica al sistema que hemos terminado el trabajo y no necesitamos seguir en ejecución. Si no lo llamamos, aunque se termine el método OnInvoke, el sistema no sabrá que hemos finalizado y matará el proceso pasado el tiempo máximo de ejecución.

Ahora vamos a añadir algo de código a nuestro agente, para este ejemplo vamos a actualizar el Live tile de la aplicación con una imagen y textos:

OnInvoke
protected override void OnInvoke(ScheduledTask task)
{
    var appTile = ShellTile.ActiveTiles.First();
    FlipTileData data = new FlipTileData();
    data.BackgroundImage = new Uri(«http://…png», UriKind.Absolute);
    data.Title = «custom title»;
    data.BackContent = «setting from background agent»;
    appTile.Update(data);

    NotifyComplete();
}

A continuación, necesitamos que nuestra aplicación se encargue de registrar este agente. Cada aplicación solo puede tener un proyecto de ejecución en segundo plano. Debido a esta limitación, el sistema usará el ensamblado referenciado en nuestra aplicación como agente, por lo que lo primero que necesitamos hacer es añadir una referencia al agente en nuestra aplicación:

image

Una vez hecho esto, solo nos queda notificar al sistema que tenemos una tarea (periódica o intensiva) y que deseamos registrarla, indicando su nombre, descripción y fecha de caducidad. Como hemos dicho anteriormente, la fecha máxima de caducidad es de 2 semanas:

Background agent registration
private void RegisterBackgroundAgent()
{
    PeriodicTask task = (PeriodicTask)ScheduledActionService.Find(«periodic»);
    if (task == null)
    {
        task = new PeriodicTask(«periodic»);
        task.Description = «Periodic task to update app tile.»;
        task.ExpirationTime = DateTime.Now.AddHours(1);
        ScheduledActionService.Add(task);
    }

#if DEBUG
    ScheduledActionService.LaunchForTest(«periodic», new TimeSpan(0, 0, 30));
#endif
}

Si analizamos el código, podemos encontrar varias partes:

  • En primer lugar usamos la clase ScheduledActionService para buscar una tarea que se llame igual que la nuestra (periodic es un nombre descriptivo para una demo, pero no para una aplicación real, recuerdalo!)
  • Si no existe, la creamos. Aquí tenemos que indicar su nombre, que debe ser único, una descripción y un tiempo de caducidad. Por último añadimos nuestra nueva tarea periódica al ScheduledActionService. El registro de una tarea intensiva es exactamente el mismo, usando la clase ResourceIntensiveTask en lugar de PeriodicTask.
  • Por último, estaría bien poder probar nuestro agente sin tener que esperar media hora delante del emulador. para ello disponemos de un método LaunchForTest dentro de la clase ScheduledActionService. A este método le pasamos el nombre de la tarea que queremos probar y un TimeSpan con el tiempo que queremos que tarde en lanzarla. Si os fijáis, he envuelto esta llamada dentro de una condición de compilación, de forma que solo se ejecute en modo DEBUG. Esto es así porque el método LaunchForTest no puede ser usado en una app publicada, haría que nuestra aplicación fallase la certificación.

Por último, tenemos que ejecutar este código. Yo personalmente suelo ejecutarlo al iniciar la aplicación, al final del método InitializePhoneApplication. El Registro de un agente en background es muy rápido y no afectará al rendimiento, además es un código que no se ejecutará siempre, pues la mayor pate del tiempo la tarea ya estará registrada. En este sentido es importante darle al usuario el control sobre la activación, añadiendo una página de settings donde pueda activar o desactivar el agente.

InitializePhoneApplication
private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;

    // Create the frame but don’t set it as RootVisual yet; this allows the splash
    // screen to remain active until the application is ready to render.
    RootFrame = new PhoneApplicationFrame();
    RootFrame.Navigated += CompleteInitializePhoneApplication;

    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Handle reset requests for clearing the backstack
    RootFrame.Navigated += CheckForResetNavigation;

    // Ensure we don’t initialize again
    phoneApplicationInitialized = true;

    RegisterBackgroundAgent();
}

Y listo, si ejecutamos el ejemplo, anclamos la aplicación al inicio y esperamos unos segundos (los que hayamos indicado, 30 en este caso) veremos que nuestro tile se actualiza:

image

Y con esto terminamos la segunda entrega de esta serie. Aquí os dejo el código fuente de este ejemplo, para que lo podáis usar como referencia. En el próximo artículo hablaremos sobre reproducción de música en background.

Un saludo y Happy Coding!

[Windows Phone 8] Ejecución de código en segundo plano (I).

Hola a todos!

Hoy quiero dedicar unas líneas a hablar de la ejecución en segundo plano en Windows Phone 8. ¿Qué son? ¿Como se usan? ¿Qué restricciones tienen?

En Windows Phone 8 disponemos de cuatro opciones para ejecutar código en background:

Geolocalización en background

La primera, geolocalización en background, permite indicar al sistema que necesitamos continuar siguiendo la posición del dispositivo en toda circunstancia. Nuestra aplicación queda “viva” y seguimos recibiendo eventos de posición aunque el usuario haya cambiado a otra app. Pero no es tan bonito como parece, existen ciertas restricciones que pueden hacer que la aplicación se desactive:

  • Si el usuario no la ha usado en menos de 4 horas.
  • Si paramos de seguir la posición.
  • Si se activa el modo de ahorro de batería.
  • Si la memoria del dispositivo es baja.
  • Si otra aplicación empieza a ejecutarse en background.
  • Si el usuario desactiva los servicios de localización.

Algunas de estas situaciones podemos intentar evitarlas, por ejemplo reduciendo el consumo de la aplicación al mínimo con el objetivo de no llenar la memoria del dispositivo. Otras, lamentablemente, están fuera de nuestro control.

Para que nuestra aplicación continúe ejecutándose en background, debemos primero indicarlo al sistema. Esto lo llevaremos acabo en el archivo .xml, en el nodo DefaultTask. Tenemos que añadir el nodo BackgroundExecution:

Background execution
<DefaultTask  Name_default» NavigationPageMainPage.xaml«>
  <BackgroundExecution>
    <ExecutionType NameLocationTracking«/>
  </BackgroundExecution>
</DefaultTask>

A continuación, solo tendremos que desarrollar nuestro código normal y corriente para seguir la posición cuando esta cambie:

GpsService
Geolocator locator = new Geolocator();

public event EventHandler<PositionChangedEventArgs> PositionChanged;

public void StartTrackingLocation()
{
    locator.DesiredAccuracy = PositionAccuracy.High;
    locator.MovementThreshold = 20;
    locator.PositionChanged += locator_PositionChanged;
}

private void locator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    var tmpHandle = PositionChanged;
    if (tmpHandle != null)
    {
        App.RootFrame.Dispatcher.BeginInvoke(delegate
        {
            tmpHandle(this, args);
        });
    }
}

Y Voila!

Ahora, en nuestro ViewModel vamos a añadir código para que reciba las posiciones y las añada a una lista:

ViewModel principal
public class VMMainPage : VMBase
{
    private IGpsService gpsService;
    private ObservableCollection<string> positions = new ObservableCollection<string>();

    public VMMainPage(IGpsService gpsService)
    {
        this.gpsService = gpsService;
        this.gpsService.PositionChanged += gpsService_PositionChanged;
        this.gpsService.StartTrackingLocation();
    }

    void gpsService_PositionChanged(object sender, Windows.Devices.Geolocation.PositionChangedEventArgs e)
    {
        Positions.Add(string.Format(«{0} / {1}», e.Position.Coordinate.Latitude, e.Position.Coordinate.Longitude));
    }

    public ObservableCollection<string> Positions
    {
        get { return positions; }
        set
        {
            positions = value;
            RaisePropertyChanged();
        }
    }
}

No olvides añadir la capability ID_CAP_LOCATION a tu app y ya podrás ejecutarla. Si usas el emulador, podrás ver como al añadir puntos al mapa del simulador GPS, aparecen en una lista en pantalla. Si pruebas a volver al menú inicio, poner un punto de parada en el evento PositionChanged y añadir un nuevo punto, verás como la llamada llega, aunque la aplicación no esté en primer plano.

image

Así de sencillo, podéis hacer una app que siga al dispositivo aun estando en background. Como siempre, aquí podéis descargar el código de ejemplo de la aplicación para que tengáis una guía de como hacer lo que os cuento. Por supuesto, con MVVM, IoC y servicios, “Rico, Rico” jeje.

Espero que este pequeño post os ayude.

Un saludo y Happy Coding!

[Windows Phone 8] Resumen de artículos sobre Windows Phone 8

Para empezar este año 2014 en el blog, creo que es una buena idea hacer un repaso por todos los temas de los que ya hemos hablado acerca de la plataforma. Al final, tras un año de artículos, he escrito sobre muchos temas diferentes que pueden quedar algo perdidos en el blog. Empecemos!

APIs de voz en Windows Phone 8:

En este artículo explico como hacer uso de las APIs de voz: Comandos, Text to Speech y Speech to Text. Todo con un divertido ejemplo!

http://geeks.ms/blogs/jyeray/archive/2012/11/15/windows-phone-8-apis-de-trabajo-con-voz.aspx

Mapas en Windows Phone 8:

En dos artículos, repasamos el nuevo control de mapas de Windows Phone 8, el cálculo de rutas, la geo codificación y la geo codificación inversa.

http://geeks.ms/blogs/jyeray/archive/2012/12/27/nuevo-control-de-mapas-y-calculo-de-rutas-en-windows-phone-8.aspx

http://geeks.ms/blogs/jyeray/archive/2012/12/31/geocodificaci-243-n-y-geocodificaci-243-n-inversa-en-windows-phone-8.aspx

Contactos:

Explico como crear, leer y actualizar contactos en la agenda del dispositivo, creando nuestro propio almacén de contactos.

http://geeks.ms/blogs/jyeray/archive/2013/01/05/windows-phone-8-gesti-243-n-de-contactos.aspx

Asociación de archivos y protocolos:

Una de las novedades estrella de Windows Phone 8, poder asociar protocolos y extensiones de archivo a nuestra aplicación. Con ello conseguimos que cuando un usuario tenga un tipo de archivo concreto o un esquema de protocolo, se lance nuestra aplicación.

http://geeks.ms/blogs/jyeray/archive/2013/01/16/windows-phone-8-asociaci-243-n-de-archivos-y-protocolos.aspx

Fast App Resume:

FAR nos permite conservar siempre una sola instancia de nuestra aplicación abierta, de forma que aunque el usuario pulse sobre el tile de inicio de la aplicación, recuperemos la instancia creada en vez de abrir una nueva.

http://geeks.ms/blogs/jyeray/archive/2013/01/28/windows-phone-8-tip-fast-app-resume.aspx

Compartir código entre Windows Phone 7.X y Windows Phone 8:

Una de las grandes preocupaciones de este pasado año, tener que mantener varias versiones distintas de nuestras apps. En este artículo hablo de los trucos y consejos para escribir código que pueda ser compartido fácilmente.

http://geeks.ms/blogs/jyeray/archive/2013/02/07/windows-phone-8-compartiendo-codigo-en-windows-phone-7-y-windows-phone-8.aspx

Probar nuestras aplicaciones en dispositivos remotos:

Con el incremento del número de dispositivos disponibles en el mercado, probar nuestros desarrollos en todos ellos es una tarea imposible. Nokia pone a nuestra disposición un servicio para acceder a todos sus modelos de dispositivos de forma remota y gratuita.

http://geeks.ms/blogs/jyeray/archive/2013/03/05/windows-phone-8-probando-nuestras-aplicaciones-en-dispositivos-f-237-sicos-remotos.aspx

Interactuando con la pantalla de bloqueo:

Otra de las nuevas APIs que encontramos en Windows Phone 8. Esta nos ofrece la capacidad de poner un contador en la pantalla de bloqueo o incluso de ser proveedores de imágenes para la misma.

http://geeks.ms/blogs/jyeray/archive/2013/03/13/windows-phone-8-interactuando-con-la-pantalla-de-bloqueo.aspx

API Here Places:

No es estrictamente solo para Windows Phone, pero en el artículo explicamos como interactuar con un API REST de forma asíncrona desde Windows Phone 8 y como consumir su contenido. En este caso usando el API Places de Here.

http://geeks.ms/blogs/jyeray/archive/2013/03/27/windows-phone-8-here-places-api.aspx

Evitar problemas al publicar nuestra app para Windows Phone 7 y Windows Phone 8 simultáneamente:

Existen ciertas cosas que debemos tener en cuenta para publicar dos XAP distintos de nuestra aplicación para soportar Windows Phone 7.X y Windows Phone 8. En este artículo explico que hay que saber y como enfrentarnos a lo posibles problemas.

http://geeks.ms/blogs/jyeray/archive/2013/05/14/windows-phone-tip-problemas-al-publicar-para-windows-phone-7-y-para-windows-phone-8.aspx

Validación de datos en Windows Phone 8 y Windows 8:

Un proyecto que podéis obtener en NuGet y que, con el simple uso de un Behavior, nos permite validar los datos de nuestra aplicación de forma sencilla. Además con ejemplos para Windows Phone 8 y Windows 8.

http://geeks.ms/blogs/jyeray/archive/2013/06/16/xaml-tip-validaci-243-n-de-datos-en-windows-phone-8-y-windows-8.aspx

Google Analytics en nuestra aplicación Windows Phone 8:

El primer paso para mejorar es conocer que debemos mejorar. Añadiendo Google Analytics a nuestra aplicación podremos tener una imagen clara del uso que los usuarios hacen de la misma.

http://geeks.ms/blogs/jyeray/archive/2013/07/15/windows-phone-8-a-241-adir-google-analytics-a-nuestras-aplicaciones.aspx

Conseguir reviews para tus aplicaciones:

En este artículo explico como presentar al usuario la opción de valorar nuestra aplicación de forma sencilla y rápida, de forma que consigamos más reviews y valoraciones.

http://geeks.ms/blogs/jyeray/archive/2013/09/19/conseguir-reviews-de-tus-apps-en-windows-phone-8-y-windows-8-x.aspx

Novedades de Windows Phone 8 Update 3 para desarrolladores:

En Octubre se liberó el update 3 d Windows Phone 8 y en esta ocasión nos ofrecía novedades también a los desarrolladores. Sonidos configurables para nuestras notificaciones, nueva resolución…

http://geeks.ms/blogs/jyeray/archive/2013/10/15/windows-phone-8-gdr3-preview-novedades-para-desarrolladores.aspx

Multilingual App Toolkit:

En muchas ocasiones he hablado de lo importante que es tener nuestra aplicación localizada en varios idiomas, para conseguir muchas más descargas, para esto Multilingual App Toolkit nos va a ayudar a hacer el trabajo más sencillo.

http://geeks.ms/blogs/jyeray/archive/2013/11/02/windows-phone-8-multilingual-app-toolkit.aspx

Cimbalino toolkit:

En dos artículos os presentaba este fantástico toolkit para Windows Phone 8. ApplicationBar con soporte para enlace a datos, multitud de servicios y behaviors… Un montón de herramientas para hacernos la vida mucho más fácil.

http://geeks.ms/blogs/jyeray/archive/2013/10/27/windows-phone-8-cimbalino-toolkit-applicationbar-y-servicios.aspx

http://geeks.ms/blogs/jyeray/archive/2013/11/14/windows-phone-8-cimbalino-toolkit-trabajando-con-xaml.aspx

La verdad es que he tocado muchos temas distintos sobre Windows Phone 8 durante este último año y en ocasiones uno se queda sin ideas sobre que escribir o que genera más dudas en la plataforma… Así que tiro la pelota a vuestro tejado. He compartido un libro de excel en mi Skydrive al que podéis entrar y contarme que es lo que os gustaría ver en mi blog. De entre todas las propuestas, sacaré los próximos artículos que veréis publicados:

http://sdrv.ms/1lZTbqh

Espero que todo esto os sea de Utilidad. Un saludo y Happy Coding!!