Windows Phone 8: Here Places API

Hola a todos!

Hoy quiero aprovechar para hablar de la plataforma Here. Como sabréis, Here es la plataforma de mapas de Nokia, usando datos de NAVTEQ. En Windows Phone 8, tenemos múltiples aplicaciones que usan esta tecnología, Here Drive, Here Transit, Here Maps… e incluso podemos integrarla en nuestros propios desarrollos gracias al nuevo control de maps y las clases GeocodeQuery y ReverseGeocodeQuery, como ya vimos hace algún tiempo aquí y aquí. Pero existe un API extra, que no está implementada en el SDK de Windows Phone 8: Here Places.

Here Places nos permite acceder a los datos de localización de lugares de Nokia, de la misma forma que podemos hacer en Here Maps. Esto nos ofrece mucha información que poder incluir en nuestras aplicaciones, para enriquecerlas mucho más. Podremos encontrar información de 200 países, más de 1,5 millones de lugares (ciudades, distritos…) en total tendremos más de 200 millones de puntos de interés que podremos buscar y mostrar a nuestros usuarios.

Toda esta información se encuentra disponible a través de un servicio REST de Nokia, muy fácil de consumir desde nuestras aplicaciones Windows Phone. Pero para empezar, tendremos que registrarnos y obtener un Id de aplicación y un Código de aplicación.

Registro en Here Places

Para registrarnos, debemos acudir a http://developer.here.com donde podremos autenticarnos con el usuario y password que tengamos de Nokia developer. Tras autenticarnos, vamos a ir al menú “Create app”, donde necesitaremos indicar un nombre para la aplicación y una descripción:

image

A continuación presionaremos el botón “Get Started”, que nos llevará a la pantalla de selección de plan. Básicamente tendremos dos planes distintos para elegir: “Base”, que incluye mapas 2D ilimitados y 2.500 llamadas a otras APIs, como la de Places en este caso. Este plan es totalmente gratuito. El segundo plan es el “Core” cuesta $1.500 al mes, incluye 10.000 llamadas a otras APIs, pero seguro que se nos va de precio. Por ahora podemos quedarnos con el plan “Base” y presionar el botón “Select” que se encuentra al lado del mismo.

La última pantalla nos mostrará dos códigos: App Id y App Code, que deberemos incluir en todas las llamadas al API REST que realicemos:

image

Una vez que hayamos guardado nuestro Id y Code, podemos ir a Visual Studio y crear un nuevo proyecto de Windows Phone 8 para empezar a usar el API de Here Places.

Como ejemplo, vamos a hacer una aplicación que obtenga nuestra posición y nos devuelva los lugares cercanos disponibles. Además, como bonus, usaremos la clase TaskCompletitionSource, para convertir una clase que no usa async/await y trabajar más sencillamente con ella.

Para comenzar, necesitamos la URL del API REST de Places, exactamente una de estas dos:

Siempre que estemos desarrollando, debemos usar la URL que empieza por demo, dejando la otra solo para aplicaciones en producción. Una vez que sabemos que URL usar, vamos a crear un nuevo servicio en nuestra aplicación (asumo que, después de toda la chapa que he dado, estáis usando MVVM ;-P) que se llamará HereService y contendrá un método llamado GetNearbyPlaces y recibirá un objeto GeoCoordinate como parámetro.

public interface IHereService
{
    Task<VMPlace> GetNearbyPlaces(GeoCoordinate currentLocation);
}

public class HereService : IHereService
{
    private const string APP_ID = "YOURAPPID";
    private const string APP_CODE = "YOURAPPCODE";

    public Task<VMPlace> GetNearbyPlaces(GeoCoordinate currentLocation)
    {
        //TODO: Implement awesome code here!!!
    }
}

Una vez definido su Interface e implementación, vamos a empezar a trabajar. El método GetNearbyPlaces devuelve una Task<VMPlace>, pero nosotros usaremos para comunicarnos con el servicio REST la clase HttpWebRequest que no está preparada para async/await ni usa Tasks. De hecho, si os fijáis en el método GetNearbyPlaces, no he incluido la keyword async. Esto es porque no nos va a hacer falta, ya que el código que va a contener, no hace uso de async/await. Sin embargo el modelo de trabajo normal de HttpWebRequest se basa en callbacks. Por norma general, iniciaríamos la petición y cuando se terminase, llamaría a un callback desde el cual podríamos lanzar un evento para notificar el resultado, lo que nos da el tan conocido patrón Async/Completed.

Comenzaremos el código de nuestro método GetNearbyPlaces, construyendo la URI de la petición, básicamente esta debe contener las coordenadas, el ID de aplicación y el CODE de aplicación:

StringBuilder petitionUri = new StringBuilder("http://places.nlp.nokia.com/places/v1/discover/here?");
petitionUri.AppendFormat("at={0},{1}", currentLocation.Latitude, currentLocation.Longitude);
petitionUri.AppendFormat("&app_id={0}&app_code={1}&accept=application/json", APP_ID, APP_CODE);

Usamos la clase StringBuilder para evitar concatenar múltiples Strings, que crearían instancias en memoria, por un lado añadimos las coordenadas y en segundo lugar el ID y CODE de aplicación.

Una vez que hemos creado la URI, vamos a crear una instancia de la clase TaskCompletitionSource y devolver la Task que contiene como resultado de nuestro método:

public Task<VMPlace> GetNearbyPlaces(GeoCoordinate currentLocation)
{
    StringBuilder petitionUri = new StringBuilder("http://places.nlp.nokia.com/places/v1/discover/here?");
    petitionUri.AppendFormat("at={0},{1}", currentLocation.Latitude, currentLocation.Longitude);
    petitionUri.AppendFormat("&app_id={0}&app_code={1}&accept=application/json", APP_ID, APP_CODE);

    var taskCompletitionSource = new TaskCompletionSource<VMPlace>();

    return taskCompletitionSource.Task;
}

¿Para qué hacemos esto? Es muy sencillo. La teoría detrás de las Task es simple: En ejecución, al hacer un await sobre una Task, la aplicación espera a que esa Task tenga un Result, antes de continuar la ejecución del método que la esperó. Al devolver la Task del TaskCompletitionSource, devolvemos una Task no finalizada, sin resultado, por lo que el await esperará hasta que algo o alguien la complete. Esto lo haremos en el callback del método BeginGetResponse de la clase HttpWebRequest, como podemos ver a continuación:

HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
request.BeginGetResponse(async result =>
{
    if (result.IsCompleted)
    {
        VMPlace places = new VMPlace();
        taskCompletitionSource.SetResult(places);
    }
}, null);

Como podemos ver en el código anterior, creamos una expresión Lambda que recibe el resultado de la petición, la respuesta. Si está completada, creamos una nueva instancia de la clase VMPlace y usamos el método SetResult de TaskCompletitionSource para establecer el resultado. Es en este momento en el que la ejecución del método que originalmente llamó con await a GetNearbyPlaces, continúa, pues ya tiene un resultado y la Task se ha completado.

Pero no estamos devolviendo el resultado, simplemente devolvemos una instancia vacía. Primero, vamos a examinar el tipo de resultado que nos ofrece el API REST de Here Places:

{
    "results":
    {
        "next":"http://demo.places.nlp.nokia.com/places/v1/discover/search;context=Zmxvdy1pZD1iZDE0OTE1Yy1hMDAzLTU1OTEtYWU4ZC1iYjRlZjE3MGY0YmZfMTM2NDM2NjA5MTE4NV8wXzQ4MTMmb2Zmc2V0PTIw?app_id=APPID&app_code=APPCODE&size=20&q=restaurant&at=37.7851%2C-122.4047",
        "items":[
            {
                "position":[
                    37.785057,-122.404768
                ],
                "distance":8,
                "title":"Bin 55",
                "averageRating":5,
                "category":
                {
                    "id":"bar-pub",
                    "title":"Bares y clubes",
                    "href":"http://demo.places.nlp.nokia.com/places/v1/categories/places/bar-pub?app_id=_peU-uCkp-j8ovkzFGNU&app_code=gBoUkAMoxoqIWfxWA5DuMQ",
                    "type":"urn:nlp-types:category"
                },
                "icon":"http://download.vcdn.nokia.com/p/d/places2/icons/categories/22.icon",
                "vicinity":"55 Fourth Street<br/>San Francisco 94103<br/>EE.UU.",
                "having":[
                ],
                "type":"urn:nlp-types:place",
                "href":"http://demo.places.nlp.nokia.com/places/v1/places/8409q8yy-b29e8557ae0d4a1d8f0d7b7f9c10a8f0;context=Zmxvdy1pZD1iZDE0OTE1Yy1hMDAzLTU1OTEtYWU4ZC1iYjRlZjE3MGY0YmZfMTM2NDM2NjA5MTE4NV8wXzQ4MTMmcmFuaz0w?app_id=APPID&app_code=APPCODE",
                "id":"8409q8yy-b29e8557ae0d4a1d8f0d7b7f9c10a8f0",
                "references":
                {
                    "building":
                    {
                        "id":"9000000000000921352"
                    }
                }
            }
        ]
    },
    "search":
    {
        "context":
        {
            "location":
            {
                "position":[
                    37.7851,-122.4047
                ],
                "address":
                {
                    "house":"55",
                    "street":"4th St",
                    "postalCode":"94103",
                    "district":"Soma",
                    "city":"San Francisco",
                    "stateCode":"CA",
                    "county":"San Francisco",
                    "countryCode":"USA",
                    "country":"EE.UU.",
                    "text":"55 4th St<br/>San Francisco, CA 94103<br/>EE.UU."
                }
            },
            "type":"urn:nlp-types:place",
            "href":"http://demo.places.nlp.nokia.com/places/v1/places/loc-dmVyc2lvbj0xO3RpdGxlPTU1KzR0aCtTdDtsYXQ9MzcuNzg1MTtsb249LTEyMi40MDQ3O3N0cmVldD00dGgrU3Q7aG91c2U9NTU7Y2l0eT1TYW4rRnJhbmNpc2NvO3Bvc3RhbENvZGU9OTQxMDM7Y291bnRyeT1VU0E7ZGlzdHJpY3Q9U29tYTtzdGF0ZUNvZGU9Q0E7Y291bnR5PVNhbitGcmFuY2lzY287Y2F0ZWdvcnlJZD1idWlsZGluZw;context=Zmxvdy1pZD1iZDE0OTE1Yy1hMDAzLTU1OTEtYWU4ZC1iYjRlZjE3MGY0YmZfMTM2NDM2NjA5MTE4NV8wXzQ4MTM?app_id=APPID&app_code=APPCODE"
        }
    }
}

Nos encontramos ante una respuesta de tipo JSON. Para que sea fácil procesarla, podemos usar la librería NewtonSoft JSON, muy sencilla de utilizar y muy efectiva. Podemos instalarla usando NuGet. Una vez que la tengamos, crearemos la clase VMPlaces y la decoraremos con atributos para que pueda deserializar JSON de forma correcta:

public class VMPlace
{
    [JsonProperty("results")]
    public PlaceResult Result { get; set; }
}

public class PlaceResult
{
    [JsonProperty("next")]
    public string Next { get; set; }

    [JsonProperty("items")]
    public List<Place> Places { get; set; }
}

public class Place
{
    [JsonProperty("position")]
    public double[] Location { get; set; }

    [JsonProperty("title")]
    public string PlaceTitle { get; set; }

    [JsonProperty("distance")]
    public double Distance { get; set; }    
}

Simplemente creamos una jerarquía de clases que nos permita mapear los diferentes elementos y niveles del JSON. En este ejemplo está simplificado, nos faltarían más elementos y propiedades. Ahora ya podemos leer la respuesta usando HttpWebRequest y HttpWebResponse y mapear el JSON a nuestra clase usando NewtonSoft JSON:

if (result.IsCompleted)
{
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

    string resultJson;
    using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
    {
        resultJson = await reader.ReadToEndAsync();
    }
    if (!string.IsNullOrEmpty(resultJson))
    {
        VMPlace places = JsonConvert.DeserializeObject<VMPlace>(resultJson);
        taskCompletitionSource.SetResult(places);
    }
}

En primer lugar, obtenemos la respuesta con el método EndGetResponse de la petición HttpWebRequest que habíamos iniciado. A continuación obtenemos todo el texto usando un StreamReader sobre la Stream que devuelve el método GetResponseStream de HttpWebResponse. Una vez que tenemos nuestra string, solo tenemos que usar el método DeserializeObject de JsonConverter, indicando el tipo de objeto, y tendremos nuestra clase rellena con la información obtenida, ¿fácil, verdad?

Por último, ahora sí, llamamos al método SetResult de nuestro TaskCompletitionSource para terminar la tarea y hacer que devuelva el resultado de nuestra llamada al servicio. En definitiva, nuestro método GetNearbyPlaces quedaría de la siguiente forma:

public Task<VMPlace> GetNearbyPlaces(GeoCoordinate currentLocation)
{
    StringBuilder petitionUri = new StringBuilder("http://places.nlp.nokia.com/places/v1/discover/here?");
    petitionUri.AppendFormat("at={0},{1}", currentLocation.Latitude, currentLocation.Longitude);
    petitionUri.AppendFormat("&app_id={0}&app_code={1}&accept=application/json", APP_ID, APP_CODE);

    var taskCompletitionSource = new TaskCompletionSource<VMPlace>();
            
    HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
    request.BeginGetResponse(async result =>
    {
        if (result.IsCompleted)
        {
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

            string resultJson;
            using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                resultJson = await reader.ReadToEndAsync();
            }
            if (!string.IsNullOrEmpty(resultJson))
            {
                VMPlace places = JsonConvert.DeserializeObject<VMPlace>(resultJson);
                taskCompletitionSource.SetResult(places);
            }
        }
    }, null);

    return taskCompletitionSource.Task;
}

Ahora solo nos queda por ver como llamamos al método, para asegurarnos de que, de cara al desarrollador, se comporta como un método basado en Tasks normal y corriente:

var result = await this.hereService.GetNearbyPlaces(this.myPosition);

if (result != null)
{
    Places = result;
    this.IsBusy = false;
}

Como podemos ver, nuestro método GetNearbyPlaces se usa como un método async más, y no implica ningún trabajo extra a la hora de consumirlo. De la misma forma podemos ver que usar el API REST de Here Places es realmente trivial y nos aporta muchísima información para nuestra aplicación.

En este ejemplo usamos HttpWebRequest, que sigue el antiguo patrón async/completed en vez de WebClient, que tiene métodos async/await basados en Task. ¿Porqué? No es gratuito, ni simplemente para lucirme o por que me guste escribir más código. WebClient está bien, pero no tiene el mismo rendimiento que HttpWebRequest. HttpWebRequest es más rápido y efectivo, además de consumir menos memoria, que WebClient. Esto se debe a que WebClient en realidad es solo un wrapper que utiliza HttpWebRequest / HttpWebResponse para realizar la petición y devolvernos el resultado ya procesado. Personalmente, considero que HttpWebRequest no supone un trabajo complicado y que usándolo en conjunción con TaskCompletitionSource, podemos tener una gran potencia, solo por escribir algunas líneas de código más. Así que no lo olvides:

WebClient es Evil, usa HttpWebRequest 

Conclusión

Y hasta aquí llega el artículo de hoy. Creo que Nokia está haciendo un gran trabajo con su plataforma Here y este API nos lo demuestra, si profundizáis más en el, usando el API Explorer, encontraréis mucha información interesante y muy útil. Como siempre, a continuación tenéis el proyecto de ejemplo que hemos estado viendo en el artículo, totalmente funcional y usando el patrón MVVM, espero que lo disfrutéis:

Un saludo y Happy Coding!!

Windows Phone 8: Interactuando con la pantalla de bloqueo.

Hola a todos!

Una de las novedades de Windows Phone 8 reside en su pantalla de bloqueo. En esta nueva versión del sistema operativo, podemos interactuar de una forma muy completa con la pantalla que se muestra al bloquear nuestro terminal. Podemos mostrar el icono de nuestra aplicación junto a un contador de notificaciones, mostrar texto e incluso cambiar la imagen de fondo.

¿Es esto algo que todas las apps deban implementar para ser más “cool”? No, ni mucho menos. Esta funcionalidad está pensada para ofrecer un mayor grado de personalización al usuario. Por ejemplo, si nuestra aplicación trabaja con imágenes, podemos darle al usuario la opción de usarla como proveedor de la imagen de fondo. Si nuestra app recibe notificaciones tile, quizás sea una buena idea que el usuario pueda configurar la pantalla de bloqueo para que muestre nuestras notificaciones. Incluso en una aplicación de mensajería, podríamos querer mostrar el último mensaje recibido en la pantalla de bloqueo (o no… eso queda a elección del usuario también).

Así, podemos distinguir tres formas de interactuar con la pantalla de bloqueo en Windows Phone 8:

  • Cambiando la imagen de fondo.
  • Mostrando el numero de notificaciones pendientes.
  • Mostrando un texto enviado por nuestra aplicación.

En este post, vamos a repasar cada una de ellas y ver como se implementa.

Cambiando la imagen de fondo

Esta es quizás una de las acciones más visuales, pues cambiamos totalmente el aspecto de la pantalla de bloqueo, cambiando su imagen de fondo.

Para ello, lo primero que necesitamos hacer en nuestro proyecto Windows Phone 8 es modificar el manifiesto de aplicación para añadir una nueva extensión. Esta extensión identificará a nuestra aplicación como proveedora de la imagen de fondo de la pantalla de bloqueo:

<Extensions>
  <Extension ExtensionName="LockScreen_Background" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default"/>
</Extensions>

Una vez que hayamos añadido esta extensión, nuestra aplicación debería aparecer en el desplegable de Background de los settings de la pantalla de bloqueo.

image

Al seleccionar nuestra aplicación, tendremos un botón para lanzarla. La forma de establecer el fondo de la pantalla de bloqueo es muy sencilla. Podemos establecer una imagen que esté incluida en nuestra aplicación o que hayamos descargado y guardado en el isolated storage. Para definir de donde obtenemos la imagen, usaremos distintos esquemas URI:

  • ms-appx:/// Indica que la imagen está en el directorio de instalación de nuestra aplicación.
  • ms-appdata:///local/ Indica que la imagen está en el isolated storage de la aplicación.

Antes de poder establecer la imagen de fondo, tendremos que comprobar si tenemos permiso (el usuario ha seleccionado la aplicación en los settings) o no. Para ello comprobaremos la propiedad IsProvidedByCurrentApplication de la clase LockScreenManager que podemos encontrar en el namespace Windows.Phone.System.UserProfile. Si el resultado es false, podemos usar el método RequestAccessAsync de la misma clase para pedir permiso al usuario. Al ejecutar este método, se mostrará un popup del sistema informando al usuario de que deseamos proveer la imagen de fondo de la pantalla de bloqueo. Si acepta, como resultado obtendremos Granted, de lo contrario Denied. El código quedaría escrito de la siguiente manera:

var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;

if (!isProvider)
{
    var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();

    isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
}

Una vez que hemos comprobado el acceso y pedido permiso al usuario si fuese necesario, ya solo nos queda llamar al método SetImageUri de la clase LockScreen, que se encuentra en el mismo namespace. Es importante que comprobemos que efectivamente tenemos permisos antes de llamar a este método, si lo hacemos y no tenemos permisos, el resultado será una excepción de seguridad. Finalmente, el método completo de nuestro código quedaría de la siguiente forma:

public async Task SetLockScreenWallpaper()
{
    var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;

    if (!isProvider)
    {
        var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();

        isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
    }

    if (isProvider)
    {
        Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appx:///newBackground.png"));
    }
}

Ahora ya podemos desplegar nuestra aplicación en el emulador. Al iniciarse, si hemos llamado al método SetLockScreenWallpaper que hemos creado, nos preguntará si deseamos permitir que la aplicación cambie el fondo de la pantalla de bloqueo. Si presionamos “Yes” (Si), y bloqueamos la pantalla del emulador y la volvemos a encender (pulsando F12 dos veces, se apaga y se vuelve a encender), veremos que ya tenemos nuestra imagen establecida.

image

Mostrando el número de notificaciones pendientes.

El segundo punto de personalización de la pantalla de bloqueo que podemos llevar a cabo, es mostrar las notificaciones pendientes, o cualquier otro número que deseemos, en la pantalla de bloqueo. Para ello, nuestro primer trabajo será crear un  icono de nuestra aplicación con un tamaño de 30×30 píxeles. En la documentación nos avisan de que este icono solo debe contener píxeles blancos y transparentes. Una vez que lo hayamos creado, tenemos que añadirlo al proyecto, estableciendo su propiedad Build Action en Content y Copy to output directory a Copy if newer.

A continuación tenemos que modificar el manifiesto de la aplicación para añadir una extensión, al igual que con el wallpaper, que indique al sistema que podemos establecer un icono y su contador en la pantalla de bloqueo:

<Extensions>
  <Extension ExtensionName="LockScreen_Notification_IconCount" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default"/>
</Extensions>

También tendremos que modificar el nodo Token del manifiesto, exactamente modificaremos la línea DeviceLockImageUri, dentro del nodo PrimaryToken, para indicar la imagen que acabamos de crear:

<DeviceLockImageURI IsRelative="true" IsResource="false">AssetsTilesLockScreenTile.png</DeviceLockImageURI>

Con estas modificaciones del manifiesto, si desplegamos la aplicación al emulador, podemos ir a los settings > Lock sceen y escoger nuestra app para mostrar notificaciones:

image

Como actualizamos el conteo de notificaciones pendientes? Muy fácil, el contador que se muestra en la pantalla de bloqueo es el mismo que el del tile principal de la aplicación. Simplemente actualizando el contador del tile, se actualizará la pantalla de bloqueo automáticamente:

public void UpdateTileCount(int count)
{
    ShellTile tile = ShellTile.ActiveTiles.First();

    FlipTileData data = new FlipTileData();
    data.Count = count;

    tile.Update(data);
}

Con este sencillo código, podemos actualizar el tile principal de la aplicación. Recuerda, que el tile principal siempre existe, aunque no hayamos anclado la app al inicio. Si ejecutamos la app y establecemos un nuevo número, al bloquear la pantalla veremos que se notifica:

image

Así de fácil podemos dar a nuestros usuarios más feedback sobre notificaciones o cualquier otra cosa que deseemos mostrar.

Mostrando un texto enviado por nuestra aplicación.

Y vamos con la última, pero no menos importante, forma de interactuar con la pantalla de bloqueo desde nuestra aplicación. La técnica es la misma que con el contador, lo primero que tendremos que hacer es modificar el manifiesto de nuestra aplicación para añadir una nueva extensión:

<Extensions>
  <Extension ExtensionName="LockScreen_Notification_TextField" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default"/>
</Extensions>

Una vez que hayamos incluido la extensión LockScreen_Notification_TextField, nuestra aplicación aparecerá listada en el desplegable de Settings > Lock screen > App to show detailed status. El texto que se mostrará se obtendrá desde el live tile principal de la aplicación, exactamente de la propiedad BackContent. Recuerda que no es necesario anclar la aplicación a la pantalla de inicio para poder establecer este texto, el tile principal siempre existe aunque no se muestre:

public void UpdateTileText(string text)
{
    ShellTile tile = ShellTile.ActiveTiles.First();

    FlipTileData data = new FlipTileData();
    data.BackContent = text;

    tile.Update(data);
}

Con la extensión y este simple método UpdateTileText, ya podremos comprobar la funcionalidad de nuestra aplicación. Para ello debemos desplegarla en el emulador o en un dispositivo e ir a Settings > Lock screen. En esta pantalla seleccionaremos nuestra aplicación en el desplegable App to show detailed status. Si antes o después de seleccionarla, establecemos la propiedad BackContent de nuestro tile, se reflejará también en la pantalla de bloqueo:

image

BONUS TRACK: Lanzar la pantalla de configuración de bloqueo desde nuestra aplicación.

Ahora que ya hemos visto como poder interactuar con la pantalla de bloqueo cambiando la imagen de fondo, añadiendo un icono de nuestra app con un contador o un texto de detalles, nos falta algo más por hacer. Sería estupendo si, ya que tenemos todas estas posibilidades implementadas en nuestra app, pudiésemos facilitar al usuario la configuración, dándole una forma rápida de ir a los settings de la pantalla de bloqueo desde nuestra app. Y de hecho, lo podemos hacer usando una funcionalidad nueva en Windows Phone 8: el lanzamiento de apps mediante URIs.

En el namespace Windows.System existe una clase llamada Launcher, que contiene un método llamado LaunchUriAsync. Este método nos permite lanzar al sistema cualquier URI y que sea este el que decida como ejecutarla. Por supuesto si lo que lanzamos es una URI de internet, http, https… se abrirá internet explorer. Pero si lanzamos una URI a la que se ha registrado una app, se lanzará esa aplicación.

Bien, pues muchas partes del sistema operativo están relacionadas con URIs exclusivas, como es el caso de la configuración de la pantalla de bloqueo. En este caso la URI asociada es “ms-settings-lock:” con lo que si añadimos el siguiente código a nuestra aplicación, se abrirá la pantalla de configuración de pantalla de bloqueo:

await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings-lock:"));

Así de sencillo. Existen multitud de URIs interesantísimas como “ms-drive-to:” o “ms-walk-to:” que lanzarán la aplicación de navegación del sistema con la ruta calculada en coche o caminando que hayamos expresado.

Conclusión

Pues esto es todo, creo que si nuestra aplicación muestra información al usuario en su tile principal, integrarlo con la pantalla de bloqueo es un “must” que debemos cumplir. Además, según Windows Phone 8 vaya sustituyendo a Windows Phone 7.X, más y más usuarios buscarán aplicaciones que exploten todas las capacidades del dispositivo.

Si además nuestra aplicación trabaja de alguna forma con imágenes, poder establecer la pantalla de bloqueo es también algo increíblemente y que le da un punto diferenciador a nuestra aplicación.

Como siempre, a continuación os dejo los tres ejemplos completos y funcionales que hemos visto en este artículo para que podáis jugar con ellos:

Un saludo y Happy Coding!!

Windows Phone 8: Materiales del wphoneIO del 5 de marzo, MVVM

Hola a todos!

Ayer, junto a Alejandro Campos y Rafael Serna, tuve el placer de participar en una nueva edición de #wphoneIO, el hangout sobre desarrollo para Windows Phone que organiza desarrollo web. En esta ocasión centramos la hora entera de hangout en hablar sobre el modelo MVVM, Rafa nos explicó como funciona el enlace a datos y el DataContext en XAML y yo cree un ejemplo de implementación del patrón MVVM. Muy pocas diapositivas y mucho código, que es lo que al final se aprovecha.

Si no pudisteis verlo en directo ayer, podéis ver la grabación completa a continuación:

Además, aquí os dejo el proyecto con la implementación de MVVM que hicimos en vivo y en directo:

También, al final, tuve unos minutos para hablar sobre el programa de Nokia Premium Developer, las ventajas que ofrece y como podemos aprovecharnos de ellas, ya que creo que es un gran desconocido y nos puede ahorrar mucho dinero al registrarnos como publicador para Windows Phone o al actualizar una suscripción.

Espero que os sea útil, seguro que repetimos y volvemos a hacer una nueva edición con temas más avanzados, algún caso real y con tiempo para responder a todas las preguntas que tengáis.

Un saludo y Happy Coding!

Windows Phone 8: Probando nuestras aplicaciones en dispositivos físicos remotos

Hola a todos!

Hoy os traigo una utilidad que sin duda os ayudará y mucho en vuestros desarrollos. Una de las grandes barreras de entrada en Windows Phone 8 es la necesidad de que nuestro equipo cumpla unas características mínimas para poder usar los emuladores: SLAT, 64bits, Windows 8 Pro… esto evita que muchos podáis usar los emuladores. Otro problema que se plantea es la diferencia de configuraciones que podemos encontrar en dispositivos: Varias resoluciones, tamaño de memoria y de pantalla, almacenamiento interno…

Lo ideal siempre sería poder disponer de varios terminales para realizar las pruebas de la aplicación que estemos desarrollando, pero eso requiere una inversión muy alta de dinero por nuestra parte. Bien, pues Nokia viene al rescate, permitiéndonos probar en terminales físicos Lumia 620, 820 y 920 directamente desde la comodidad de nuestra casa, mediante su sistema RDA: Remote Device Access.

RDA consiste en un pool de dispositivos: Windows Phone, Symbian, S40, Meego, Belle… a los cuales podemos acceder de forma remota. No son emuladores vituales, son dispositivos físicos conectados a servidores que nos permiten usarlos a distancia. ¿Como podemos acceder a ellos? Bueno, el primer paso es registrarnos como desarrolladores nokia en developer.nokia.com,  un registro que es totalmente gratuito. Una vez hecho esto y estando logeados en nuestra cuenta, podemos acceder a la página de RDA. La primera vez que entremos, se validará que nuestro sistema cumple con las características necesarias para la conexión:

rda_02

Para usar el Remote Device Access, necesitaremos Javascript habilitado, un navegador compatible (no funciona con Chrome) y tener Java, al menos JRE 1.5, instalado. Si todo está OK, solo tendremos que pulsar en el botón Proceed y nos llevará directamente a la página de dispositivos:

image

Y lo primero que veremos serán los terminales disponibles, no siendo usados, en estos momentos. Con Windows Phone tenemos tres modelos, 620, 820 y 920. De cada modelo existen varios terminales, de forma que varias personas puedan usarlos al mismo tiempo. Podemos reservar el uso de un dispositivo por un periodo de tiempo de entre 15 minutos y 3 horas. Al pasar el ratón sobre cualquiera de ellos, veremos la información de reserva:

image

Solo tenemos que escoger el tiempo que deseamos usarlo y presionar Start. Si lo que queremos es asegurarnos de poder usar el dispositivo, por ejemplo esta tarde, podemos presionar el enlace de Make later reservation, que nos llevará a una página donde podremos planificar el uso del mismo:

image

Los dispositivos que aparecen en rojo están offline, los que aparecen normales están disponibles. De esta forma podemos planificar una sesión de pruebas con varios dispositivos y saber que estarán disponibles a la hora que los necesitamos.

Volviendo a la pantalla anterior, si presionamos el botón Start, empezaremos a usar nuestro terminal. Esto descargará un archivo jnrd a nuestro equipo y abrirá una aplicación Java en cliente.

image

Una vez aceptada esta advertencia y una confirmación del firewall de Windows, tendremos nuestro dispositivo listo para usar:

image

En este caso, un Lumia 620. Podemos navegar por internet, tenemos acceso a todo el dispositivo. En la barra de botones superior podemos Administrar los archivos, ver el log de consola, Instalar un XAP, Capturar imágenes, capturar video, Ir a pantalla completa…

Conclusión

Nokia RDA, es una solución ideal para probar nuestras aplicaciones en distintos dispositivos físicos de la casa Finlandesa. Por supuesto, en un mundo perfecto, lo mejor sería tener en nuestra oficina un modelo de cada Windows Phone que hay en el mercado para realizar pruebas exhaustivas. Pero sabemos que no estamos en un mundo perfecto y que la inversión en terminales sería gigantesca. Nokia RDA nos permite al menos acceder a la gama de terminales del fabricante finlandes, sin gastar un céntimo, lo cual es todo un avance.

Enlaces

Nokia Developer: https://www.developer.nokia.com/

Nokia Remote Device Access: https://www.developer.nokia.com/Devices/Remote_device_access/

Nokia Premium Developer Program: https://www.developer.nokia.com/Developer_Programs/Premium_program.xhtml

Un saludo y Happy Coding!

WPhoneIO: Patrón MVVM

Hola a todos!

WinPhone8Logo

Tras unas pequeñas vacaciones en las que he estado visitando Redmond con motivo del MVP Summit 2013 y Barcelona para el Mobile World Congress 2013, volvemos a la carga y que mejor que con un evento en vivo. Mañana martes 5 de Marzo a las 20:00 hora de España (GMT+1, 19:00 en Canarias)

En esta ocasión, dedicaremos el evento a hablar sobre el patrón MVVM, como implementarlo, porqué usarlo. Empezaremos viendo como se implementa y cerraremos con un debate acerca de su uso. Si estás empezando en el desarrollo sobre Windows Phone o llevas un tiempo, no te puedes perder este evento.

Todos los detalles, horarios en otras zonas y más información aquí: http://www.desarrolloweb.com/en-directo/modelo-mvvm-windows-phone8-7962.html

Un saludo y Happy Coding!