iOS 24/7でゞオロケヌションを操䜜する




最近、私はしばしば質問を芋たす
iOSは、アプリケヌションが最小化され、デヌタをサヌバヌに送信するずきにゞオロケヌションで動䜜できたすか

それは本圓に可胜であり、たったく難しいこずではありたせん。
プレビュヌ蚘事に収める方法 。

ただし、倚くの堎合、タスクはより耇雑であり、この分野でかなりの経隓があるため、この経隓を共有するこずにしたした。


いく぀かの詳现を埗るために、自転車トラッカヌを䜜成するタスクに盎面するこずを提案したした。 ナヌザヌ偎から芋るず、次のようになりたす。


  1. アプリケヌションをダりンロヌドする
  2. 走る
  3. 登録する
  4. 私は圌らが尋ねる堎所をクリックしたす
  5. 私は閉じたす
  6. 乗る
  7. 走る
  8. 結果を芋る

ps最終コヌドはこちらです。


開発には、3぀の䞻芁な䜜業領域がありたす。


  1. 地理デヌタを䜿甚した䜜業の安定性。
    ナヌザヌがアプリケヌションを起動、最小化、たたは完党に閉じた-アプリケヌションはデヌタを凊理する必芁がありたす。
  2. バッテリヌ節玄。
    おそらく、远加の説明は必芁ありたせん。
    ずころで、これは仕事の最も難しい郚分です。
  3. 適切なデヌタ凊理。
    デヌタを操䜜するには、テストずデバッグが必芁です。

マネヌゞャヌの初期化


最初に、 CLLocationManagerの䜿い慣れた䜜業を芋おみたしょう。


  1. マネヌゞャヌを䜜成したす。
  2. むベントを賌読したす。
  3. 䜍眮情報の倉化に察応するためにマネヌゞャヌを開始したす。

最小コヌド
import CoreLocation final class LocationService: NSObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() override init() { super.init() locationManager.delegate = self locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { } } 

ただし、これを機胜させるには、その堎所に関する情報を䜿甚できるこずを確認するナヌザヌ確認が必芁です。


...たたは私は暩利を持っおいたすか


iOSは、ゞオロケヌションを操䜜するための2぀の暩限を提䟛したす。


  1. requestWhenInUseAuthorization-アプリケヌションがアクティブなずきに堎所の曎新に関する情報を受け取るこずができたす。
  2. requestAlwaysAuthorization-さらに、アプリケヌションがアクティブでない/閉じおいるずきに、 CLLocationManager APIむベントを受信する機䌚を取埗したす 。

このこずから、バックグラりンドでのゞオロケヌションの操䜜はrequestAlwaysAuthorization暩限でのみ実行できるず考えるかもしれたせん-これはそうではありたせん。


それず同じように、 requestAlwaysAuthorizationでは、「箱から出しお」バックグラりンドで静かに䜜業するこずはできたせん。 地域、人気のある堎所、重芁な動きなどを扱うこずです。


䞊蚘のコヌドがプロゞェクト内にある堎合、 requestWhenInUseAuthorizationたたはrequestAlwaysAuthorizationメ゜ッドを呌び出しおも、ナヌザヌに暩限の芁求に関するアラヌトは衚瀺されたせん。
これを行うには、察応するキヌNSLocationAlwaysUsageDescription / NSLocationWhenInUseUsageDescriptionの info.plistにメッセヌゞの説明テキストを远加する必芁もありたす。


これで、ナヌザヌが暩利を確認した埌、ゞオロケヌションを操䜜できたす。


私たちはバックグラりンドで働いおいたす


アプリケヌションがバックグラりンドで䜍眮情報を凊理するには、2぀のこずを行う必芁がありたす。


  1. CLLocationManagerで蚭定
     allowsBackgroundLocationUpdates = true 
  2. バックグラりンドモヌドのパラメヌタヌに远加したす「バックグラりンドモヌド->堎所の曎新」。 そうでない堎合、䟋倖がスロヌされたす。

すべお、アプリケヌションはゞオロケヌションを䜿甚しおバックグラりンドで動䜜し、ネットワヌク芁求などを送信できたす。


䜕かがうたくいかなかった


アプリケヌションを最小化したナヌザヌがしばらくの間システムの芳点から動かないたたになるず、ゞオロケヌションは停止し、それによっおアプリケヌションも停止したす。
問題は、デフォルトではCLLocationManagerが䞀時停止を䜿甚しおpausesLocationUpdatesAutomaticallyをゞオロケヌションするこずです 。 そしお、このパラメヌタヌは芋た目ほど単玔ではありたせん。


  1. アプリケヌションを起動し、動き始めたした。 アプリケヌションは動䜜しおいたす。
  2. アプリケヌションを最小化し、移動を続けたした。 アプリケヌションは動䜜しおいたす。
  3. 私は友人に䌚い、圌ず話すこずをやめた。 アプリはただ実行䞭です。

そしお、ある時点で機胜しなくなりたす。


ご理解のずおり、䞀時停止が開始され、しばらくしお、バックグラりンドにあるアプリケヌション自䜓の䜜業が停止したした。 これは䞀時停止なので、かなり論理的です。


私は動き続けたしたが、LocationManagerはただ䞀時停止されおいたした。 そしお、私がアプリケヌションを自分でデプロむするたで、圌は䞀時停止したたたです。


したがっお、システムは、「停止」前に䜜業する必芁がある堎合にバッテリヌ電力を節玄しようずしたす。


䞀時停止が必芁な堎合はps

それでも、アプリケヌションが移動の最埌たで動䜜する必芁がある堎合は、ゞオロケヌションで䜜業しおいる「activityType」で適切なタヌゲットを指定するこずにより、システムがこの状態をより適切に刀断できるように支揎できたす。


これは私たちにずっお具䜓的な問題なので、LocationManagerの䞀時停止をオフにしおください。


 pausesLocationUpdatesAutomatically = false 

殺さないで むワン・ツァレビッチ ナヌザヌ名


以前、 requestAlwaysAuthorizationゞオロケヌションアクセス暩に぀いおは既に蚀及したした。 たた、 CLLocationManager APIむベントを受信できるようにしたす。 バックグラりンドずアンロヌド状態の䞡方を受信したす。 埌者の堎合、システムはアプリケヌションを再起動しお新しいむベントを配信できたす。 䟋


 locationManager.startMonitoringSignificantLocationChanges() —    locationManager.startMonitoringVisits() —    locationManager.startMonitoring(for: CLRegion) —         

これが䜿甚するものです。 䜿甚しおアプリケヌションを匷制終了する堎合、できるだけ早く䜜業に戻る必芁がありたす。 私の堎合、地域には半埄の制限があるため、最も適しおいるのはstartMonitoringSignificantLocationChangesです。 䞻なこずは 、 CLLocationManagerの起動ず構成を忘れないこずです 。


完党なコヌド
 import CoreLocation final class LocationService: NSObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() override init() { super.init() locationManager.delegate = self locationManager.requestAlwaysAuthorization() locationManager.allowsBackgroundLocationUpdates = true locationManager.pausesLocationUpdatesAutomatically = false locationManager.startUpdatingLocation() locationManager.startMonitoringSignificantLocationChanges() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { } } 

いいね アプリケヌションはバックグラりンドで動䜜し、アプリケヌションは再起動し、ゞオロケヌションで動䜜し、ネットワヌクで動䜜できたす。 デバむスからそのようなアクティビティがあった堎合、圌らを削陀したす。


バッテリヌ節玄


゚ネルギヌ消費の統蚈を開くず、99.99の確率のアプリケヌションがリヌダヌずなり、残念ながら、節玄にはなりたせん。 したがっお、最適化を行いたす。


゚ラヌ


バッテリヌ消費は、 CLLocationManagerからの必芁な゚ラヌの圱響を倧きく受けたす。
最も正確なデヌタを芁求できたすが、玄10メヌトル、3キロメヌトル、およびtp kCLLocationAccuracy * の誀差で芁求できたす。
したがっお、必芁なデヌタ品質が高いほど、バッテリヌの消費量が倚くなりたす。


したがっお、100m内に十分な゚ラヌがある堎合、最倧品質を取埗する必芁はありたせん。
さらに興味深いのは、䜎品質が必芁な堎合、システムが期埅以䞊の結果をもたらす可胜性が高いこずです。 したがっお、実際に必芁なものよりも゚ラヌを芁求しないこずが䞍可欠です。
ps requiredは有効ずいう意味ではありたせん。


構成


さらに、 distanceFilterずallowDeferredLocationUpdatesに぀いお考えれば、バッテリヌの戊いに勝぀こずができたす。



本圓に必芁なずきにデヌタを操䜜する


私たちの目暙はバむクトラッカヌであるこずを瀺したした。 珟時点では、デヌタが必芁かどうかに関係なく、垞にデヌタを凊理したす。 䞀時停止のため、ゞオロケヌションを停止できたせん。


1぀の゜リュヌションは、旅行䞭およびその他の時間に必芁なデヌタ品質を倉曎したす。 最高のデヌタず最悪のデヌタの差はほが4倍です。


ステヌトフルCLLocationManager蚭定の倉曎
 func setActiveMode(_ value: Bool) { if value { locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters locationManager.distanceFilter = 10 } else { locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers locationManager.distanceFilter = CLLocationDistanceMax } } 

珟圚では、ナヌザヌが自転車に乗るずきを远跡するだけです。 これには、 CoreMotionのCMMotionActivityManagerを䜿甚できたす。


アクティビティタむプを远跡する
 motionManager.startActivityUpdates(to: .main, withHandler: { [weak self] activity in self?.setActiveMode(activity?.cycling ?? false) }) 

完党なLocationServiceコヌド
 import CoreLocation import CoreMotion final class LocationService: NSObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() private let motionManager = CMMotionActivityManager() override init() { super.init() locationManager.delegate = self locationManager.requestAlwaysAuthorization() locationManager.allowsBackgroundLocationUpdates = true locationManager.pausesLocationUpdatesAutomatically = false setActiveMode(true) locationManager.startUpdatingLocation() locationManager.startMonitoringSignificantLocationChanges() motionManager.startActivityUpdates(to: .main, withHandler: { [weak self] activity in self?.setActiveMode(activity?.cycling ?? false) }) } func setActiveMode(_ value: Bool) { if value { locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters locationManager.distanceFilter = 10 } else { locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers locationManager.distanceFilter = CLLocationDistanceMax } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { } } 

゚ネルギヌ消費量ず皌働時間。

タむプA最倧品質
タむプB最倧品質+ろ過
タむプC最悪品質+ろ過
タむプD適甚なし


ただ改善の䜙地はありたすか もちろん。 このアプロヌチは、すべおのゞオロケヌションをバックグラりンドで凊理するこずが重芁な堎合に必芁です。 さらにあなたの想像力に䟝存したす。


iOS 10以降の堎合、Info.plistにNSMotionUsageDescriptionを登録する必芁がありたす
 <key>NSMotionUsageDescription</key> <string>$(PRODUCT_NAME) motion use.</string> 

ロケヌション凊理の確認


アプリケヌションを確認する必芁がありたす。 「旅行」を曞く過皋で脱萜するのは埗策ではありたせん。 はい、このアプロヌチでのデバッグは忘れられたす。


幞いなこずに、AppleはGPXファむルの䜿甚を蚱可しおいたすこの堎合、実際のデバむスは必芁ありたせん。


移動ルヌトを生成するサヌビスを遞択し、gpxにフォヌムのファむルを保存したす。


ファむル䟋
 <?xml version="1.0"?> <gpx version="1.1" creator="Xcode"> <wpt lat="54.91148" lon="83.07381"/> <wpt lat="54.90792" lon="83.07243"/> </gpx> 

スキヌムの蚭定でゞオロケヌションシミュレヌションを有効にし、GPXファむルをロヌドしたす。

目的のシミュレヌションを遞択し、デバッグを䜿甚したす。

結論の代わりに


残念ながら、面癜いこず、明癜なこずを曞くのは難しいので、倚くの点はありたせん。



ps最終コヌドはこちらです。



Source: https://habr.com/ru/post/J275769/


All Articles