di: Roberto Brunetti 30 Giugno 2010
Anche in questo caso diamo uno sguardo prima al codice partendo dal form, che ormai abbiamo imparato a chiamare Page, per poi concentrarci su qualche dettaglio sul servizio di localizzazione.
La Page consente di attivare e di fermare il servizio e mette a disposizione sei TextBlock: i primi 5 consentono di visualizzare la latitudine, la longitudine, l'altezza e l'orientamento (per ques'ultimo occorre verificare nelle prossime versioni il supporto e l'interazione con la bussola: in questa prima versione è possibile ricavare l'orientamento se il device è in movimento).
Ovviamente serve un movimento del device per calcolare la velocità che visualizzeremo nel penultimo TextBlock. L'ultimo elemento della user interface è dedicato ad accogliere le informazioni di stato sul servizio. Il codice necessita delle reference a System.Device.Location per utilizzare la classe GeoCoordinateWatcher e i relativi eventi:
using System.Device.Location
namespace _30_LocationService
{
public partial class MainPage : PhoneApplicationPage
{
GeoCoordinateWatcher watcher;
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
}
private void StarTrack_Click(Object sender, RoutedEventArgs e)
{
if(watcher == null)
{
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Low);
//watcher.MovementThreshold = 20;
}
n
IsolatedStorageSettings.ApplicationSettings["Data"] = DateTime.Now.ToString();
// N.B. Save automatico quando si chiude l'applicazione
// se stateless è bene salvare subito
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
Dopo aver definito per semplicità l'oggetto watcher a livello di Page, nel metodo StartTrack_Click inizializzamo l'oggetto con una nuova istanza di GeoCoordinateWatcher. Come si nota è possibile passare un livello di accuratezza che servirà al device per fornire informazioni da GPS, Wi-Fi o rete cellulare in base alle preferenze: in pratica è inutile utilizzare un sistema molto preciso che consuma molta batteria se non abbiamo bisogno di calcolare gli spostamenti inferiori a 20 metri, così come è possibile invece impostare GeoPositionAccuracy.High per ottenere dati molto precisi pur consumando più batteria. MovementThreshold è un altro parametro sulla stessa linea: consente di impostare il limite di notifica per evitare che una applicazione venga informata troppo frequentemente su spostamenti minimi e ininfluenti rispetto all'applicazione stessa.
Il metodo StartTrack_Click prosegue con l'aggancio a due eventi che, rispettivamente, consentono di capire se stiamo ricevendo dati dal servizio di Location e qual è la nostra posizione. Il codice del pulsante Stop si commenta da solo. Il codice del primo evento è il seguente:
void watcher_StatusChanged(Object sender, GeoPositionStatusChangedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() => MyStatusChanged(e));
}
void MyStatusChanged(GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
// Controllo disabilitazione del servizio da parte dell'utente
if(watcher.Permission == GeoPositionPermission.Denied)
{
StatusTextBlock.Text = "Hai disabilitato il servizio";
}
else
{
StatusTextBlock.Text = "Il servizio non funziona";
}
break;
case GeoPositionStatus.Initializing:
StartTrackButton.IsEnabled = false;
break;
case GeoPositionStatus.NoData:
StatusTextBlock.Text = "Non riesco a recuperare le informazioni";
StopTrackButton.IsEnabled = true;
break;
case GeoPositionStatus.Ready:
StatusTextBlock.Text = "Dati disponibili";
StopTrackButton.IsEnabled = true;
break;
}
}
A parte rimarcare il fatto che gli eventi sono notificati da un thread secondario che impone, sin da Windows Forms versione 1, di chiedere al thread principale di effettuare una operazione sulla Page, l'evento è molto semplice da descrivere: in base a GeoPositionStatusChangedEventArgs sappiamo se il servizio è stato disabilitato dall'utente (o non abilitato per la nostra applicazione), se il servizio è in fase di inizializzazione, se riesce a leggere dati nonostante il suo apparente funzionamento oppure sta leggendo dati dalle sue fonti.
Con lo stesso approccio, passiamo al thread principale anche le informazioni sui dati stessi:
void watcher_PositionChanged(Object sender, GeoPositionChangedEventArgse) { Deployment.Current.Dispatcher.BeginInvoke(() => MyPositionChanged(e)); } void MyPositionChanged(GeoPositionChangedEventArgs e) { LatitudeTextBlock.Text = e.Position.Location.Latitude.ToString("0.000"); LongitudeTextBlock.Text = e.Position.Location.Longitude.ToString("0.000"); altitudeTextBlock.Text = e.Position.Location.Altitude.ToString("0.000"); courseTextBlock.Text = e.Position.Location.Course.ToString("0.000"); speedTextBlock.Text = e.Position.Location.Speed.ToString("0.000"); }
Il risultato è visualizzabile anche sull'emulatore, a patto di non aver scelto "Accuracy = High" e di avere una connessione Wi-Fi o cellulare (o, ma non sono riuscito a eseguire test, anche un GPS sul PC). Eseguendo il progetto otteniamo i valori sulla posizione corrente.
Ovviamente Speed e Course sono "NaN" in quanto eseguiamo il test sull'emulatore. È possibile simulare l'invio di dati al servizio utilizzando le Reactive Extension (Rx Framework) di .NET.
Alla prossima
Guida Windows Azure Code SnippetsLe migliori pratiche per far girare le applicazioni "in the cloud",... |
Guida ASP.NET MVC Best PracticesUn workflow dettagliato e ricco di suggerimenti pratici per... |
Guida ASP.NET Starter KitUn modo semplice per imparare ad utilizzare le tecnologie Microsoft... |
Ogni giovedì, direttamente nella tua e-mail: articoli, guide, tutorial e script ASP, ASP.Net, SQL server e IIS.
Iscriviti alla newsletter
|
|
Corso Progettazione database11 Maggio 2012 a Milano |
|
|
Amministratore di Reti Windows Server 200811 Giugno 2012 a Milano |
|
Nessun corso previsto |