93

高精度で低頻度のバックグラウンド位置更新を必要とするアプリケーションを作成しています。解決策は、ロケーション マネージャーの更新を開始し、すぐにシャットダウンするバックグラウンド NSTimer タスクのようです。この質問は以前に尋ねられました:

iOS アプリケーションで n 分ごとにバックグラウンドで位置情報を更新するにはどうすればよいですか?

アプリがバックグラウンドになった後、n 分ごとにユーザーの位置情報を取得する

iOS 典型的なバックグラウンド位置追跡タイマーの問題ではない

「場所」バックグラウンド モードを使用した iOS 長時間バックグラウンド タイマー

位置追跡に基づく iOS フルタイム バックグラウンド サービス

しかし、最低限の例をまだ動かしていません。上記の受け入れられた回答のすべての順列を試した後、出発点をまとめました。背景を入力:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"ending background task");
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }];


    self.timer = [NSTimer scheduledTimerWithTimeInterval:60
                                                  target:self.locationManager
                                                selector:@selector(startUpdatingLocation)
                                                userInfo:nil
                                                 repeats:YES];
}

およびデリゲート メソッド:

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation {

    NSLog(@"%@", newLocation);

    NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
    [self.locationManager stopUpdatingLocation];

}

現在の動作では、backgroundTimeRemaining180 秒から 0 まで減少し (場所のログ記録中)、有効期限ハンドラーが実行され、それ以上の場所の更新は生成されません。バックグラウンドで定期的な位置情報の更新を無期限に受信するには、上記のコードをどのように変更すればよいですか?

更新: iOS 7 をターゲットにしていますが、バックグラウンド タスクの動作が異なるという証拠がいくつかあるようです。

バックグラウンド タスクから iOS 7 の Location Manager を起動する

4

9 に答える 9

62

それstopUpdatingLocationがバックグラウンドのウォッチドッグタイマーをトリガーしているように見えるので、次のように置き換えましたdidUpdateLocation

[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];

これは、GPS の電源を効果的に落としているように見えます。背景のセレクターは次のようNSTimerになります。

- (void) changeAccuracy {
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

私が行っているのは、定期的に精度を切り替えて、数分ごとに高精度の座標を取得することです。locationManager停止していないため、backgroundTimeRemaining最大値のままです。これにより、デバイスのバッテリー消費量が 1 時間あたり 10% (kCLLocationAccuracyBestバックグラウンドで一定) から 1 時間あたり 2% に減少しました。

于 2013-09-30T02:13:54.330 に答える
46

位置情報サービスを使用してアプリを作成しました。アプリは 10 秒ごとに位置情報を送信する必要があります。そして、それは非常にうまくいきました。

Apple のドキュメントに従って、「 allowDeferredLocationUpdatesUntilTraveled:timeout 」メソッドを使用するだけです。

手順は次のとおりです。

必須:更新場所のバックグラウンド モードを登録します。

1. LocationManger と startUpdatingLocation を、任意の精度とfilteredDistance で作成します。

-(void) initLocationManager    
{
    // Create the manager object
    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    _locationManager.delegate = self;
    // This is the most important property to set for the manager. It ultimately determines how the manager will
    // attempt to acquire location and thus, the amount of power that will be consumed.
    _locationManager.desiredAccuracy = 45;
    _locationManager.distanceFilter = 100;
    // Once configured, the location manager must be "started".
    [_locationManager startUpdatingLocation];
}

2.バックグラウンドで「allowDeferredLocationUpdatesUntilTraveled:timeout」メソッドを使用してアプリを永久に実行し続けるには、次のように、アプリがバックグラウンドに移動したときに新しいパラメーターを使用して updatesLocation を再起動する必要があります。

- (void)applicationWillResignActive:(UIApplication *)application {
     _isBackgroundMode = YES;

    [_locationManager stopUpdatingLocation];
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [_locationManager setDistanceFilter:kCLDistanceFilterNone];
    _locationManager.pausesLocationUpdatesAutomatically = NO;
    _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
    [_locationManager startUpdatingLocation];
 }

3.アプリは、「locationManager:didUpdateLocations:」コールバックを使用して、updatedLocations を通常どおり取得します。

-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
    CLLocation *newLocation = [locations lastObject];
    self.userLocation = newLocation;

   //tell the centralManager that you want to deferred this updatedLocation
    if (_isBackgroundMode && !_deferringUpdates)
    {
        _deferringUpdates = YES;
        [self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
    }
}

4.ただし、目的に応じて「locationManager:didFinishDeferredUpdatesWithError:」コールバックでデータを処理する必要があります

- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

     _deferringUpdates = NO;

     //do something 
}

5. 注:アプリがバックグラウンド モードとフォアグラウンド モードを切り替えるたびに、LocationManager のパラメーターをリセットする必要があると思います。

于 2014-07-10T02:18:05.997 に答える
39
  1. UIBackgroundModesplist にkeyがある場合は、メソッドlocationを使用する必要はありませんbeginBackgroundTaskWithExpirationHandler。それは冗長です。また、間違って使用しています(こちらを参照)が、plistが設定されているため、それは意味がありません。

  2. plist を使用UIBackgroundModes locationすると、アプリは実行されている間だけ無期限にバックグラウンドで実行され続けCLLocationMangerます。バックグラウンドで呼び出した場合stopUpdatingLocation、アプリは停止し、再起動しません。

    電話をかけるbeginBackgroundTaskWithExpirationHandler直前に電話して、電話をかけstopUpdatingLocationた後に を呼び出しstartUpdatingLocationて、GPS が停止している間バックグラウンドを維持することもできますがendBackgroundTask、私はそれを試したことはありません。これは単なるアイデアです。

    別のオプション (私は試していません) は、バックグラウンドでロケーション マネージャーを実行し続けることですが、正確な位置を取得したら、desiredAccuracyプロパティを 1000 m 以上に変更して、GPS チップをオフにできるようにします (バッテリーを節約するため)。それから 10 分後に別の位置情報の更新が必要になったら、desiredAccuracyバックを 100m に変更して、正確な位置が得られるまで GPS をオンにします。これを繰り返します。

  3. ロケーションマネージャーに連絡するときはstartUpdatingLocation、ポジションを取得する時間を与える必要があります。すぐに電話しないでくださいstopUpdatingLocation。最大 10 秒間、またはキャッシュされていない高精度の位置情報を取得するまで実行します。

  4. キャッシュされた場所を除外し、取得した場所の精度をチェックして、最低限必要な精度を満たしていることを確認する必要があります (こちらを参照)。最初の更新は、10 分または 10 日経過している可能性があります。最初に得られる精度は 3000m かもしれません。

  5. 代わりに、重要な場所変更 API の使用を検討してください。重要な変更の通知を受け取ったらCLLocationManager、数秒間開始して高精度の位置を取得できます。確かではありませんが、重要な場所の変更サービスを使用したことがありません。

于 2013-09-27T13:02:25.527 に答える
10

位置情報サービスを開始してバックグラウンド タスクを停止するときは、バックグラウンド タスクを遅延して停止する必要があります (1 秒で十分です)。そうしないと、位置情報サービスが開始されません。また、位置情報サービスを数秒間 (たとえば 3 秒間) オンのままにしておく必要があります。

必要な位置精度でn秒ごとにバックグラウンド位置更新を取得できるcocoapod APScheduledLocationManagerがあります。

let manager = APScheduledLocationManager(delegate: self)
manager.startUpdatingLocation(interval: 170, acceptableLocationAccuracy: 100)

リポジトリには、Swift 3 で記述されたサンプル アプリも含まれています。

于 2016-10-29T14:37:41.413 に答える
1

info.plist に次のキーを追加して、アプリケーションに位置更新モードを追加する必要があります。

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

didUpdateToLocationメソッドが呼び出されます (アプリがバックグラウンドにある場合でも)。このメソッド呼び出しに基づいて何でも実行できます

于 2013-09-27T05:28:01.257 に答える
1

startMonitoringSignificantLocationChanges:APIで試してみませんか?それは間違いなくより少ない頻度で発砲し、精度はかなり良い. locationManagerさらに、他のAPIを使用するよりも多くの利点があります。

この API に関する詳細は、このリンクで既に説明されています

于 2013-09-27T05:21:35.397 に答える
0

アプリケーションがバックグラウンドにあるときに標準の位置情報サービスを使用するには、まずターゲット設定の [機能] タブで [バックグラウンド モード] をオンにし、[位置情報の更新] を選択する必要があります。

または、Info.plistに直接追加します。

<key>NSLocationAlwaysUsageDescription</key>
 <string>I want to get your location Information in background</string>
<key>UIBackgroundModes</key>
 <array><string>location</string> </array>

次に、CLLocationManager をセットアップする必要があります

オブジェクティブ C

//The Location Manager must have a strong reference to it.
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
//Request Always authorization (iOS8+)
if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [_locationManager requestAlwaysAuthorization];
}
//Allow location updates in the background (iOS9+)
if ([_locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) { _locationManager.allowsBackgroundLocationUpdates = YES;
}
[_locationManager startUpdatingLocation];

迅速

self.locationManager.delegate = self
if #available (iOS 8.0,*) {
    self.locationManager.requestAlwaysAuthorization()
}
if #available (iOS 9.0,*) {
    self.locationManager.allowsBackgroundLocationUpdates = true
}
self.locationManager.startUpdatingLocation()

参照: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba

于 2019-08-24T22:23:37.353 に答える
-3
locationManager.allowsBackgroundLocationUpdates = true
于 2019-01-10T07:36:14.780 に答える