Condividi tramite


Georilevazione

Browse sample. Esplorare l'esempio

Questo articolo descrive come usare l'interfaccia dell'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI). IGeolocation Questa interfaccia fornisce API per recuperare le coordinate di georilevazione correnti del dispositivo.

L'implementazione predefinita dell'interfaccia IGeolocation è disponibile tramite la Geolocation.Default proprietà . Sia l'interfaccia che Geolocation la IGeolocation classe sono contenute nello spazio dei Microsoft.Maui.Devices.Sensors nomi .

Attività iniziali

Per accedere alla funzionalità Geolocation, è necessaria la configurazione seguente specifica della piattaforma:

Le autorizzazioni di posizione grossolana o fine, o entrambe, devono essere specificate e devono essere configurate nel progetto Android.

Se inoltre l'app usa come destinazione Android 5.0 (livello API 21) o versione successiva, è necessario dichiarare che l'app usa le funzionalità hardware nel file manifesto. È possibile aggiungerla nei modi seguenti:

  • Aggiungere l'autorizzazione basata su assembly:

    Aprire il file Platforms/Android/MainApplication.cs e aggiungere gli attributi assembly seguenti dopo using le direttive:

    [assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
    [assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
    [assembly: UsesFeature("android.hardware.location", Required = false)]
    [assembly: UsesFeature("android.hardware.location.gps", Required = false)]
    [assembly: UsesFeature("android.hardware.location.network", Required = false)]
    

    Se l'applicazione ha come destinazione Android 10 - Q (livello API 29 o versione successiva) e richiede LocationAlways, è necessario aggiungere anche questa richiesta di autorizzazione:

    [assembly: UsesPermission(Manifest.Permission.AccessBackgroundLocation)]
    

    - oppure -

  • Aggiornare il manifesto Android:

    Aprire il file Platforms/Android/AndroidManifest.xml e aggiungere quanto segue nel manifest nodo:

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location" android:required="false" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    <uses-feature android:name="android.hardware.location.network" android:required="false" />
    

    Se l'applicazione ha come destinazione Android 10 - Q (livello API 29 o versione successiva) e richiede LocationAlways, è necessario aggiungere anche questa richiesta di autorizzazione:

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    

    - oppure -

  • Aggiornare il manifesto Android nell'editor del manifesto:

    In Visual Studio fare doppio clic sul file Platforms/Android/AndroidManifest.xml per aprire l'editor del manifesto Android. Quindi, in Autorizzazioni necessarie controllare le autorizzazioni elencate in precedenza. Il file AndroidManifest.xml verrà aggiornato automaticamente.

Suggerimento

Assicurarsi di leggere la documentazione di Android sugli aggiornamenti della posizione in background, perché esistono molte restrizioni da considerare.

Ottenere l'ultima posizione nota

Il dispositivo potrebbe aver memorizzato nella cache la posizione più recente del dispositivo. Usare il GetLastKnownLocationAsync() metodo per accedere alla posizione memorizzata nella cache, se disponibile. Questa operazione è spesso più veloce rispetto all'esecuzione di una query di posizione completa, ma può essere meno accurata. Se non esiste alcun percorso memorizzato nella cache, questo metodo restituisce null.

Nota

Quando necessario, l'API georilevazione richiede all'utente le autorizzazioni.

Nell'esempio di codice seguente viene illustrato il controllo di una posizione memorizzata nella cache:

public async Task<string> GetCachedLocation()
{
    try
    {
        Location location = await Geolocation.Default.GetLastKnownLocationAsync();

        if (location != null)
            return $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";
    }
    catch (FeatureNotSupportedException fnsEx)
    {
        // Handle not supported on device exception
    }
    catch (FeatureNotEnabledException fneEx)
    {
        // Handle not enabled on device exception
    }
    catch (PermissionException pEx)
    {
        // Handle permission exception
    }
    catch (Exception ex)
    {
        // Unable to get location
    }

    return "None";
}

A seconda del dispositivo, non tutti i valori di posizione potrebbero essere disponibili. Ad esempio, la Altitude proprietà potrebbe essere null, avere un valore pari a 0 o avere un valore positivo che indica i metri sopra il livello del mare. Altri valori che potrebbero non essere presenti includono le Speed proprietà e Course .

Ottenere il percorso corrente

Anche se il controllo dell'ultima posizione nota del dispositivo può essere più rapido, può essere impreciso. Usare il GetLocationAsync metodo per eseguire una query sul dispositivo per la posizione corrente. È possibile configurare l'accuratezza e il timeout della query. È consigliabile usare l'overload del metodo che usa i GeolocationRequest parametri e CancellationToken , poiché potrebbe essere necessario del tempo per ottenere la posizione del dispositivo.

Nota

Quando necessario, l'API georilevazione richiede all'utente le autorizzazioni.

L'esempio di codice seguente illustra come richiedere la posizione del dispositivo, supportando l'annullamento:

private CancellationTokenSource _cancelTokenSource;
private bool _isCheckingLocation;

public async Task GetCurrentLocation()
{
    try
    {
        _isCheckingLocation = true;

        GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));

        _cancelTokenSource = new CancellationTokenSource();

        Location location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);

        if (location != null)
            Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
    }
    // Catch one of the following exceptions:
    //   FeatureNotSupportedException
    //   FeatureNotEnabledException
    //   PermissionException
    catch (Exception ex)
    {
        // Unable to get location
    }
    finally
    {
        _isCheckingLocation = false;
    }
}

public void CancelRequest()
{
    if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false)
        _cancelTokenSource.Cancel();
}

Non tutti i valori di posizione possono essere disponibili, a seconda del dispositivo. Ad esempio, la Altitude proprietà potrebbe essere null, avere un valore pari a 0 o avere un valore positivo che indica i metri sopra il livello del mare. Altri valori che potrebbero non essere presenti includono Speed e Course.

Avviso

GetLocationAsync può restituire null in alcuni scenari. Ciò indica che la piattaforma sottostante non è in grado di ottenere la posizione corrente.

Ascolto delle modifiche alla posizione

Oltre a eseguire query sul dispositivo per la posizione corrente, è possibile ascoltare le modifiche alla posizione mentre un'app è in primo piano.

Per verificare se l'app è attualmente in ascolto delle modifiche alla posizione, è disponibile una IsListeningForeground proprietà su cui è possibile eseguire una query. Quando si è pronti per iniziare ad ascoltare le modifiche alla posizione, è necessario chiamare il StartListeningForegroundAsync metodo . Questo metodo inizia ad ascoltare gli aggiornamenti della posizione e genera l'evento LocationChanged quando cambia la posizione, purché l'app sia in primo piano. L'oggetto GeolocationLocationChangedEventArgs che accompagna questo evento ha una Location proprietà di tipo Location, che rappresenta la nuova posizione rilevata.

Nota

Quando necessario, l'API georilevazione richiede all'utente le autorizzazioni.

Nell'esempio di codice seguente viene illustrato come restare in ascolto di una modifica della posizione e come elaborare la posizione modificata:

async void OnStartListening()
{
    try
    {
        Geolocation.LocationChanged += Geolocation_LocationChanged;
        var request = new GeolocationListeningRequest((GeolocationAccuracy)Accuracy);
        var success = await Geolocation.StartListeningForegroundAsync(request);

        string status = success
            ? "Started listening for foreground location updates"
            : "Couldn't start listening";
    }
    catch (Exception ex)
    {
        // Unable to start listening for location changes
    }
}

void Geolocation_LocationChanged(object sender, GeolocationLocationChangedEventArgs e)
{
    // Process e.Location to get the new location
}

La gestione degli errori può essere implementata registrando un gestore eventi per l'evento ListeningFailed . L'oggetto che accompagna questo evento ha una Error proprietà di tipo GeolocationError, che indica il motivo per cui l'ascolto GeolocationListeningFailedEventArgs non è riuscito. Quando viene generato l'evento, l'ascolto ListeningFailed di ulteriori modifiche di posizione si arresta e non vengono generati altri LocationChanged eventi.

Per interrompere l'ascolto delle modifiche alla posizione, chiamare il StopListeningForeground metodo :

void OnStopListening()
{
    try
    {
        Geolocation.LocationChanged -= Geolocation_LocationChanged;
        Geolocation.StopListeningForeground();
        string status = "Stopped listening for foreground location updates";
    }
    catch (Exception ex)
    {
        // Unable to stop listening for location changes
    }
}

Nota

Il StopListeningForeground metodo non ha alcun effetto quando l'app non è in ascolto delle modifiche alla posizione.

Accuratezza

Le sezioni seguenti descrivono la distanza di accuratezza della posizione, per piattaforma:

Importante

iOS presenta alcune limitazioni relative all'accuratezza. Per altre informazioni, vedere la sezione Differenze della piattaforma.

Più basso

Piattaforma Distanza (in metri)
Android 500
iOS 3000
Finestre 1000 - 5000

Bassa

Piattaforma Distanza (in metri)
Android 500
iOS 1000
Finestre 300 - 3000

Media (impostazione predefinita)

Piattaforma Distanza (in metri)
Android 100 - 500
iOS 100
Finestre 30 - 500

Alto

Piattaforma Distanza (in metri)
Android 0 - 100
iOS 10
Finestre <= 10

Migliore

Piattaforma Distanza (in metri)
Android 0 - 100
iOS ~0
Finestre <= 10

Rilevamento di posizioni fittizie

Alcuni dispositivi possono restituire una località fittizia proposta dal provider o da un'applicazione che fornisce località fittizie. È possibile rilevare questo problema usando in IsFromMockProvider qualsiasi Locationoggetto :

public async Task CheckMock()
{
    GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium);
    Location location = await Geolocation.Default.GetLocationAsync(request);

    if (location != null && location.IsFromMockProvider)
    {
        // location is from a mock provider
    }
}

Distanza tra due posizioni

Il CalculateDistance metodo calcola la distanza tra due posizioni geografiche. Questa distanza calcolata non prende in considerazione strade o altri percorsi, ed è semplicemente la distanza più breve tra i due punti lungo la superficie della Terra. Questo calcolo è noto come calcolo della distanza grande cerchio.

Il codice seguente calcola la distanza tra la Stati Uniti delle città americane di Boston e San Francisco:

Location boston = new Location(42.358056, -71.063611);
Location sanFrancisco = new Location(37.783333, -122.416667);

double miles = Location.CalculateDistance(boston, sanFrancisco, DistanceUnits.Miles);

Il Location(Double, Double, Double) costruttore accetta rispettivamente gli argomenti di latitudine e longitudine. I valori di latitudine positiva sono a nord dell'equatore e i valori di longitudine positiva sono a est del Meridiano di Greenwich. Usare l'argomento finale per CalculateDistance per specificare miglia o chilometri. La classe UnitConverters definisce anche i metodi KilometersToMiles e MilesToKilometers per eseguire la conversione da un'unità di misura all'altra.

Differenze tra le piattaforme

Questa sezione descrive le differenze specifiche della piattaforma con l'API di georilevazione.

L'altitudine viene calcolata in modo diverso in ogni piattaforma.

In Android, l'altitudine, se disponibile, viene restituita in metri sopra l'ellissoide di riferimento WGS 84. Se questa posizione non ha un'altitudine, 0.0 viene restituita.

La Location.ReducedAccuracy proprietà viene usata solo da iOS e restituisce false in tutte le altre piattaforme.