Ottenere la posizione dell'utente

Nota

MapControl e i servizi per le mappe richiedono una chiave di autenticazione delle mappe denominata MapServiceToken. Per altre informazioni su come ottenere e impostare una chiave di autenticazione delle mappe, vedere Richiedere una chiave di autenticazione per le mappe.

Trovare la posizione dell'utente e rispondere alle modifiche nella posizione. L'accesso alla posizione dell'utente viene gestito dalle impostazioni di privacy nell'app Impostazioni. Questo argomento illustra anche come verificare se l'app dispone dell'autorizzazione per accedere alla posizione dell'utente.

Suggerimento Per saperne di più su come accedere alla posizione dell'utente nell'app, scaricare gli esempi seguenti dalla repository di esempi di Windows Universal su GitHub.

Abilitare la funzionalità posizione

  1. In Esplora soluzioni fare doppio clic su package.appxmanifest e selezionare la scheda Funzionalità.
  2. Nell'elenco Funzionalità selezionare la casella Posizione. Ciò aggiunge la location funzionalità del dispositivo al file manifesto del pacchetto.
  <Capabilities>
    <!-- DeviceCapability elements must follow Capability elements (if present) -->
    <DeviceCapability Name="location"/>
  </Capabilities>

Ottenere la posiziona corrente

Questa sezione descrive come rilevare la posizione geografica dell'utente usando le API nello spazio dei nomi Windows.Devices.Geolocation.

Passaggio 1: Richiedere l'accesso alla posizione dell'utente

A meno che l'app non abbia funzionalità di posizione grossolana (vedi nota), si deve richiedere l'accesso alla posizione dell'utente usando il metodo RequestAccessAsync prima di tentare di accedere alla posizione. Si deve chiamare il metodo RequestAccessAsync dal thread dell'interfaccia utente e l'app deve essere in primo piano. L'app non sarà in grado di accedere alle informazioni sulla posizione dell'utente fino a quando l'utente non concede l'autorizzazione all'app.*

using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();

Il metodo RequestAccessAsync richiede all'utente l'autorizzazione per accedere alla propria posizione. All'utente viene richiesto una sola volta (per app). Dopo la prima volta che concedono o negano l'autorizzazione, questo metodo non richiede più all'utente l'autorizzazione. Per consentire all'utente di modificare le autorizzazioni relative alla posizione dopo che sono state richieste, è consigliabile fornire un collegamento alle impostazioni della posizione, come illustrato più avanti in questo argomento.

Nota: la funzionalità di posizione grossolana consente all'app di ottenere una posizione intenzionalmente offuscata (imprecisa) senza ottenere l'autorizzazione esplicita dell'utente (il commutatore di posizione a livello di sistema deve comunque essere attivo). Per informazioni su come usare la posizione grossolana nell'app, vedere il metodo AllowFallbackToConsentlessPositions nella classe Geolocator.

Passaggio 2: Ottenere la posizione dell'utente e registrarsi per le modifiche apportate alle autorizzazioni di posizione

Il metodo GetGeopositionAsync esegue una lettura una tantum della posizione corrente. In questo caso, viene usata un'istruzione switch con accessStatus (dall'esempio precedente) per agire solo quando è consentito l'accesso alla posizione dell'utente. Se è consentito l'accesso alla posizione dell'utente, il codice crea un oggetto Geolocator, esegue la registrazione per le modifiche apportate alle autorizzazioni di posizione e richiede la posizione dell'utente.

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        _rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);

        // If DesiredAccuracy or DesiredAccuracyInMeters are not set (or value is 0), DesiredAccuracy.Default is used.
        Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = _desireAccuracyInMetersValue };

        // Subscribe to the StatusChanged event to get updates of location status changes.
        _geolocator.StatusChanged += OnStatusChanged;

        // Carry out the operation.
        Geoposition pos = await geolocator.GetGeopositionAsync();

        UpdateLocationData(pos);
        _rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
        break;

    case GeolocationAccessStatus.Denied:
        _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Visible;
        UpdateLocationData(null);
        break;

    case GeolocationAccessStatus.Unspecified:
        _rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
        UpdateLocationData(null);
        break;
}

Passaggio 3: Gestire le modifiche nelle autorizzazioni per la posizione

L'oggetto Geolocator attiva l'evento StatusChanged per indicare che le impostazioni della posizione dell'utente sono state modificate. Tale evento passa lo stato corrispondente tramite il mittente dell'argomento. Proprietà dello stato (di tipo PositionStatus). Si noti che questo metodo non viene chiamato dal thread dell'interfaccia utente e l'oggetto Dispatcher richiama le modifiche dell'interfaccia utente.

using Windows.UI.Core;
...
async private void OnStatusChanged(Geolocator sender, StatusChangedEventArgs e)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // Show the location setting message only if status is disabled.
        LocationDisabledMessage.Visibility = Visibility.Collapsed;

        switch (e.Status)
        {
            case PositionStatus.Ready:
                // Location platform is providing valid data.
                ScenarioOutput_Status.Text = "Ready";
                _rootPage.NotifyUser("Location platform is ready.", NotifyType.StatusMessage);
                break;

            case PositionStatus.Initializing:
                // Location platform is attempting to acquire a fix.
                ScenarioOutput_Status.Text = "Initializing";
                _rootPage.NotifyUser("Location platform is attempting to obtain a position.", NotifyType.StatusMessage);
                break;

            case PositionStatus.NoData:
                // Location platform could not obtain location data.
                ScenarioOutput_Status.Text = "No data";
                _rootPage.NotifyUser("Not able to determine the location.", NotifyType.ErrorMessage);
                break;

            case PositionStatus.Disabled:
                // The permission to access location data is denied by the user or other policies.
                ScenarioOutput_Status.Text = "Disabled";
                _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);

                // Show message to the user to go to location settings.
                LocationDisabledMessage.Visibility = Visibility.Visible;

                // Clear any cached location data.
                UpdateLocationData(null);
                break;

            case PositionStatus.NotInitialized:
                // The location platform is not initialized. This indicates that the application
                // has not made a request for location data.
                ScenarioOutput_Status.Text = "Not initialized";
                _rootPage.NotifyUser("No request for location is made yet.", NotifyType.StatusMessage);
                break;

            case PositionStatus.NotAvailable:
                // The location platform is not available on this version of the OS.
                ScenarioOutput_Status.Text = "Not available";
                _rootPage.NotifyUser("Location is not available on this version of the OS.", NotifyType.ErrorMessage);
                break;

            default:
                ScenarioOutput_Status.Text = "Unknown";
                _rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
                break;
        }
    });
}

Rispondere agli aggiornamenti della posizione

Questa sezione descrive come usare l'evento PositionChanged per ricevere gli aggiornamenti della posizione dell'utente in un determinato periodo di tempo. Poiché l'utente può revocare l'accesso alla posizione in qualsiasi momento, è importante chiamare RequestAccessAsync e usare l'evento StatusChanged come illustrato nella sezione precedente.

Questa sezione presuppone che sia già stata abilitata la funzionalità posizione e che sia stata chiamata RequestAccessAsync dal thread dell'interfaccia utente dell'app in primo piano.

Passaggio 1: Definire l'intervallo del report e registrarsi per gli aggiornamenti della posizione

In questo esempio, viene usata un'istruzione switch con accessStatus (dall'esempio precedente) per agire solo quando è consentito l'accesso alla posizione dell'utente. Se è consentito l'accesso alla posizione dell'utente, il codice crea un oggetto Geolocator, specifica il tipo di rilevamento e registra gli aggiornamenti della posizione.

L'oggetto Geolocator può attivare l'evento PositionChanged in base a una modifica della posizione (rilevamento basato sulla distanza) o a una modifica nel tempo (rilevamento basato su periodico).

  • Per il rilevamento basato sulla distanza, impostare la proprietà MovementThreshold.
  • Per il rilevamento periodico, impostare la proprietà ReportInterval.

Se nessuna delle proprietà è impostata, viene restituita una posizione ogni 1 secondo (equivalente a ReportInterval = 1000). In questo caso viene usato un intervallo di report di 2 secondi (ReportInterval = 2000).

using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        // Create Geolocator and define perodic-based tracking (2 second interval).
        _geolocator = new Geolocator { ReportInterval = 2000 };

        // Subscribe to the PositionChanged event to get location updates.
        _geolocator.PositionChanged += OnPositionChanged;

        // Subscribe to StatusChanged event to get updates of location status changes.
        _geolocator.StatusChanged += OnStatusChanged;

        _rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);
        LocationDisabledMessage.Visibility = Visibility.Collapsed;
        StartTrackingButton.IsEnabled = false;
        StopTrackingButton.IsEnabled = true;
        break;

    case GeolocationAccessStatus.Denied:
        _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Visible;
        break;

    case GeolocationAccessStatus.Unspecified:
        _rootPage.NotifyUser("Unspecificed error!", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Collapsed;
        break;
}

Passaggio 2: Gestire gli aggiornamenti della posizione

L'oggetto Geolocator attiva l'evento PositionChanged per indicare che la posizione dell'utente è cambiata o il tempo trascorso, a seconda della modalità di configurazione. Tale evento passa la posizione corrispondente tramite la proprietà Position dell'argomento (di tipo Geoposition). In questo esempio, il metodo non viene chiamato dal thread dell'interfaccia utente e l'oggetto Dispatcher richiama le modifiche dell'interfaccia utente.

using Windows.UI.Core;
...
async private void OnPositionChanged(Geolocator sender, PositionChangedEventArgs e)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        _rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
        UpdateLocationData(e.Position);
    });
}

Modificare le impostazioni di privacy della posizione

Se le impostazioni della privacy della posizione non consentono all'app di accedere alla posizione dell'utente, è consigliabile fornire un collegamento pratico alle impostazioni della privacy della posizione nell'app Impostazioni. In questo esempio viene usato un controllo Collegamento ipertestuale per passare all'URI ms-settings:privacy-location.

<!--Set Visibility to Visible when access to location is denied -->  
<TextBlock x:Name="LocationDisabledMessage" FontStyle="Italic"
                 Visibility="Collapsed" Margin="0,15,0,0" TextWrapping="Wrap" >
          <Run Text="This app is not able to access Location. Go to " />
              <Hyperlink NavigateUri="ms-settings:privacy-location">
                  <Run Text="Settings" />
              </Hyperlink>
          <Run Text=" to check the location privacy settings."/>
</TextBlock>

In alternativa, l'app può chiamare il metodo LaunchUriAsync per avviare l'app Impostazioni dal codice. Per maggiori informazioni, vedere Avviare l'app Impostazioni di Windows.

using Windows.System;
...
bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));

Risolvere i problemi dell’app

Prima che l'app possa accedere alla posizione dell'utente, la posizione deve essere abilitata nel dispositivo. Nell'app Impostazioni verificare che le impostazioni di privacy della posizione seguenti siano attivate:

  • Posizione per questo dispositivo... è attivato (non applicabile in Windows 10 Mobile)
  • L'impostazione dei servizi di posizione, Location, è attivata
  • In Scegliere app che possono usare la posizione, l'app è impostata su on