web-dev-qa-db-ja.com

終了/中断時の重要な場所の変更APIの動作は?

これは、 clLocationManager ドキュメンテーションのセクションで、 startMonitoringSignificantLocationChanges を使用したアプリの動作について説明しています。

このサービスを開始し、その後アプリケーションが終了した場合、新しいイベントが到着すると、システムは自動的にアプリケーションをバックグラウンドで再起動します。このような場合、アプリケーションデリゲートのapplication:didFinishLaunchingWithOptions:メソッドに渡されるオプションディクショナリには、位置イベントのためにアプリケーションが起動されたことを示すキーUIApplicationLaunchOptionsLocationKeyが含まれます。再起動時に、ロケーションマネージャオブジェクトを設定し、このメソッドを呼び出してロケーションイベントの受信を継続する必要があります。位置情報サービスを再起動すると、現在のイベントがすぐにデリゲートに配信されます。さらに、ロケーションサービスを開始する前でも、ロケーションマネージャーオブジェクトのロケーションプロパティに最新のロケーションオブジェクトが入力されます。

したがって、私の理解では、アプリが終了すると(そして applicationWillTerminate から stopMonitoringSignificantLocationChanges を呼び出さないと仮定すると) UIApplicationLaunchOptionsLocationKey パラメーターで application:didFinishLaunchingWithOptions に起こされます。その時点で、 CLLocationManager を作成し、 startMonitoringSignificantLocationChanges を呼び出し、 limitedのバックグラウンドロケーション処理を行います時間 。だから私はこのビットで大丈夫です。

前の段落では、アプリが終了したときに何が起こるかについてのみ説明しましたが、アプリケーションが中断されたときに何をすべきかを示唆していません。 didFinishLaunchingWithOptions のドキュメントには次のように書かれています:

アプリケーションは、ロケーションの更新をバックグラウンドで追跡し、削除され、再起動されました。この場合、辞書には、新しい場所イベントのためにアプリケーションが再起動されたことを示すキーが含まれています。

終了後にアプリが起動されたとき(場所の変更のため)にのみ、この呼び出しを受け取ることを提案します。

ただし、 Location Awareness Programming GuideSignificant Change Service の段落には、次のように記載されています。

このサービスを実行したままにして、アプリケーションがその後中断または終了した場合、新しい位置データが到着すると、サービスはアプリケーションを自動的に起動します。ウェイクアップ時に、アプリケーションはバックグラウンドに置かれ、位置データを処理するためのわずかな時間が与えられます。アプリケーションはバックグラウンドにあるため、最小限の作業を行い、割り当てられた時間が経過する前に戻ることを妨げる可能性のあるタスク(ネットワークへのクエリなど)を避ける必要があります。そうでない場合、アプリケーションは終了する可能性があります。

これは、アプリが中断された場合に位置データで目覚めていることを示唆していますが、目覚め方については言及していません。

  • UIApplicationDelegate は、一時停止状態からバックグラウンド状態に復帰していることを通知するコールバックを取得しますか?
  • ロケーションマネージャー(アプリが中断されたときにフリーズドライ)は locationManager:didUpdateToLocation:fromLocation コールバックの受信を開始しますか?
  • アプリケーションの状態をチェックし、バックグラウンドモードの場合は最小限の処理を行う didUpdateToLocation メッセージにコードを実装するだけでよいですか?

これを書く過程で、私は自分の質問に答えたばかりかもしれないと思いますが、より知識のある誰かがこのことを理解していることを確認するのは素晴らしいことです。

109
RedBlueThing

この質問をしてから、かなりのテストを行い(主に自宅と職場の間の電車で)、中断されたアプリの動作が質問の最後で疑ったとおりであることを確認しました。

つまり、中断されたアプリは起動され、アプリのデリゲートでコールバックを受信するのではなく、既存の CLLocationManagerDelegate を介して位置の更新を受信します。 applicationStateをチェックすることにより、バックグラウンドで実行していることを検出できます。また、ロケーション処理を行うためにサスペンド状態から起こされた場合に限られた作業を行います。

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground

download を歓迎するロケーションテストハーネスでこの結論に至りました。 UIを介して大幅な変更とGPS変更APIを有効にし、返されたすべての応答をログに記録できる非常にシンプルなアプリです。

N.B。前の回答のポイント6は正しくありません。 フリーズドライ一時停止中のアプリは、一時停止状態から復帰したときにCLLocationManagerDelegateコールバックを受け取ります。

80
RedBlueThing

私の理解は次のとおりです(このAPIに依存するアプリケーションを作成中ですが、テストを開始するのに十分なこのコンポーネントを完了していません)。

  1. アプリケーションが初めて実行されると、startMonitoringSignificantLocationChangesに登録し、コールバック関数を提供します。アプリケーションの実行中、大幅な変更を受け取るたびにコールバックを呼び出します。
  2. アプリケーションがバックグラウンドに置かれている場合、UIApplicationはapplicationWillResignActiveを受け取り、その後にapplicationDidEnterBackgroundが続きます。
  3. バックグラウンドで一時停止中にアプリケーションが強制終了された場合、通知されません。ただし、実行中にアプリケーションが強制終了された場合(私の知る限り、フォアグラウンドまたはバックグラウンド)、applicationWillTerminateが表示されます。この関数から余分なバックグラウンド時間を要求することはできません。
  4. バックグラウンドで強制終了されますが、OSはアプリケーションを再起動します。変更のためにOSによってアプリケーションが単に起動される場合、application didFinishLaunchingWithOptionsへの呼び出しを取得します。

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])
    

    バックグラウンドの場所の変更から戻ってきたかどうかを判断するのに役立ちます。

  5. 代わりに、現在バックグラウンドで実行されていて、ユーザーがアプリを手動で再起動した場合、applicationWillEnterForegroundに続いてapplicationDidBecomeActiveが返されます。
  6. どのように発生したかに関係なく、アプリケーションを再起動するとき(バックグラウンドタスクの結果としてまだバックグラウンドで実行されていて、タスクが変更の監視を開始した場合を除き)、明示的にstartMonitoringSignificantLocationChangesに伝える必要があります=「凍結乾燥」後にコールバックが添付されなくなるため。そして、はい、一時停止状態から戻ったときに何らかの種類のロケーションハンドラーを再アタッチしたら、didUpdateToLocationにコードを実装するだけです。

これが、私が現在コード開発で行っていることです。前に述べたように、デバイスでこれをテストする準備ができていないので、すべてを正しく解釈したかどうかわかりませんので、コメントする人は私に訂正してください(ただし、トピック)。

ああ、もし運が悪ければ、あなたが私のやりたいことをするアプリをリリースしたら、泣くかもしれない:)

がんばろう!

25
Aaron

ロケーション変更の結果としてアプリケーションが一時停止状態から呼び出された場合、アプリケーションはバックグラウンド状態で起動します。

すべてのオブジェクトがライブになり、既存のデリゲートで位置の更新を受け取ります。

1
Anshu