web-dev-qa-db-ja.com

アプリがバックグラウンドにある場合、しばらくすると位置追跡が停止します

ユーザーの場所を追跡し、場所が更新されるたびにローカル通知を作成するシンプルなアプリを作成しました。

以下のバックグラウンドモードを有効にしました。

enter image description here

let locationManager = CLLocationManager()

open override func viewDidLoad() {
       locationManager.delegate = self;
       locationManager.desiredAccuracy = kCLLocationAccuracyBest;
       locationManager.distanceFilter = 10
       locationManager.allowsBackgroundLocationUpdates = true
       locationManager.startUpdatingLocation()
}

open func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
       let notification = UILocalNotification()
       notification.alertBody = "location updated"
       notification.fireDate = Date()
       UIApplication.shared.scheduleLocalNotification(notification)
}

NSLocationAlwaysUsageDescriptionに文字列を設定し、許可を求めます。ユーザーは、アプリが初めて読み込まれたときに常に使用するためのアクセス許可を付与します。


アプリがフォアグラウンドにあるとき、バックグラウンドになったときまだ機能しているバッテリーまたはその他によって変更可能な少なくとも5〜40分の時間範囲でうまく機能します開いたアプリ。

問題は、それが動作を停止する理由です、動作し続けることが期待されていませんか?

Apple docs。

23
ocanal

アプリがバックグラウンドに移行したら、重要な現在地の更新に切り替えます。 iOSは、バックグラウンドで無期限に存続している場合、アプリをアンロードします。

locationManager.pausesLocationUpdatesAutomatically = false
23
Vimal Saifudin

精度を下げる

ロケーションマネージャオブジェクトの desiredAccuracy プロパティを設定します

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation

CLLocationAccuracy 定数のいずれかを使用できます

重要

デフォルトでは、iOSデバイスでの標準の場所の更新は、最高の精度レベルで実行されます。アプリの要件に合わせてこれらの設定を変更します。そうしないと、アプリが不必要にエネルギーを無駄にします。


オートポーズ

ロケーションマネージャーオブジェクトの pausesLocationUpdatesAutomatically プロパティをtrueに設定します

self.locationManager.pausesLocationUpdatesAutomatically = true

重要

使用中の承認があるアプリの場合、位置情報の更新を一時停止すると、アプリが再度起動され、それらの更新を再開できるようになるまで、位置情報の変更へのアクセスが終了します。位置情報の更新を完全に停止したくない場合は、このプロパティを無効にし、アプリがバックグラウンドに移動したときに位置の精度を kCLLocationAccuracyThreeKilometers に変更することを検討してください。そうすることで、ロケーションの更新を電力に優しい方法で受信し続けることができます。


バックグラウンド更新を許可する

ロケーションマネージャーオブジェクトの allowsBackgroundLocationUpdates プロパティをtrueに設定します

self.locationManager.allowsBackgroundLocationUpdates = true

一時停止したときに位置情報の更新を受け取りたいアプリは、アプリのInfo.plistファイルにUIBackgroundModesキー(位置値を含む)を含め、このプロパティの値をtrueに設定する必要があります。バックグラウンド更新には、場所の値を持つUIBackgroundModesキーの存在が必要です


アクティビティタイプを指定する

activityType プロパティを設定して、特定の時間にアプリが実行しているロケーションアクティビティのタイプをCore Locationに知らせます

self.locationManager.activityType = .automotiveNavigation 

CLActivityType のいずれかのケースを使用できます


ロケーション更新の延期

GPSハードウェアを搭載したサポートされているデバイスでは、アプリがバックグラウンドにある場合にロケーションマネージャーにロケーション更新の配信を延期させることができます。たとえば、ハイキングトレイルでユーザーの位置を追跡するフィットネスアプリは、ユーザーが一定の距離を移動するか、一定の時間が経過するまで更新を延期できます。


7

参照を検索した後(制限について話します)、Apple Core Location Best Practices ビデオセッションが役に立つかもしれません!at 06:53バックグラウンドでの標準的な場所の話:

さらに、Core Locationはアプリの実行を継続するためのアクションを実行しません。そのため、何らかの理由でバックグラウンドで実行しており、ロケーションセッションを開始することにした場合、更新を受け取る可能性がありますが、受信する前に中断される可能性もあります受け取りたいすべての情報...

実際、私は以前にこの問題に直面しました-回避策として-コアロケーションは、ユーザーのロケーションを追跡してそのロケーションに無関係な機能を実行します-ファイルをアップロードしています-しかし、この回避策はiOS 9以来機能しませんでしたリリースされました;この問題について question を引用して投稿しました。

ただし、次のことを目指している場合、あなたのケースは私が直面したものと同じではないようです:

...場所が更新されるたびにローカル通知を作成します。

次に、User Notification Framework- NLocationNotificationTrigger と統合するアプローチに従う必要があります。

ローカル通知の配信を可能にするためにユーザーが到達する必要がある地理的な場所。

ビデオセッションでも言及されています(08:59)。

おそらく、これはあなたが探しているものではないかもしれませんが、バックグラウンド実行が継続して実行される保証はないので、あなたは-どういうわけか-あなたのアプリにそれを統合して望ましい機能を達成する方法を見つけるかもしれません。

iOS 11のアップデート:

ロケーションアクセスをリクエストする適切な方法については、 this answer を確認する必要があるかもしれません。

2
Ahmad F

それの音によって、アプリはメモリの制約のために殺されています。ただし、ここで説明するように、新しい場所が利用可能になったら再起動する必要があります。 https://developer.Apple.com/documentation/uikit/uiapplicationlaunchoptionskey/1623101-location

application(_:didFinishLaunchingWithOptions:)が呼び出され、起動オプションに 'location'キーが存在するはずです。その後、場所を消費しているものは何でも再作成し、記録を続けることができます。

再起動されていない場合は、メモリが不足している可能性があります。アプリのメモリ消費量を確認し、applicationDidReceiveMemoryWarning(_:)が呼び出されているかどうかを確認します。

1
Tom Durrant

バックグラウンドタスクを実装していないと思います。 here と読むことができます。

上記のリンクのセクション「長時間実行タスクの実装」ポイント番号3はあなたの状況です。したがって、プロジェクトでバックグラウンドの場所の更新を使用でき、同じためにバックグラウンドタスクも実装する必要があることは有効です。

ユーザーの位置を追跡するには、3つの方法があります(上記のセクションの「ユーザーの位置の追跡」):-

  1. フォアグラウンドのみの位置情報サービス(あなたのケースで機能します)
  2. 大幅に変更された位置情報サービス(Recommended)が、10メートルごとにユーザーの位置を更新したいので、あなたのケースでは使用できないと思う〜500メートルで動作します。詳細は こちら をご覧ください
  3. バックグラウンド位置情報サービス(これを試みていると思います)および解決策は、バックグラウンドタスクを追加することです。

    以下はバックグラウンドタスクの例であり、要件に応じて変更できます。過去2時間以来機能し、アプリは引き続きバックグラウンドで場所を更新します。

。 AppDelegateクラスで、以下の関数を更新してから、アプリをバックグラウンドで実行してください。

func applicationDidEnterBackground(_ application: UIApplication) {
    application.beginBackgroundTask(withName: "") {}
}

そして、以下は私のViewControllerクラスです

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self;
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.distanceFilter = kCLDistanceFilterNone

        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
            self.locationManager.startUpdatingLocation()
        }

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("didUpdateLocations \(Date())")
        self.locationManager.stopUpdatingLocation()
    }

}
0
Anand Suthar