Sdílet prostřednictvím


Návod – umístění na pozadí v Xamarin.iOS

V tomto příkladu vytvoříme aplikaci location pro iOS, která vytiskne informace o našem aktuálním umístění: zeměpisná šířka, zeměpisná délka a další parametry na obrazovku. Tato aplikace předvede, jak správně provádět aktualizace umístění, když je aplikace aktivní nebo na pozadí.

Tento názorný postup vysvětluje některé klíčové koncepty na pozadí, včetně registrace aplikace jako aplikace potřebné na pozadí, pozastavení aktualizací uživatelského rozhraní, když je aplikace na pozadí, a práce s metodami WillEnterBackgroundWillEnterForegroundAppDelegate .

Nastavení aplikace

  1. Nejprve vytvořte novou aplikaci pro jedno zobrazení aplikace > pro iOS > (C#). Volat umístění a ujistit se, že iPad i i Telefon byly vybrány.

  2. Aplikace umístění se v iOSu kvalifikuje jako aplikace potřebná na pozadí. Zaregistrujte aplikaci jako aplikaci umístění úpravou souboru Info.plist projektu.

    V části Průzkumník řešení poklikejte na soubor Info.plist a otevřete ho a posuňte se do dolní části seznamu. Zaškrtněte políčko Povolit režimy pozadí i Aktualizace umístění.

    V Visual Studio pro Mac bude vypadat přibližně takto:

    Zaškrtněte políčko Povolit režimy pozadí i Aktualizace umístění.

    V sadě Visual Studio je potřeba soubor Info.plist aktualizovat ručně přidáním následujícího páru klíč/hodnota:

    <key>UIBackgroundModes</key>
    <array>
      <string>location</string>
    </array>
    
  3. Teď, když je aplikace zaregistrovaná, může získat data o poloze ze zařízení. V iOSu se CLLocationManager třída používá pro přístup k informacím o poloze a může vyvolat události, které poskytují aktualizace umístění.

  4. V kódu vytvořte novou třídu s názvem LocationManager , která poskytuje jedno místo pro různé obrazovky a kód pro přihlášení k odběru aktualizací umístění. LocationManager Ve třídě vytvořte instanci volaného CLLocationManagerLocMgr:

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

    Výše uvedený kód nastaví řadu vlastností a oprávnění pro třídu CLLocationManager :

    • PausesLocationUpdatesAutomatically – Jedná se o logickou hodnotu, kterou lze nastavit v závislosti na tom, jestli má systém povoleno pozastavit aktualizace polohy. Na některém zařízení se ve výchozím nastavení nastaví true, což může způsobit, že zařízení přestane dostávat aktualizace umístění na pozadí po přibližně 15 minutách.
    • RequestAlwaysAuthorization – Tuto metodu byste měli předat, aby uživatel aplikace povolil přístup k umístění na pozadí. RequestWhenInUseAuthorization můžete také předat, pokud chcete uživateli dát možnost povolit přístup k umístění pouze v případě, že je aplikace v popředí.
    • AllowsBackgroundLocationUpdates – Jedná se o logickou vlastnost zavedenou v iOSu 9, která umožňuje aplikaci přijímat aktualizace polohy při pozastavení.

    Důležité

    IOS 8 (a vyšší) také vyžaduje zadání v souboru Info.plist , aby se uživatel zobrazil jako součást žádosti o autorizaci.

  5. Přidejte klíče Info.plist pro typy oprávnění, které aplikace vyžaduje – NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription, a/nebo NSLocationAlwaysAndWhenInUseUsageDescription – s řetězcem, který se zobrazí uživateli v upozornění, který požaduje přístup k datům o poloze.

  6. iOS 9 vyžaduje, aby při použití AllowsBackgroundLocationUpdatessouboru Info.plist obsahoval klíč UIBackgroundModes s hodnotou location. Pokud jste dokončili krok 2 tohoto názorného postupu, měl by už být v souboru Info.plist.

  7. LocationManager Uvnitř třídy vytvořte metodu volanou StartLocationUpdates s následujícím kódem. Tento kód ukazuje, jak začít přijímat aktualizace umístění z 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();
    }
    

    V této metodě probíhá několik důležitých věcí. Nejprve provedeme kontrolu, abychom zjistili, jestli má aplikace přístup k datům o poloze v zařízení. Ověřujeme to voláním LocationServicesEnabled .CLLocationManager Tato metoda vrátí hodnotu false , pokud uživatel odepře přístup k informacím o poloze aplikace.

  8. Dále řekněte správci umístění, jak často se má aktualizovat. CLLocationManager poskytuje řadu možností filtrování a konfigurace dat o poloze, včetně četnosti aktualizací. V tomto příkladu DesiredAccuracy nastavte aktualizaci pokaždé, když se umístění změní podle měřiče. Další informace o konfiguraci frekvence aktualizace umístění a dalších předvoleb najdete v referenční dokumentaci ke třídě CLLocationManager v dokumentaci Společnosti Apple.

  9. Nakonec zavolejte StartUpdatingLocationCLLocationManager instanci. To správci umístění řekne, že má získat počáteční opravu aktuálního umístění a začít odesílat aktualizace.

Zatím se vytvořil správce umístění, nakonfiguroval typy dat, která chceme přijmout, a určil počáteční umístění. Kód teď musí vykreslit data o poloze do uživatelského rozhraní. Můžeme to udělat s vlastní událostí, která přebírá CLLocation jako argument:

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

Dalším krokem je přihlášení k odběru aktualizací umístění z CLLocationManageraplikace a vyvolání vlastní LocationUpdated události, jakmile budou k dispozici nová data o poloze a předají ho jako argument. Uděláte to tak, že vytvoříte novou třídu LocationUpdateEventArgs.cs. Tento kód je přístupný v rámci hlavní aplikace a při vyvolání události vrátí umístění zařízení:

public class LocationUpdatedEventArgs : EventArgs
{
    CLLocation location;

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

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

Uživatelské rozhraní

  1. Pomocí Tvůrce rozhraní Xcode sestavte obrazovku, která zobrazí informace o poloze. Začněte poklikáním na soubor Main.storyboard .

    Na scénáři přetáhněte několik popisků na obrazovku, aby fungovalo jako zástupné symboly informací o poloze. V tomto příkladu jsou popisky pro zeměpisnou šířku, zeměpisnou délku, výšku, kurz a rychlost.

    Další informace naleznete v tématu Navrhování uživatelských rozhraní pomocí Xcode.

  2. Na panelu řešení poklikejte na ViewController.cs soubor a upravte ho, aby se vytvořila nová instance LocationManageru a volala StartLocationUpdatesji. Změňte kód tak, aby vypadal takto:

    #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
    

    Tím se spustí aktualizace umístění při spuštění aplikace, i když se nezobrazí žádná data.

  3. Po přijetí aktualizací umístění aktualizujte obrazovku informacemi o poloze. Následující metoda získá umístění z naší LocationUpdated události a zobrazí ji v uživatelském rozhraní:

    #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
    

Stále se musíme přihlásit k odběru LocationUpdated události v naší appDelegate a volat novou metodu pro aktualizaci uživatelského rozhraní. Přidejte následující kód ViewDidLoad, hned za StartLocationUpdates volání:

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;

}

Když teď aplikaci spustíte, měla by vypadat přibližně takto:

Příklad spuštění aplikace

Zpracování stavů Aktivní a Pozadí

  1. Aplikace vypíše aktualizace umístění v době, kdy je v popředí a je aktivní. Abychom si ukázali, co se stane, když aplikace přejde na pozadí, přepište AppDelegate metody, které sledují změny stavu aplikace, aby aplikace při přechodu mezi popředím a pozadím zapisuje do konzoly:

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

    Do výstupu LocationManager aplikace přidejte následující kód pro průběžný tisk aktualizovaných dat o poloze, abyste ověřili, že informace o poloze jsou stále dostupné na pozadí:

    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. Došlo k jednomu zbývajícímu problému s kódem: pokus o aktualizaci uživatelského rozhraní, když je aplikace na pozadí, způsobí, že se iOS ukončí. Když aplikace přejde na pozadí, kód se musí odhlásit z aktualizací umístění a ukončit aktualizaci uživatelského rozhraní.

    IOS nám poskytuje oznámení, když se aplikace chystá přejít na jiný stav aplikace. V tomto případě se můžeme přihlásit k odběru ObserveDidEnterBackground oznámení.

    Následující fragment kódu ukazuje, jak pomocí oznámení oznámit zobrazení, kdy zastavit aktualizace uživatelského rozhraní. To bude pokračovat:ViewDidLoad

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

    Když je aplikace spuštěná, výstup bude vypadat přibližně takto:

    Příklad výstupu umístění v konzole

  3. Aplikace při provozu v popředí vytiskne aktualizace polohy na obrazovku a při provozu na pozadí bude nadále tisknout data do okna výstupu aplikace.

Zbývá jen jeden nevyřešený problém: Obrazovka spustí aktualizace uživatelského rozhraní při prvním načtení aplikace, ale nemá žádný způsob, jak zjistit, kdy se aplikace znovu dostala do popředí. Pokud se aplikace na pozadí vrátí do popředí, aktualizace uživatelského rozhraní se neobnoví.

Tento problém vyřešíte tak, že vnoříte volání pro spuštění aktualizací uživatelského rozhraní do jiného oznámení, které se aktivuje, když aplikace přejde do aktivního stavu:

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

Uživatelské rozhraní se teď začne aktualizovat při prvním spuštění aplikace a obnoví aktualizaci, kdykoli se aplikace vrátí do popředí.

V tomto názorném postupu jsme vytvořili dobře chovanou aplikaci pro iOS s podporou pozadí, která vytiskne data o poloze na obrazovku i v okně výstupu aplikace.