Xamarin.Essentials:Geolocalizzazione

La classe Geolocation fornisce le API per recuperare le coordinate di georilevazione correnti del dispositivo.

Operazioni preliminari

Per iniziare a usare questa API, leggere la guida introduttiva per Xamarin.Essentials assicurarsi che la libreria sia installata e configurata correttamente nei progetti.

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

Le autorizzazioni Coarse e Fine Location sono obbligatorie 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:

Aprire il file AssemblyInfo.cs nella cartella Proprietà e aggiungere:

[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)]

Oppure aggiornare il manifesto di Android:

Aprire il file AndroidManifest.xml nella cartella Proprietà e aggiungere quanto segue all'interno del nodo manifest:

<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" />

Oppure fare clic con il pulsante destro del mouse sul progetto Android e aprire le proprietà del progetto. In Manifesto Android trovare l'area Autorizzazioni necessarie e selezionare le autorizzazioni ACCESS_COARSE_LOCATION e ACCESS_FINE_LOCATION. Il file AndroidManifest.xml verrà aggiornato automaticamente.

Se l'applicazione ha come destinazione Android 10 - Q (livello API 29 o versione successiva) e richiede LocationAlways, è necessario aggiungere anche l'autorizzazione seguente in AssemblyInfo.cs:

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

Oppure direttamente nel AndroidManifest.xml:

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

È consigliabile leggere la documentazione di Android sugli aggiornamenti della posizione in background perché sono necessarie molte restrizioni.

Questa API usa le autorizzazioni di runtime in Android. Assicurarsi che sia completamente inizializzata e che Xamarin.Essentials la gestione delle autorizzazioni sia configurata nell'app.

Nel progetto MainLauncher Android o in qualsiasi Activity elemento avviato Xamarin.Essentials deve essere inizializzato nel OnCreate metodo :

protected override void OnCreate(Bundle savedInstanceState) 
{
    //...
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
    //...
}    

Per gestire le autorizzazioni di runtime in Android, Xamarin.Essentials deve ricevere qualsiasi OnRequestPermissionsResult. Aggiungere il codice seguente a tutte le classi Activity:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Uso di Geolocation

Aggiungere un riferimento a Xamarin.Essentials nella classe :

using Xamarin.Essentials;

L'API per la georilevazione richiederà anche le autorizzazioni all'utente quando necessario.

È possibile ottenere l'ultima posizione conosciuta del dispositivo chiamando il metodo GetLastKnownLocationAsync. Questa procedura è spesso più veloce che eseguire una query completa, ma può essere meno accurata e potrebbe restituire null in assenza di un percorso memorizzato nella cache.

try
{
    var location = await Geolocation.GetLastKnownLocationAsync();

    if (location != null)
    {
        Console.WriteLine($"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
}

Per eseguire una query delle coordinate geografiche del dispositivo corrente, si può usare GetLocationAsync. È preferibile passare GeolocationRequest e CancellationToken completi perché l'acquisizione della posizione del dispositivo potrebbe richiedere tempo.

CancellationTokenSource cts;

async Task GetCurrentLocation()
{
    try
    {
        var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
        cts = new CancellationTokenSource();
        var location = await Geolocation.GetLocationAsync(request, cts.Token);

        if (location != null)
        {
            Console.WriteLine($"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
    }
}

protected override void OnDisappearing()
{
    if (cts != null && !cts.IsCancellationRequested)
        cts.Cancel();
    base.OnDisappearing();
}

Si noti che tutti i valori possono essere disponibili a causa del modo in cui ogni dispositivo esegue query sulla georilevazione tramite provider diversi. Ad esempio, la Altitude proprietà potrebbe essere null, avere un valore pari a 0 o avere un valore positivo, espresso in metri sopra il livello del mare. Altri valori che potrebbero non essere presenti includono Speed e Course.

Accuratezza della georilevazione

La tabella seguente indica l'accuratezza per ogni piattaforma:

Più basso

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

Basso

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

Media (impostazione predefinita)

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

Elevato

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

Migliore

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

Rilevamento di località fittizie

Alcuni dispositivi possono restituire una località fittizia proposta dal provider o da un'applicazione che fornisce località fittizie. È possibile rilevarle usando IsFromMockProvider su qualsiasi Location.

var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.GetLocationAsync(request);

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

Distanza tra due località

Le classi Location e LocationExtensions definiscono i metodi CalculateDistance che consentono di calcolare la distanza tra due località geografiche. Questa distanza calcolata non tiene in considerazione le strade o altri percorsi, ma è semplicemente la distanza più breve tra due punti sulla superficie terrestre, nota anche come ortodromia o, colloquialmente, distanza "a volo d'uccello".

Ecco un esempio:

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 costruttore Location ha gli argomenti di latitudine e longitudine in quest'ordine. 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

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, viene restituito 0,0.

API

Altri video di Xamarin sono disponibili su Channel 9 e YouTube.