Windows Phone 7 – Tutorial XXXVII – Localización Tutorial IV

En este articulo veremos como utilizar BingMaps, en nuestro Windows Phone, para ello lo primero que tenemos que hacer es crear una cuenta de BingMAps siguiendo los siguientes pasos

1.- Abrir el navegador con la url http://www.bingmapsportal.com.

2.- Pinchar en el botón Create utilizando tu cuenta de Windows Live Id

3.- En la siguiente página rellenamos los datos

 

4.-Una vez que te has registrado , pincha en el enlace “Create or view keys” del menú de la izquierda.

 

5.- En la siguiente página rellenamos los datos que nos solicita

6.- Una vez que nos ha dado la key, debemos de guardarla ya que será necesaria mas adelante

image

Ya tenemos la key ahora iniciamos un nuevo proyecto en nuestro Visual Studio y añadimos la referencia a la dll Microsoft.Phone.Controls.Maps

image

Una vez añadido abrimos la pantalla Main.xaml y arrastramos desde la ToolBox el objeto map a nuestra pagina y si abrimos el xaml obtendremos un código como este

 

1 <Border x:Name="MapView" 2 Background="Black" 3 Height="768" Width="480"> 4 <my:Map Name="map1" Height=”50” Width=”50” /> 5 </Border>

Eliminamos la altura y anchura por defecto y conseguimos la siguiente pagina

 

Nuestro siguiente paso es abrir el fichero App.xaml.cs y crear una constante que haga referencia a la key que hemos generado antes

1 internal const string Id = "Tu Key";

 

El siguiente paso es enlazar la key con nuestro mapa, para ello debemos de utilizar la clase Microsoft.Phone.Controls.Maps.CredentialsProvider, crearemos una instancia de esta clase en el fichero Main.cs

 

1 private readonly CredentialsProvider _credentialsProvider = new ApplicationIdCredentialsProvider(App.Id); 2 public CredentialsProvider CredentialsProvider 3 { 4 get { return _credentialsProvider; } 5 }

Ahora solo tenemos que enlazar esta propiedad con la propiedad CredentialsProvider de nuestro objeto map a través del databinding

1 <my:Map Name="Map" 2 CredentialsProvider="{Binding CredentialsProvider}" />

Ahora ya podemos utilizarlo en nuestra aplicación, lo primero que vamos ha hacer es que muestre por defecto una localización, para ello debemos de utilizar la propiedad Center de tipo GeoCoordinate , un ejemplo lo tenemos en el siguiente código, en el fichero Main.cs

En el fichero Main.xaml

1 <my:Map Name="Map" 2 CredentialsProvider="{Binding CredentialsProvider}" 3 ZoomLevel="{Binding Zoom, Mode=TwoWay}" 4 Center="{Binding Center, Mode=TwoWay}"> 5 ... 6 </my:Map>

También podemos cambiar el zoom a través de la propiedad Zoom de tipo double por ejemplo

 

1 public double Zoom 2 { 3 get { return _zoom; } 4 set 5 { 6 var coercedZoom = Math.Max(MinZoomLevel, Math.Min(MaxZoomLevel, value)); 7 if (_zoom != coercedZoom) 8 { 9 _zoom = value; 10 NotifyPropertyChanged("Zoom"); 11 } 12 } 13 }

1 <my:Map Name="Map" 2 LogoVisibility="Collapsed" 3 ZoomLevel="{Binding Zoom, Mode=TwoWay}"> 4 <my:Map.Mode> 5 <my:AerialMode ShouldDisplayLabels="True" /> 6 </my:Map.Mode> 7 </my:Map>

y así muchas propiedades que nos proporciona, pero vamos a fijarnos en como podemos poner marcadores o pushpin para señalar direcciones dentro del mapa, para ello utilizaremos la clase Pushpin.  Generalmente añadiremos pushpin mediante código como por ejemplo

1 map1.Center = new GeoCoordinate(47.676289396624654, -122.12096571922302); 2 map1.ZoomLevel = 22; 3 4 //Creamos el pushpin 5 Pushpin pin = new Pushpin(); 6 7 //Envio la localización para el pushpin 8 pin.Location = new GeoCoordinate(47.676289396624654, -122.12096571922302); 9 10 //Añado el pushpin al mapa 11 map1.Children.Add(pin);

 

Quedándonos una imagen del tipo

 

Una de las grandes ventajas del Pushpines que podemos cambiar su apariencia totalmente, por ejemplo aprovechando la propiedad Content.

 

1 ImageBrush image = new ImageBrush() 2 { 3 ImageSource = new System.Windows.Media.Imaging.BitmapImage 4 (new Uri("http://www.clker.com/cliparts/e/d/9/9/1206572112160208723johnny_automatic_NPS_map_pictographs_part_67.svg.med.png")) 5 }; 6 7 //El contenido es una ellipse rellena con la imagen 8 pin.Content = new Ellipse() 9 { 10 Fill = image, 11 StrokeThickness=10, 12 Height = 100, 13 Width = 100 14 }; 15 16 17 map1.Children.Add(pin);

Nos quedaría

 

 

También podemos cambiar el template a través del Blend, por ejemplo

 

1 <ControlTemplate x:Key=”PushpinControlTemplate1? TargetType=”m:Pushpin”> 2 <Grid x:Name=”ContentGrid” Width=”34? Height=”34? > 3 <StackPanel Orientation=”Vertical” > 4 <Grid MinHeight=”31? MinWidth=”29? Margin=”0?> 5 <Ellipse Fill=”#FFFF7F00? 6 Margin=”1? 7 HorizontalAlignment=”Center” 8 VerticalAlignment=”Center” 9 Width=”30? 10 Height=”30? 11 Stroke=”White” 12 StrokeThickness=”3?/> 13 <ContentPresenter HorizontalAlignment=”Center” 14 Content=”{TemplateBinding Content}” 15 ContentTemplate=”{TemplateBinding ContentTemplate}” 16 Margin=”4?/> 17 </Grid> 18 </StackPanel> 19 </Grid> 20 </ControlTemplate>

Si aplicamos este template

 

image

 

Como veis un gran control totalmente personalizable para nuestras aplicaciones que queramos mostrar información en un mapa

Windows Phone 7 – Tutorial XXXVI – Localización Tutorial III

En este articulo veremos como utilizar el emulador de GPS que viene con Mango, para nuestros desarrollos en el emulador. Cuando creamos nuestra aplicación de Windows Phone, Visual Studio nos propone en que framework queremos desarrollar nuestra aplicación, mostrándonos la siguiente ventana.

 

image

 

Una vez creado nuestro proyecto creamos un XAMl sencillo tal que este

1 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 2 <Grid.RowDefinitions> 3 <RowDefinition /> 4 <RowDefinition /> 5 <RowDefinition /> 6 <RowDefinition /> 7 <RowDefinition /> 8 </Grid.RowDefinitions> 9 <Grid.ColumnDefinitions> 10 <ColumnDefinition /> 11 <ColumnDefinition /> 12 </Grid.ColumnDefinitions> 13 <TextBlock Height="30" HorizontalAlignment="Right" Name="textBlock1" Text="Longitud:" VerticalAlignment="Center" TextAlignment="Right" /> 14 <TextBlock Height="30" HorizontalAlignment="Right" Name="textBlock2" Text="Latitud:" TextAlignment="Right" VerticalAlignment="Center" Grid.Row="1" /> 15 <TextBox Grid.Column="1" HorizontalAlignment="Left" Name="txtLongitud" Text="" VerticalAlignment="Center" Width="222" /> 16 <TextBox HorizontalAlignment="Left" Name="txtLatitud" Text="" VerticalAlignment="Center" Width="222" Grid.Column="1" Grid.Row="1" /> 17 <Button Content="Obtener Loca." Grid.ColumnSpan="2" Grid.Row="2" HorizontalAlignment="Center" Name="btnLocalizacion" VerticalAlignment="Center" /> 18 </Grid> 19

Como resultado la pantalla siguiente, un botón para recoger la localización y mostrarla en la cajas de texto.

 

image

El code-behind seria

 

1 public MainPage() 2 { 3 InitializeComponent(); 4 btnLocalizacion.Click += new RoutedEventHandler(btnLocalizacion_Click); 5 } 6 7 void btnLocalizacion_Click(object sender, RoutedEventArgs e) 8 { 9 GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(); 10 watcher.Start(); 11 txtLatitud.Text = watcher.Position.Location.Latitude.ToString(); 12 txtLongitud.Text = watcher.Position.Location.Longitude.ToString(); 13 watcher.Stop(); 14 }

Vamos a utilizar las nuevas herramientas del emulador que vienen con Mango para poder probar nuestra aplicación. Si lanzamos la aplicación en el emulador tendremos la pantalla anterior si pulsamos el botón de obtener Localización , sse nos mostrara en cada caja de texto los valores NaN, es decir, no ha podido recuperar la localización. Ahora con Mango en la barra de herramientas del emulador nos aparece un nuevo botón

image

 

Pulsando sobre el nos aparece una nueva ventana para simular el acelerómetro y el GPS, en nuestro caso pulsando sobre la pestaña de Location se nos presenta la siguiente pantalla

 

image

Si queremos poner una localización en concreto, en la caja se Search ponemos una dirección damos a la lupa y se nos mostrara el mapa con esa dirección, por ejemplo si ponemos Bilbao

 

image

El siguiente paso es pinchar con el ratón en la posición del mapa y se irán poniendo psuhpin según vayamos pinchando, podemos poner tantos como queramos como por ejemplo simular una ruta

image

 

Como podéis ver en la imagen anterior tenemos Current Location con un valor el del PushPin con el número 1 y luego una lista con los siguientes puntos. Si pinchase ahora en el botón obtendría una localización correcta.

 

image

Con esta herramienta podemos simular que el teléfono sigue una ruta determinada por unos puntos, aquí tenéis un video para que veáis el partido que se le puede sacar

 

Demo Emulador GPS Mango

 

Una gran herramienta para nuestros desarrollos en Windows Phone

Windows Phone 7 – Tutorial XXXV – Localización Tutorial II

En el anterior articulo vimos como detectar los cambios de estado del GPS de nuestro teléfono, en este nos vamos a centrar en como recoger nuestra posición en todo momento. Como todos sabéis la localización GPS se mide a partir de tres valores Latitud, Longitud y Altitud, estos tres valores se encuentran en la propiedad Position del objeto GeoCoordinateWatcher, estos valores solo aparecerán si el estado es Ready, sino es así y se tomo la posición en otro momento aparecerán los datos de Latitud, Longitud y Altitud  aunque también se nos indicará junto a la propiedad TimeStamp que hora se tomo la posición.

Lo que nos interesa muchas veces es ir recogiendo la posición cada vez que cambie, por ejemplo, para un programa de rutas de bici…. Para ello debemos utilizar el evento PositionChanged que se lanzara cada vez que el usuario cambie de posición. Es importante recordar que si queremos cambiar elementos visuales de la UI tendremos que utilizar el objeto Dispatcher.

Como siempre es mejor verlo en líneas de código os la dejo aquí.

 

1 GeoCoordinateWatcher geowatcher; 2 private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 3 { 4 geowatcher = new GeoCoordinateWatcher(); 5 geowatcher.PositionChanged += geowatcher_PositionChanged; 6 } 7 private void geowatcher_PositionChanged(object sender, 8 GeoPositionChangedEventArgs<GeoCoordinate> e){ 9 var locationText = PositionString(e.Position.Location); 10 this.Dispatcher.BeginInvoke(() = > this.GeoLocationText.Text = locationText); 11 } 12 private string PositionString(GeoCoordinate position) 13 { 14 return "Latitude: " + position.Latitude.ToString() + Environment.NewLine + 15 "Longitude: " + position.Longitude.ToString() + Environment.NewLine + 16 "Altitude: " + position.Altitude.ToString(); 17 } 18

Generalmente queremos coger la posición del GPS cada cierto tiempo y no siempre, por ejemplo, coger la posición cada 100 metros, para ello tendremos que utilizar la propiedad MovementThreshold donde le indicaremos cada cuantos metros como mínimo debe de ejecutarse el evento PositionChanged.

 

Ahora viene la pregunta del millo, como probamos en nuestro emulador?. La repuesta en estos momentos no es tan sencilla ya que tendremos que elegir entre la versión 7.0 o Mango, en este articulo vamos a ver las dos empezando por la primera versión 7.0

Como en nuestro emulador no disponemos de los sensores debemos de utilizar Mock para simular el GPS, para ello Microsoft nos provee de la interfaz IGeoPositionWatcher < GeoCoordinate > para que creemos nuestro Mock, en este articulo no vamos a ver como crear nuestro Mock sino utilizar uno ya hecho. Si hay que decir que esto es valido para cuando desarrollemos para la versión 7.0, ya que Mango nos va a proporcionar las herramientas de simulación integradas con el emulador que veremos en el siguiente articulo.

Yo utilizo Windows Phone GPS Emulator una pequeña aplicación hecha en WPF que nos va a permitir probar nuestra aplicación en el emulador aunque no tengamos GPS. Con esta herramienta podemos enviar tanto un punto simulando nuestra localización, como una ruta con puntos intermedios.

La herramienta incluye

  • Una aplicación windows que emula el GPS
  • el assembly Windows Phone GPS Emulator
  • Una simple aplicación de test
  • Una aplicación completa utilizando BingMaps

Para usarlo en nuestra aplicación debemos de seguir unos sencillos pasos. El paquete de descarga nos ofrece la dll GPSEmulatorClient, esta dll contiene la clase GeoCoordinateWatcher que cumple la interfaz IGeoPositionWatcher < GeoCoordinate > de la clase System.Device.Location.GeoCoordinateWatcher, de manera que programaticamente nos va a dar igual utilizar una que otra ya que solo se diferencian en el namespace.

Debemos de crear una variable de compilación en debug y la llamamos GPS_EMULATOR , de esta manera distinguiremos las llamadas a los métodos de la dll “real” con la de “mock”, por ejemplo.

1 #if GPS_EMULATOR 2 _Watcher = new GpsEmulatorClient.GeoCoordinateWatcher(); 3 #else 4 _Watcher = new System.Device.Location.GeoCoordinateWatcher(); 5 #endif

De esta manera podemos probar todo nuestro código que afecte a la localización en el emulador perfectamente, además las llamadas a métodos de localización de la dll de mock se comunican con la aplicación WPF a través de WCF, mostrándonos información en el plano y pudiendo enviar información de la aplicación al GPS, por ejemplo si solicitamos una posición en la aplicación del teléfono cogerá la posición que tenga la aplicación WPF, de manera que la aplicación WPF hace las veces de GPS

Debemos de recordar que para ejecutar la aplicación en WPF tiene que tener permisos de administrador, sino no será capaz de crear los canales de WCF, es una herramienta muy útil cuando desarrollamos contra el GPS, pero nunca debemos olvidarnos de probar contra un dispositivo físico

Windows Phone 7 – Tutorial XXXIV – Localización Tutorial I

En esta serie de artículos trataremos de aprender como utilizar el GPS de nuestro Windows Phone además de aprovecharnos del control Bing Maps. En este primer articulo trataremos el objeto GeoCoordinateWatcher, este objeto es el que nos proporcionará el acceso al GPS del teléfono.Esta clase se encuentra en la dll System.Device.dll que tendremos que hacer referencia en nuestros proyectos.

Lo primero que tenemos que saber es que este objeto nos proporciona el estado del GPS del teléfono a través de la enumeración GeoPositionStatus, para detectar los cambios de estado de nuestro GPS y actuar en consecuencia en nuestra aplicación utilizaremos el evento StatusChanged.

Cuando instanciamos el objeto su estado siempre será NoData, hasta que no arranquemos el servicio con Start no cambiara de estado comprobando si el GPS esta disponible o no indicándolo en el estado. En este sencillo código podemos probar la aplicación.

 

1 GeoCoordinateWatcher geowatcher; 2 private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e){ 3 geowatcher = new GeoCoordinateWatcher(); 4 geowatcher.StatusChanged += geowatcher_StatusChanged; 5 } 6 private void StartButton_Click(object sender, RoutedEventArgs e){ 7 geowatcher.Start(); 8 } 9 private void StopButton_Click(object sender, RoutedEventArgs e){ 10 geowatcher.Stop(); 11 } 12 private void geowatcher_StatusChanged(object sender, 13 GeoPositionStatusChangedEventArgs e){ 14 this.Dispatcher.BeginInvoke(() = > { 15 this.StatusText.Text = e.Status.ToString(); 16 }); 17 } 18

Si se nos muestra el estado Disabled debemos de chequear la propiedad Permission de la instancia de nuestro objeto GeoCoordinateWatcher, esta propiedad devolverá Granted, Denied, o Unknown, valores de la enumeración GeoPositionPermission , dependiendo de estos valores deberemos de solicitar al usuario permiso para que nuestra aplicación acceda a al GPS y recoger la posición.

Al código anterior en el evento Status_Changed podemos actuar antes los diferentes estados

1 if (geowatcher.Status == GeoPositionStatus.Disabled) 2 { 3 if (geowatcher.Permission == GeoPositionPermission.Denied) 4 { 5 MessageBox.Show("El servicio de localización esta deshabilitado."); 6 } 7 else 8 { 9 MessageBox.Show("El servicio de localización no esta funcionando."); 10 } 11 geowatcher.StatusChanged -= new EventHandler<GeoPositionStatusChangedEventArgs>(geowatcher_StatusChanged); 12 geowatcher.Stop(); 13 } 14 else if (geowatcher.Status == GeoPositionStatus.Initializing) 15 { 16 userMessage.Text = "Inicializando localización"; 17 } 18 else if (geowatcher.Status == GeoPositionStatus.NoData) 19 { 20 MessageBox.Show("Los datos de localización no esta disponible"); 21 } 22 else if (geowatcher.Status == GeoPositionStatus.Ready) 23 { 24 25 }

A la hora de utilizar el GPS tendremos que tener en cuenta si queremos que recoja la posición del GPS, de la Wifi o de la red de móvil, dependiendo de la aplicación y sus necesidades será necesario una alta precisión o no. Esto es importante para que gestionemos bien el gasto de batería. Este valor lo podemos indicar a partir de la propiedad DesiredAccuracy  y se lo indicaremos con la enumeración GeoPositionAccuracy que contiene los valores High y Low, por defecto es Low con lo que utilizará la red de móvil o wifi para coger la posición, si queremos que tire del GPS le tendremos que indicar el valor High.

En el siguiente articulo veremos como coger la posición del GPS una vez que lo tenemos en estado Ready.

Windows Phone 7 – Tutorial XXXIII – Utilizar TweetSharp para autenticarse

Después de unos correos que me han llegado a raíz de mi ultimo articulo, la gente me ha estado preguntando como usar autenticarse usando la librería Tweetsharp que recomendaba en ese articulo.

La verdad es que es muy sencilla de utilizar y me voy a saltar los pasos de como recoger los APIKey, ConsumerKey y ConsumerSecret que lo explicaba en el anterior articulo. Como siempre lo voy a realizar con un ejemplo, en este caso de consola.

El primer paso lógicamente es bajarnos la librería de Codeplex que se encuentra en la siguiente direción:TweetSharp Library.

El segundo paso es tambien facil, añadimos las referencias Hammock , Newtonsoft.Json , TweetSharp , TweetSharp.Twitter a nuestro proyecto

 

 

El siguiente paso ya es codificar la llamada, como veries el código es muy simple

 

1 using System; 2 using System.Configuration; 3 using System.Diagnostics; 4 using TweetSharp; 5 using TweetSharp.Model; 6 using TweetSharp.Twitter.Service; 7 8 namespace ConsoleApplication1 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 15 TwitterClientInfo twitterClientInfo = new TwitterClientInfo(); 16 twitterClientInfo.ConsumerKey = ConsumerKey; 17 twitterClientInfo.ConsumerSecret = ConsumerSecret; 18 //Creamos el servicio de Twitter 19 TwitterService twitterService = new TwitterService(twitterClientInfo); 20 21 if (string.IsNullOrEmpty(AccessToken) || string.IsNullOrEmpty(AccessTokenSecret)) 22 { 23 //recogemos el TokenSecret y AuthorisationUrl 24 25 OAuthToken requestToken = twitterService.GetRequestToken(); 26 string authUrl = twitterService.GetAuthorizationUrl(requestToken); 27 28 29 Console.WriteLine("Permite a esta APP enviar Tweets"); 30 Process.Start(authUrl); //Lanzamos el navegador con AuthUrl. 31 32 //Permitir la APP 33 Console.WriteLine("Introduce el PIN:"); 34 string pin = Console.ReadLine(); 35 36 OAuthToken accessToken = twitterService.GetAccessToken(requestToken, pin); 37 38 string token = accessToken.Token; 39 string tokenSecret = accessToken.TokenSecret; 40 41 Console.WriteLine("AccessToken: " + token); 42 Console.WriteLine("AccessTokenSecret: " + tokenSecret); 43 } 44 45 twitterService.AuthenticateWith(AccessToken, AccessTokenSecret); 46 twitterService.SendTweet("Mi primer Tweet desde Tweetsharp"); 47 Console.WriteLine("Introduce un Tweet"); 48 string tweetMessage; 49 50 while (true) 51 { 52 tweetMessage = Console.ReadLine(); 53 if(tweetMessage.ToLower() == "salir") 54 { 55 break; 56 } 57 twitterService.SendTweet(tweetMessage); 58 } 59 } 60 61 62 63 #region ConsumerKey & ConsumerSecret 64 private static string ConsumerSecret 65 { 66 get { return ConfigurationManager.AppSettings["ConsumerSecret"]; } 67 } 68 69 private static string ConsumerKey 70 { 71 get { return ConfigurationManager.AppSettings["ConsumerKey"]; } 72 } 73 74 private static string AccessToken 75 { 76 get { return ConfigurationManager.AppSettings["AccessToken"]; } 77 } 78 private static string AccessTokenSecret 79 { 80 get { return ConfigurationManager.AppSettings["AccessTokenSecret"]; } 81 } 82 #endregion 83 } 84 }

 

Bien esto funciona para este tipo de aplicaciones pero para nuestro querido Windows Phone deberemos de optar por otro método mas sencillo y es utilizar xAuth en nuestra aplicación, TweetSharp nos facilita este tipo de autenticación en Twitter y es tan sencillo como

 

1 TwitterService service = new TwitterService("consumerKey", "consumerSecret"); 2 OAuthAccessToken access = service.GetAccessTokenWithXAuth("username", "password");

Como veis mucho mas sencillo si es posible, tenéis información de como se trabaja con este tipo de autenticación en http://apiwiki.twitter.com/Twitter-REST-API-Method:-oauth-access_token-for-xAuth

 

Espero que no hagáis muchas aplicaciones de Twitter