Condividi tramite


Procedura dettagliata - Percorso in background in Xamarin.iOS

In questo esempio si creerà un'applicazione location iOS che stampa informazioni sulla posizione corrente: latitudine, longitudine e altri parametri sullo schermo. Questa applicazione dimostrerà come eseguire correttamente gli aggiornamenti della posizione mentre l'applicazione è attiva o in background.

Questa procedura dettagliata illustra alcuni concetti di base chiave, tra cui la registrazione di un'app come applicazione in background, la sospensione degli aggiornamenti dell'interfaccia utente quando l'app è in background e l'uso dei WillEnterBackground metodi e WillEnterForegroundAppDelegate .

Configurazione dell'applicazione

  1. Creare prima di tutto una nuova applicazione di visualizzazione singola per app iOS >> (C#). Chiama location e assicurati che sia iPad che i Telefono siano stati selezionati.

  2. Un'applicazione location si qualifica come applicazione in background in iOS. Registrare l'applicazione come applicazione Location modificando il file Info.plist per il progetto.

    In Esplora soluzioni fare doppio clic sul file Info.plist per aprirlo e scorrere fino alla fine dell'elenco. Selezionare entrambe le caselle di controllo Abilita modalità in background e Posizione Aggiornamenti.

    In Visual Studio per Mac avrà un aspetto simile al seguente:

    Selezionare entrambe le caselle di controllo Abilita modalità in background e Posizione Aggiornamenti

    In Visual Studio, Info.plist deve essere aggiornato manualmente aggiungendo la coppia chiave/valore seguente:

    <key>UIBackgroundModes</key>
    <array>
      <string>location</string>
    </array>
    
  3. Ora che l'applicazione è registrata, può ottenere i dati sulla posizione dal dispositivo. In iOS, la CLLocationManager classe viene usata per accedere alle informazioni sulla posizione e può generare eventi che forniscono aggiornamenti della posizione.

  4. Nel codice creare una nuova classe denominata LocationManager che fornisce un'unica posizione per varie schermate e codice per sottoscrivere gli aggiornamenti della posizione. LocationManager Nella classe creare un'istanza di CLLocationManager denominata LocMgr:

    public class LocationManager
    {
        protected CLLocationManager locMgr;
    
        public LocationManager () {
            this.locMgr = new CLLocationManager();
            this.locMgr.PausesLocationUpdatesAutomatically = false;
    
            // iOS 8 has additional permissions requirements
            if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                locMgr.RequestAlwaysAuthorization (); // works in background
                //locMgr.RequestWhenInUseAuthorization (); // only in foreground
            }
    
            if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) {
                locMgr.AllowsBackgroundLocationUpdates = true;
            }
        }
    
        public CLLocationManager LocMgr {
            get { return this.locMgr; }
        }
    }
    

    Il codice precedente imposta una serie di proprietà e autorizzazioni per la classe CLLocationManager :

    • PausesLocationUpdatesAutomatically : valore booleano che può essere impostato a seconda che il sistema possa sospendere gli aggiornamenti della posizione. In un dispositivo per impostazione predefinita è true, che può causare l'arresto dell'aggiornamento della posizione in background del dispositivo dopo circa 15 minuti.
    • RequestAlwaysAuthorization - Devi passare questo metodo per consentire all'utente dell'app di consentire l'accesso alla posizione in background. RequestWhenInUseAuthorization può essere passato anche se vuoi dare all'utente la possibilità di consentire l'accesso alla posizione solo quando l'app è in primo piano.
    • AllowsBackgroundLocationUpdates : si tratta di una proprietà booleana, introdotta in iOS 9 che può essere impostata per consentire a un'app di ricevere gli aggiornamenti della posizione quando viene sospesa.

    Importante

    Anche iOS 8 (e versioni successive) richiede una voce nel file Info.plist per mostrare l'utente come parte della richiesta di autorizzazione.

  5. Aggiungere chiavi Info.plist per i tipi di autorizzazione richiesti dall'app, NSLocationAlwaysUsageDescription, NSLocationWhenInUseUsageDescriptione/o NSLocationAlwaysAndWhenInUseUsageDescription , con una stringa che verrà visualizzata all'utente nell'avviso che richiede l'accesso ai dati sulla posizione.

  6. iOS 9 richiede che quando si usa AllowsBackgroundLocationUpdates Info.plist includa la chiave UIBackgroundModes con il valore location. Se hai completato il passaggio 2 di questa procedura dettagliata, questo dovrebbe essere già presente nel file Info.plist.

  7. All'interno della LocationManager classe creare un metodo denominato StartLocationUpdates con il codice seguente. Questo codice illustra come iniziare a ricevere gli aggiornamenti della posizione da CLLocationManager:

    if (CLLocationManager.LocationServicesEnabled) {
        //set the desired accuracy, in meters
        LocMgr.DesiredAccuracy = 1;
        LocMgr.LocationsUpdated += (object sender, CLLocationsUpdatedEventArgs e) =>
        {
            // fire our custom Location Updated event
            LocationUpdated (this, new LocationUpdatedEventArgs (e.Locations [e.Locations.Length - 1]));
        };
        LocMgr.StartUpdatingLocation();
    }
    

    In questo metodo sono presenti diversi aspetti importanti. Prima di tutto, viene eseguito un controllo per verificare se l'applicazione ha accesso ai dati sulla posizione nel dispositivo. Per verificare questa situazione, chiamare LocationServicesEnabled su CLLocationManager. Questo metodo restituirà false se l'utente ha negato l'accesso dell'applicazione alle informazioni sulla posizione.

  8. In seguito, indicare al gestore della posizione la frequenza con cui eseguire l'aggiornamento. CLLocationManager offre molte opzioni per filtrare e configurare i dati sulla posizione, inclusa la frequenza degli aggiornamenti. In questo esempio impostare l'oggetto DesiredAccuracy da aggiornare ogni volta che la posizione cambia di un contatore. Per altre informazioni sulla configurazione della frequenza di aggiornamento della posizione e altre preferenze, vedere le informazioni di riferimento sulla classe CLLocationManager nella documentazione di Apple.

  9. Infine, chiamare StartUpdatingLocation sull'istanza CLLocationManager di . Questo indica al gestore della posizione di ottenere una correzione iniziale nel percorso corrente e di iniziare a inviare gli aggiornamenti

Finora, il gestore della posizione è stato creato, configurato con i tipi di dati che si desidera ricevere e ha determinato la posizione iniziale. A questo punto, il codice deve eseguire il rendering dei dati della posizione nell'interfaccia utente. È possibile eseguire questa operazione con un evento personalizzato che accetta come CLLocation argomento:

// event for the location changing
public event EventHandler<LocationUpdatedEventArgs>LocationUpdated = delegate { };

Il passaggio successivo consiste nel sottoscrivere gli aggiornamenti della posizione da CLLocationManagere generare l'evento personalizzato LocationUpdated quando i nuovi dati di posizione diventano disponibili, passando il percorso come argomento. A tale scopo, creare una nuova classe LocationUpdateEventArgs.cs. Questo codice è accessibile all'interno dell'applicazione principale e restituisce la posizione del dispositivo quando viene generato l'evento:

public class LocationUpdatedEventArgs : EventArgs
{
    CLLocation location;

    public LocationUpdatedEventArgs(CLLocation location)
    {
       this.location = location;
    }

    public CLLocation Location
    {
       get { return location; }
    }
}

Interfaccia utente

  1. Usare Xcode Interface Builder per compilare la schermata che visualizzerà le informazioni sulla posizione. Fare doppio clic sul file Main.storyboard per iniziare.

    Nello storyboard trascinare diverse etichette sullo schermo per fungere da segnaposto per le informazioni sulla posizione. In questo esempio sono disponibili etichette per latitudine, longitudine, altitudine, corso e velocità.

    Per altre informazioni, vedere Progettazione di interfacce utente con Xcode.

  2. Nel riquadro della soluzione fare doppio clic sul ViewController.cs file e modificarlo per creare una nuova istanza di LocationManager e chiamarla StartLocationUpdates. Modificare il codice in modo che sia simile al seguente:

    #region Computed Properties
    public static bool UserInterfaceIdiomIsPhone {
        get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
    }
    
    public static LocationManager Manager { get; set;}
    #endregion
    
    #region Constructors
    public ViewController (IntPtr handle) : base (handle)
    {
    // As soon as the app is done launching, begin generating location updates in the location manager
        Manager = new LocationManager();
        Manager.StartLocationUpdates();
    }
    
    #endregion
    

    Verrà avviato l'aggiornamento del percorso all'avvio dell'applicazione, anche se non verranno visualizzati dati.

  3. Ora che gli aggiornamenti della posizione vengono ricevuti, aggiornare la schermata con le informazioni sulla posizione. Il metodo seguente ottiene la posizione dall'evento LocationUpdated e lo mostra nell'interfaccia utente:

    #region Public Methods
    public void HandleLocationChanged (object sender, LocationUpdatedEventArgs e)
    {
        // Handle foreground updates
        CLLocation location = e.Location;
    
        LblAltitude.Text = location.Altitude + " meters";
        LblLongitude.Text = location.Coordinate.Longitude.ToString ();
        LblLatitude.Text = location.Coordinate.Latitude.ToString ();
        LblCourse.Text = location.Course.ToString ();
        LblSpeed.Text = location.Speed.ToString ();
    
        Console.WriteLine ("foreground updated");
    }
    #endregion
    

È comunque necessario sottoscrivere l'evento LocationUpdated in AppDelegate e chiamare il nuovo metodo per aggiornare l'interfaccia utente. Aggiungere il codice seguente subito ViewDidLoad, dopo la StartLocationUpdates chiamata:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // It is better to handle this with notifications, so that the UI updates
    // resume when the application re-enters the foreground!
    Manager.LocationUpdated += HandleLocationChanged;

}

A questo punto, quando l'applicazione viene eseguita, dovrebbe essere simile alla seguente:

Esecuzione di un'app di esempio

Gestione degli stati attivi e in background

  1. L'applicazione restituisce gli aggiornamenti del percorso mentre è in primo piano e attivo. Per illustrare cosa accade quando l'app entra in background, eseguire l'override dei metodi che tengono traccia delle AppDelegate modifiche dello stato dell'applicazione in modo che l'applicazione scriva nella console quando passa tra il primo piano e lo sfondo:

    public override void DidEnterBackground (UIApplication application)
    {
        Console.WriteLine ("App entering background state.");
    }
    
    public override void WillEnterForeground (UIApplication application)
    {
        Console.WriteLine ("App will enter foreground");
    }
    

    Aggiungere il codice seguente in LocationManager per stampare continuamente i dati di posizione aggiornati nell'output dell'applicazione per verificare che le informazioni sulla posizione siano ancora disponibili in background:

    public class LocationManager
    {
        public LocationManager ()
        {
        ...
        LocationUpdated += PrintLocation;
        }
        ...
    
        //This will keep going in the background and the foreground
        public void PrintLocation (object sender, LocationUpdatedEventArgs e) {
        CLLocation location = e.Location;
        Console.WriteLine ("Altitude: " + location.Altitude + " meters");
        Console.WriteLine ("Longitude: " + location.Coordinate.Longitude);
        Console.WriteLine ("Latitude: " + location.Coordinate.Latitude);
        Console.WriteLine ("Course: " + location.Course);
        Console.WriteLine ("Speed: " + location.Speed);
        }
    }
    
  2. C'è un problema rimanente con il codice: il tentativo di aggiornare l'interfaccia utente quando l'app è in background causerà l'interruzione di iOS. Quando l'app entra in background, il codice deve annullare la sottoscrizione agli aggiornamenti della posizione e interrompere l'aggiornamento dell'interfaccia utente.

    iOS fornisce notifiche quando l'app sta per passare a un diverso stato dell'applicazione. In questo caso, è possibile sottoscrivere la ObserveDidEnterBackground notifica.

    Il frammento di codice seguente mostra come usare una notifica per informare la visualizzazione quando interrompere gli aggiornamenti dell'interfaccia utente. Questa operazione verrà visualizzata in ViewDidLoad:

    UIApplication.Notifications.ObserveDidEnterBackground ((sender, args) => {
        Manager.LocationUpdated -= HandleLocationChanged;
    });
    

    Quando l'app è in esecuzione, l'output sarà simile al seguente:

    Esempio di output del percorso nella console

  3. L'applicazione stampa gli aggiornamenti della posizione sullo schermo quando si opera in primo piano e continua a stampare i dati nella finestra di output dell'applicazione mentre opera in background.

Rimane un solo problema in sospeso: la schermata avvia gli aggiornamenti dell'interfaccia utente al primo caricamento dell'app, ma non ha modo di sapere quando l'app è nuovamente in primo piano. Se l'applicazione in background viene ripristinata in primo piano, gli aggiornamenti dell'interfaccia utente non riprenderanno.

Per risolvere questo problema, annidare una chiamata per avviare gli aggiornamenti dell'interfaccia utente all'interno di un'altra notifica, che verrà attivata quando l'applicazione entra nello stato Attivo:

UIApplication.Notifications.ObserveDidBecomeActive ((sender, args) => {
  Manager.LocationUpdated += HandleLocationChanged;
});

Ora l'interfaccia utente inizierà ad aggiornare al primo avvio dell'applicazione e riprenderà l'aggiornamento in qualsiasi momento in cui l'app torna in primo piano.

In questa procedura dettagliata è stata creata un'applicazione iOS con riconoscimento dello sfondo ben comportamento che stampa i dati sulla posizione sia sullo schermo che sulla finestra di output dell'applicazione.