Freigeben über


Exemplarische Vorgehensweise – Hintergrundspeicherort in Xamarin.iOS

In diesem Beispiel erstellen wir eine iOS-Standortanwendung, die Informationen zu unserem aktuellen Standort druckt: Breitengrad, Längengrad und andere Parameter auf dem Bildschirm. Diese Anwendung veranschaulicht, wie Positionsaktualisierungen ordnungsgemäß ausgeführt werden, während die Anwendung entweder aktiv oder hintergrundiert ist.

In dieser exemplarischen Vorgehensweise werden einige wichtige Hintergrundkonzepte erläutert, z. B. das Registrieren einer App als Hintergrundanwendung, das Anhalten von UI-Updates beim Hintergrund und das Arbeiten mit den WillEnterBackground Methoden WillEnterForegroundAppDelegate .

Anwendungssetup

  1. Erstellen Sie zunächst eine neue Einzelansichtsanwendung für iOS-Apps >> (C#). Rufen Sie den Standort auf, und stellen Sie sicher, dass sowohl iPad als auch i Telefon ausgewählt wurden.

  2. Eine Standortanwendung qualifiziert sich als Hintergrundanwendung in iOS. Registrieren Sie die Anwendung als Speicherortanwendung, indem Sie die Info.plist-Datei für das Projekt bearbeiten.

    Doppelklicken Sie unter Projektmappen-Explorer auf die Datei "Info.plist", um sie zu öffnen, und scrollen Sie zum Ende der Liste. Aktivieren Sie sowohl die Kontrollkästchen "Hintergrundmodi aktivieren" als auch die Kontrollkästchen "Positionsaktualisierungen" .

    In Visual Studio für Mac sieht es wie folgt aus:

    Aktivieren sie sowohl die Kontrollkästchen

    In Visual Studio muss Info.plist manuell aktualisiert werden, indem das folgende Schlüssel-Wert-Paar hinzugefügt wird:

    <key>UIBackgroundModes</key>
    <array>
      <string>location</string>
    </array>
    
  3. Nachdem die Anwendung registriert wurde, kann sie Standortdaten vom Gerät abrufen. In iOS wird die CLLocationManager Klasse für den Zugriff auf Standortinformationen verwendet und kann Ereignisse auslösen, die Standortupdates bereitstellen.

  4. Erstellen Sie im Code eine neue Klasse, die einen LocationManager zentralen Ort für verschiedene Bildschirme und Code zum Abonnieren von Positionsupdates bereitstellt. Erstellen Sie in der LocationManager Klasse eine Instanz des CLLocationManager aufgerufenen LocMgrElements:

    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; }
        }
    }
    

    Der obige Code legt eine Reihe von Eigenschaften und Berechtigungen für die CLLocationManager-Klasse fest:

    • PausesLocationUpdatesAutomatically – Dies ist ein boolescher Wert, der abhängig davon festgelegt werden kann, ob das System Positionsupdates anhalten darf. Auf einigen Geräten wird truestandardmäßig festgelegt, was dazu führen kann, dass das Gerät nach ca. 15 Minuten keine Aktualisierung der Hintergrundspeicherorte mehr erhält.
    • RequestAlwaysAuthorization – Sie sollten diese Methode übergeben, um dem App-Benutzer die Möglichkeit zu geben, den Zugriff auf den Speicherort im Hintergrund zu ermöglichen. RequestWhenInUseAuthorization kann auch übergeben werden, wenn Sie dem Benutzer die Möglichkeit geben möchten, den Zugriff auf den Standort nur zuzulassen, wenn sich die App im Vordergrund befindet.
    • AllowsBackgroundLocationUpdates – Dies ist eine boolesche Eigenschaft, die in iOS 9 eingeführt wurde und so festgelegt werden kann, dass eine App Positionsupdates empfangen kann, wenn sie angehalten wird.

    Wichtig

    iOS 8 (und höher) erfordert auch einen Eintrag in der Datei Info.plist , um den Benutzer als Teil der Autorisierungsanforderung anzuzeigen.

  5. Fügen Sie Info.plist-Schlüssel für die Berechtigungstypen hinzu, NSLocationWhenInUseUsageDescriptiondie die App erfordert – NSLocationAlwaysUsageDescription, und/oder NSLocationAlwaysAndWhenInUseUsageDescription – mit einer Zeichenfolge, die dem Benutzer in der Warnung angezeigt wird, die den Zugriff auf Standortdaten anfordert.

  6. iOS 9 erfordert, dass bei Verwendung AllowsBackgroundLocationUpdates der Info.plist den Schlüssel UIBackgroundModes mit dem Wert locationenthält. Wenn Sie Schritt 2 dieser exemplarischen Vorgehensweise abgeschlossen haben, sollte dies bereits in Der Datei "Info.plist" enthalten sein.

  7. Erstellen Sie innerhalb der LocationManager Klasse eine Methode, die mit dem folgenden Code aufgerufen wird StartLocationUpdates . Dieser Code zeigt, wie Sie mit dem Empfangen von Positionsupdates aus dem 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 dieser Methode gibt es mehrere wichtige Dinge. Zunächst führen wir eine Überprüfung durch, um festzustellen, ob die Anwendung Zugriff auf Standortdaten auf dem Gerät hat. Wir überprüfen dies durch Aufrufen LocationServicesEnabled der CLLocationManager. Diese Methode gibt "false" zurück, wenn der Benutzer die Anwendung den Zugriff auf Standortinformationen verweigert hat.

  8. Informieren Sie als Nächstes den Standort-Manager, wie oft aktualisiert werden soll. CLLocationManager bietet viele Optionen zum Filtern und Konfigurieren von Standortdaten, einschließlich der Häufigkeit von Updates. Legen Sie in diesem Beispiel die DesiredAccuracy Aktualisierung fest, wenn sich die Position um einen Meter ändert. Weitere Informationen zum Konfigurieren der Standortaktualisierungshäufigkeit und anderer Einstellungen finden Sie in der Apple-Dokumentation in der CLLocationManager-Klassenreferenz .

  9. Rufen Sie schließlich die CLLocationManager Instanz aufStartUpdatingLocation. Dadurch wird der Standortmanager aufgefordert, einen anfänglichen Fix für den aktuellen Speicherort zu erhalten und mit dem Senden von Updates zu beginnen.

Bisher wurde der Standort-Manager erstellt, mit den Arten von Daten konfiguriert, die wir empfangen möchten, und hat den ursprünglichen Standort bestimmt. Jetzt muss der Code die Standortdaten auf der Benutzeroberfläche rendern. Wir können dies mit einem benutzerdefinierten Ereignis tun, das ein CLLocation Argument akzeptiert:

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

Der nächste Schritt besteht darin, Standortaktualisierungen von dem CLLocationManagerEreignis zu abonnieren und das benutzerdefinierte LocationUpdated Ereignis auszuheben, wenn neue Standortdaten verfügbar werden, wobei der Speicherort als Argument übergeben wird. Erstellen Sie dazu eine neue Klasse LocationUpdateEventArgs.cs. Auf diesen Code kann innerhalb der Standard-Anwendung zugegriffen werden und gibt den Gerätespeicherort zurück, wenn das Ereignis ausgelöst wird:

public class LocationUpdatedEventArgs : EventArgs
{
    CLLocation location;

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

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

Benutzeroberfläche

  1. Verwenden Sie den Xcode-Schnittstellen-Generator, um den Bildschirm zu erstellen, auf dem Standortinformationen angezeigt werden. Doppelklicken Sie auf die Datei "Main.storyboard ", um zu beginnen.

    Ziehen Sie auf dem Storyboard mehrere Beschriftungen auf den Bildschirm, um als Platzhalter für die Positionsinformationen zu fungieren. In diesem Beispiel gibt es Bezeichnungen für Breitengrad, Längengrad, Höhe, Kurs und Geschwindigkeit.

    Weitere Informationen finden Sie unter Entwerfen von Benutzeroberflächen mit Xcode.

  2. Doppelklicken Sie auf dem Lösungspad auf die ViewController.cs Datei, und bearbeiten Sie sie, um eine neue Instanz des LocationManager zu erstellen und darauf aufzurufen StartLocationUpdates. Ändern Sie den Code so, dass er wie folgt aussieht:

    #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
    

    Dadurch werden die Positionsupdates beim Starten der Anwendung gestartet, obwohl keine Daten angezeigt werden.

  3. Nachdem die Positionsupdates empfangen wurden, aktualisieren Sie den Bildschirm mit den Standortinformationen. Die folgende Methode ruft den Ort aus unserem LocationUpdated Ereignis ab und zeigt ihn in der Benutzeroberfläche an:

    #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
    

Wir müssen das LocationUpdated Ereignis weiterhin in unserem AppDelegate abonnieren und die neue Methode aufrufen, um die Benutzeroberfläche zu aktualisieren. Fügen Sie den folgenden Code ViewDidLoad, direkt hinter dem StartLocationUpdates Aufruf hinzu:

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;

}

Wenn die Anwendung ausgeführt wird, sollte sie nun etwa wie folgt aussehen:

Beispiel für eine App-Ausführung

Behandeln von Aktiven und Hintergrundzuständen

  1. Die Anwendung gibt Positionsaktualisierungen aus, während sie sich im Vordergrund und aktiv befindet. Um zu veranschaulichen, was passiert, wenn die App in den Hintergrund wechselt, überschreiben Sie die AppDelegate Methoden, mit denen anwendungszustandsänderungen nachverfolgt werden, damit die Anwendung in die Konsole schreibt, wenn sie zwischen Vordergrund und Hintergrund wechselt:

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

    Fügen Sie den LocationManager folgenden Code zum fortlaufenden Drucken aktualisierter Positionsdaten zur Anwendungsausgabe hinzu, um sicherzustellen, dass die Standortinformationen weiterhin im Hintergrund verfügbar sind:

    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. Es gibt ein problem mit dem Code Standard: Wenn Sie versuchen, die Benutzeroberfläche zu aktualisieren, wenn die App hintergrund ist, wird sie von iOS beendet. Wenn die App in den Hintergrund wechselt, muss der Code das Abonnement von Positionsupdates kündigen und die Aktualisierung der Benutzeroberfläche beenden.

    iOS stellt uns Benachrichtigungen bereit, wenn die App zu einem anderen Anwendungsstatus wechselt. In diesem Fall können wir die ObserveDidEnterBackground Benachrichtigung abonnieren.

    Der folgende Codeausschnitt zeigt, wie Sie eine Benachrichtigung verwenden, um die Ansicht darüber zu informieren, wann Ui-Updates angehalten werden sollen. Dies wird in ViewDidLoad:

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

    Wenn die App ausgeführt wird, sieht die Ausgabe ungefähr wie folgt aus:

    Beispiel für die Positionsausgabe in der Konsole

  3. Die Anwendung druckt Positionsaktualisierungen auf dem Bildschirm, wenn sie im Vordergrund ausgeführt werden, und druckt weiterhin Daten in das Anwendungsausgabefenster, während sie im Hintergrund ausgeführt werden.

Nur ein noch ausstehendes Problem ist neu Standard: Der Bildschirm startet UI-Updates, wenn die App zum ersten Mal geladen wird, aber es hat keine Möglichkeit zu wissen, wann die App erneut in den Vordergrund eingegeben wurde. Wenn die hintergrundgeschaltete Anwendung wieder in den Vordergrund gebracht wird, werden UI-Updates nicht fortgesetzt.

Um dies zu beheben, schachteln Sie einen Aufruf, um UI-Updates in einer anderen Benachrichtigung zu starten, was ausgelöst wird, wenn die Anwendung in den aktiven Zustand wechselt:

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

Jetzt beginnt die Benutzeroberfläche, wenn die Anwendung zum ersten Mal gestartet wird, zu aktualisieren und die Aktualisierung fortzusetzen, wenn die App wieder im Vordergrund angezeigt wird.

In dieser exemplarischen Vorgehensweise haben wir eine gut verhaltene, hintergrundfähige iOS-Anwendung erstellt, die Standortdaten sowohl auf dem Bildschirm als auch im Anwendungsausgabefenster druckt.