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 WillEnterBackground
WillEnterForeground
AppDelegate
.
Nastavení aplikace
Nejprve vytvořte novou aplikaci pro jedno zobrazení aplikace > pro iOS > (C#). Zavolejte umístění a ujistěte se, že iPad i iPhone byly vybrány.
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:
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>
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í.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éhoCLLocationManager
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; } } }
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.
Přidejte klíče Info.plist pro typy oprávnění, které aplikace vyžaduje –
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
, a/neboNSLocationAlwaysAndWhenInUseUsageDescription
– s řetězcem, který se zobrazí uživateli v upozornění, který požaduje přístup k datům o poloze.iOS 9 vyžaduje, aby při použití
AllowsBackgroundLocationUpdates
souboru Info.plist obsahoval klíčUIBackgroundModes
s hodnotoulocation
. Pokud jste dokončili krok 2 tohoto názorného postupu, měl by už být v souboru Info.plist.LocationManager
Uvnitř třídy vytvořte metodu volanouStartLocationUpdates
s následujícím kódem. Tento kód ukazuje, jak začít přijímat aktualizace umístění zCLLocationManager
: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.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říkladuDesiredAccuracy
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.Nakonec zavolejte
StartUpdatingLocation
CLLocationManager
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 CLLocationManager
aplikace 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í
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.
Na panelu řešení poklikejte na
ViewController.cs
soubor a upravte ho, aby se vytvořila nová instance LocationManageru a volalaStartLocationUpdates
ji. 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.
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:
Zpracování stavů Aktivní a Pozadí
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); } }
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:
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.