web-dev-qa-db-ja.com

iOS Geofence CLCircularRegionモニタリング。 locationManager:didExitRegionが期待どおりに機能していないようです

現在、CoreLocationを使用して特定の領域を監視するようにアプリを取得しようとしていますが、期待どおりに動作しないようです。各場所に小さな半径を設定すると動作しないようですすなわち10メートル。

また、円の半径を地図上にプロットする小さなテストアプリをまとめて、何が起きているかを視覚的に確認できるようにしました。

場所の監視に使用しているコードは次のとおりです。

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;

// Set-up a region
CLLocationDegrees latitude = 52.64915;
CLLocationDegrees longitude = -1.1506367;
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);

CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:centerCoordinate
                                                                 radius:10 // Metres
                                                             identifier:@"testLocation"];

[self.locationManager startMonitoringForRegion:region];

DidEnter地域などのコードをここに配置していません。監視対象地域から100m以上離れたときに機能することがわかっています。

地図上の紫色の場所から10メートル以上離れている場合のアプリのスクリーンショットを次に示します。終了領域イベントは発生しませんでしたが、locationロンドン起動し、locationを青い場所に戻す現在、それも起動します。

Example Region

最小領域半径に制限があるのか​​、おそらく何か間違ったことをしているのかを誰もが知っていますか?.

ありがとうアーロン

28
MonkeyBlue

このような小さな半径では、リージョンモニタリングがうまく機能するとは思わない。

  • GPSチップとkCLLocationAccuracyBestForNavigationを使用した場合の最高の精度は、多くの場合わずか10メートルです。
  • Appleは、( Location&Maps PG で)リージョンの最小距離は200mであると仮定する必要があると述べています
  • 地域の監視ではWiFiを使用して位置を取得していると聞きました(これは節電に意味があります)。 WiFiの精度は20m〜100m程度です。バックグラウンドロケーションを使用する(GPSを使用する)別のアプリがこれにどのように影響するかはわかりません。おそらく、ロケーションマネージャーは情報を共有して、精度を向上させるでしょう。
  • リージョンモニタリングは、リージョン内で1回起動するのに30秒かかり、リージョンを離れてから起動するのに数分かかることがあります(ロケーショングリッチによるトリガーを防ぐため)。
  • リージョンモニタリングが最初に導入されたとき、彼らは100mのリージョンでのみ動作し、それより小さいものはバンプアップされると述べました。これはおそらくまだ起こります。
  • 非推奨のメソッドstartMonitoringForRegion:desiredAccuracy:通知の生成を開始するために、リージョンの境界を越えた距離を指定できます。おそらく、この機能はstartMonitoringForRegion:しかし、まだあります。 10mの領域は、10mのバッファで終わる可能性があります。
  • これを行いたい場合は、監視する場所の周りに大きな地域を指定し、その地域でデバイスが起動したら、バックグラウンドロケーション更新(GPS)を開始し、CLCircularRegion 's -containsCoordinate:デバイスが手動で10m以内にあるときにトリガーします。このメソッドは、公式にApple( WWDC 201 Session 307を参照)によって認可されています。

CLCircularRegionドキュメントから:

ロケーションマネージャは、リージョンの境界を越えてもすぐに通知を生成しないことに注意してください。代わりに、時間と距離の基準を適用して、交差が意図されたものであり、本当に通知をトリガーするようにします。したがって、適切な中心点と半径を選択し、ユーザーに警告するのに十分な時間を与えます。

Location&Maps PG から:

リージョン境界を超えた直後にリージョンイベントが発生しない場合があります。偽の通知を防ぐため、iOSは特定のしきい値条件が満たされるまで地域通知を配信しません。具体的には、ユーザーの位置は領域の境界を越え、境界から最小距離だけ移動し、通知が報告されるまで少なくとも20秒間その最小距離に留まる必要があります。
特定のしきい値距離は、現在利用可能なハードウェアとロケーションテクノロジーによって決まります。たとえば、Wi-Fiが無効になっている場合、地域の監視の精度は大幅に低下します。ただし、テスト目的では、最小距離は約200メートルであると想定できます。

Kevin McMahonによるこの投稿 からの内部スクープがあります。彼は、コアロケーションエンジニアにWWDC 2012のラボでの地域モニタリングについて質問しました。面白い。編集は次のとおりです。

Fine Region(0-150m)
-100mの床では、このカテゴリの範囲は事実上100-150mです。
-地域の場合、このサイズのパフォーマンスは場所関連のハードウェアに大きく依存します
-コアロケーションが適切なデリゲートメソッドを検出して呼び出すのにかかる時間は、領域の境界を越えてから平均で約2〜3分です。
-一部の開発者は、小さな地域ではより速いコールバックが表示され、小さな地域をクラスター化して1つの大きなエリアをカバーし、地域横断通知を改善することを独自に考えています。

51
nevan king

これはCLLocationManagerのバグのようです。さまざまな領域の半径構成とlocationManager:didExitRegionは予期した方法で起動しません。これはかなり厄介なバグであるか、ドキュメントが示唆するように地域の監視がまったく行われないようです。私はそれを望む誰でも利用できるテストハーネスを持っています:

http://www.mediafire.com/download/x863zkttltyalk6/LocationTest.Zip

シミュレータで実行し、iOSシミュレータメニューで[デバッグ]-> [場所]-> [Freeway Drive]を選択してテストを開始します。表示される数値は、監視対象地域の中心からの距離です。背景色は、デバイスが監視対象地域内にある間は緑になり、地域外になると赤になります。距離の下のテキストはイベントログです。

enter image description here

アプリを実行すると、locationManager:didExitRegion監視対象地域から5319メートルで発射。ルートは37分ごとにループし、デバイスが常に5319メートルで地域を出るのがわかります。

radar with Apple(17064346) を提出しました。返事があったらこの回答を更新します。少なくともその後は入力があります正規のソースから。

Appleに送信される詳細なテキストは次のとおりです。

IOSシミュレーターとiPhone 5Sでテストアプリを使用すると、CLLocationManagerがdidExitRegionコールバックを予期したとおりに起動しないようです。監視対象の円形領域の半径に関係なく、約5000メートルのしきい値に達するまでコールバックは発生しません。

再現する手順:
1。添付アプリを実行する
2。 iOSシミュレータで[デバッグ]-> [場所]-> [Freeway Drive]を選択して、リージョントラッキングを開始します。
3。アプリを監視します。大きな#は、監視対象領域の中心からの距離を示します。
4。約190秒後、5300メートルのdidExitRegionが最終的に起動します。

この問題は、リージョンのサイズとはまったく関係がないようです。 Apple docs によると、小さな地域でもサポートされています:

IOS 6では、半径が1〜400メートルの地域は、iPhone 4S以降のデバイスでより適切に機能します。 (iOS 5では、半径が1から150メートルの地域は、iPhone 4S以降のデバイスでより適切に動作します。)これらのデバイスでは、アプリは平均で3から5分以内に適切な地域入力または地域退出通知を受け取ることができます。早ければ。

リージョンイベントは瞬時には発生しませんが、かなり迅速に発生するはずです。 Apple docs から:

リージョン境界を超えた直後にリージョンイベントが発生しない場合があります。偽の通知を防ぐため、iOSは特定のしきい値条件が満たされるまで地域通知を配信しません。具体的には、ユーザーの位置は領域の境界を越え、境界から最小距離だけ移動し、通知が報告されるまで少なくとも20秒間その最小距離に留まる必要があります。

これは、テストハーネスで見ているものとはまったく異なります。シミュレーターでは、デバイスは常にlocationManager:didExitRegionイベントが発生します。

24
memmons

マイケルとネヴァンの答えが好きです。 位置ベースのiOSアプリケーション with 地域監視の開発における私の個人的な経験/意見からより多くの情報を追加し、いくつかの重要なポイントを強調したいです:-

地域の監視を現実的にする

リージョンモニタリングでは、全地球測位システム(GPS)、Wifi、およびその他の技術を使用して、デバイスが監視対象地域の内外にあるかどうかを判断します。私たちの地球は510平方キロメートルであり、約30%が土地(1億4900万km2)であることを忘れないでください。広大なエリアです。最近のMH370欠落ケースを覚えていますか?現在の最先端の技術では、その欠落した平面の推定領域を特定することさえできませんでした。

10メートル半径のみの小さな領域を監視する場合。おそらく、多数のセルタワーとWi-Fi接続エリアがある高密度の都市で動作する可能性があります。ただし、同時に、高層タワーによって信号がブロックされる可能性があります。これにより、数秒/分にわたって信号が失われ、通知の配信が遅延する可能性があります。

そのため、監視する地域の大きさを決定する前に、上記の情報を実際に検討する必要があります。個人的には、半径10メートルは小さすぎると思います。

監視対象地域の数を現実的にする

現在のコアロケーションテクノロジーは、単一のアプリで最大最大20リージョンまでしか監視できません。監視対象地域が互いに近すぎないことも確認してください。

私は個人的に、半径が約100メートル、互いに約200メートル離れた3つの領域をテストしました。運転しているときにこれら3つの地域すべてから通知を受け取ることもありますが、最初の地域からのみ通知を受け取ることもあります。理由は何でしょうか?知りませんでした。領域が互いに近すぎる可能性があります。または、セルタワーは、デバイスが実際に監視対象地域内にないと判断します。

StackOverFlowには、地球上の1800ポイントを監視したい人がいました。彼は非常に非現実的であり、おそらく現在のCore Locationテクノロジー。 リンクユーザーの位置がいくつかのポイントの近くにあるかどうかを確認します

LocationManagerの微調整

アプリが小さな領域を監視する必要がある場合、または位置情報を頻繁に更新する必要がある場合。 Location Managerの潜在的なプロパティは次のとおりです。

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

kCLLocationAccuracyBestForNavigationは、kCLLocationAccuracyBestと比較してより多くのバッテリーを消費します。しかし、それはより正確になります。

iOS 7での領域監視で、異なる監視対象領域で同時にトリガーされる複数の通知があるときに不具合が見つかりました。このグリッチを除去する解決策を見つけました。詳細については、以下をご覧ください。 iOS 7のリージョンモニタリンググリッチ-同時に複数の通知

野心的ではない

小さな地域を監視でき、非常に正確で、地域に足を踏み入れたのと同じ秒数を通知できるアプリを使用したことがあるかもしれません。そして、あなたは彼らと競争するためにまったく同じアプリを開発するインスピレーションを持っています。しかし、舞台裏で何が起こるか理解していますか?彼らが使用している追加技術は何ですか?そして、彼らが協力しているパートナーは何ですか?

私はそれについていくつか調査を行い、彼らが使用している技術のいくつかは公的に利用できないことを発見しました。これらの企業の一部は多額の資金を提供しており、最高のユーザーエクスペリエンスのために最高の位置精度を得るために通信会社にプレミアムを支払うことができます。私はそれがどのように機能するかの詳細を理解していません。ロケーション決定のほとんどは、実際にはモバイル(フロントエンド)ではなく、サーバーエンド(バックエンド)で行われると思います。

そのため、これらの企業が開発したアプリは、最も正確な位置を特定できるだけでなく、バ​​ッテリーを大量に消費しません。

[〜#〜] note [〜#〜]:2セントを共有したいだけです。上記の情報は、私の経験と個人的な意見で構成されています。私はまだCore LocationおよびRegion Monitoringを学習しているため、100%正確ではないかもしれません。

16
Ricky

Michael G. Emmonsに同意し、私の経験も共有したい:

次の画像に示すように、3つの領域でコードをテストしました。

enter image description here

動作の説明:

  • 現在の場所はRegion-1で、上記の3つの地域の監視を開始し、requestStateForRegionを呼び出して、内部に地域が存在するかどうかを判断します。
  • 次に、最初の2つの領域(領域1、および領域2)に対して「Enter」通知を受け取りますが、領域1のみを検出する必要があります。
  • リージョン2に入ると、リージョン3のEnter通知を受け取ります。しかし、ここでリージョン2の通知を取得する必要があります。
  • リージョン1に再び入ると、リージョン3に対してExitイベントが発生し、これが続きます。
  • しかし、最初の2つの地域から少なくとも7Km-10Km以上離れて移動するまで、最初の2つの地域のEnter/Exitイベントを取得しません。

期待される動作:-Enter/Exitイベントは、領域の500メートル前ではなく、領域の境界を越えたとき、または領域内でのみトリガーされます。

私の仮定:

  • すべての実験の後に気づいたのは、3つの地域すべてで「requestStateForRegion」を呼び出すと、
  • 半径5000mの領域内のすべての領域を検出します。そのため、最初の2つの領域を同時に検出します(領域1は半径5000mの円を作成し、領域2は範囲内に入ります。そのため、領域-2も検出されます。 )。
  • ユーザーが10Kmをはるかに超えて移動すると、Exitイベントが呼び出され、ユーザーがこれらの地域に戻ったときに、Enterイベントが発生します。 Aaron Wardle上記で説明したのと同じケース。
  • ユーザーがリージョン1に入ると、リージョン3が検出されます。リージョン3から8〜9 km離れているため、Exitイベントが発生します。ユーザーがリージョン2のルートにいる場合、リージョン3が5000メートル離れていても、リージョン3を検出して発火します。 、地域3のイベントを入力します。

したがって、5000メートル以内のすべての領域が検出され、ユーザーが検出された領域から10 km離れると、Exitイベントが発生します。それ以外の場合、ユーザーが5Kmの範囲内にある場合、Enter/Exitイベントを再度呼び出すことはありません。

誰かがこの問題を修正した場合、またはAppleこの問題に関するドキュメントを更新してください。

6
nidIOS

これは、より重要なコメントのようなものです。から 地域モニタリングとiBeacon

IOSアプリの地域監視サポートのテスト

IOSシミュレーターまたはデバイスでリージョンモニタリングコードをテストするときは、リージョンの境界を越えた直後にリージョンイベントが発生しない可能性があることに注意してください。偽の通知を防ぐため、iOSは特定のしきい値条件が満たされるまで地域通知を配信しません。具体的には、ユーザーの位置が領域の境界を越え、境界から最小距離だけ移動し、通知が報告されるまで少なくとも20秒間その最小距離に留まる必要があります

特定のしきい値距離は、現在利用可能なハードウェアとロケーションテクノロジーによって決まります。たとえば、Wi-Fiが無効になっている場合、リージョンモニタリングの精度は大幅に低下します。ただし、テスト目的では、最小距離は約200メートルであると想定できます。

2
Honey

1メートルでも動作するはずです(そしてiPhone 4S +デバイスでより良く動作します):

startMonitoringForRegion:

(...)

IOS 6では、半径が1〜400メートルの地域は、iPhone 4S以降のデバイスでより適切に機能します。 (iOS 5では、半径が1から150メートルの地域は、iPhone 4S以降のデバイスでより適切に動作します。)これらのデバイスでは、アプリは、平均で3から5分以内に適切な地域入力または地域終了通知の受信を期待できますが、早ければ。

1
Rivera

WWDC 2013 307で何らかのカバレッジを示した@Nevanの回答に基づいて(これには直接対処しませんでした)、私は感覚を持っていますが、場所に到着するために10 m未満の精度を得るための合理的なソリューションを思い付きました-(void)locationManager:didVisit:を実装すると、これはバッテリーの保守性を高めますが、更新頻度は少なくなります。

最初に、半径が0..150mの地域をいくつか用意し、監視を開始します。システムはこれらを約150〜200mでトリガーするように見えるので、実際には問題ではありません。

_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;

CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(location.lat, location.lng) radius:50 identifier:location.name];
[_locationManager startMonitoringForRegion:region];

次に、実装する

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
        if ([enteredRegion.identifier isEqualToString:region.identifier]) {

            self.locationManager.activityType = CLActivityTypeFitness;
            self.locationManager.distanceFilter = 5;
            [self.locationManager startUpdatingLocation];

            break;
        }
    }
}

システムは、アプリが中断されている場合でも、場所のストリームの監視とデリゲートへのレポートを開始します(UIBackgroundModes配列要素を含めるにはlocationが必要です)。

それらの場所の1つが地域の1つの中心内にあるかどうかを確認するには、以下を実装します。

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *firstLocation = [locations firstObject];
    CGFloat const DESIRED_RADIUS = 10.0;

    CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:firstLocation.coordinate radius:DESIRED_RADIUS identifier:@"radiusCheck"];

    for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
        if ([circularRegion containsCoordinate:enteredRegion.center]) {
            [_locationManager stopUpdatingLocation];
            NSLog(@"You are within %@ of %@, @(DESIRED_RADIUS), enteredRegion.identifier);            
            break;
        } else if ([enteredRegion containsCoordinate:circularRegion.center]) {
            NSLog(@"You are within the region, but not yet %@m from %@", @(DESIRED_RADIUS), enteredRegion.identifier);
        }
    }
}

また、実装することもできます。

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    [_locationManager stopUpdatingLocation];
}
1
James Perih

過去数日間、iv'eは開発したアプリのiOS 8.1デバイス(iPhone 5S)でジオフェンシング機能をテストしています。
アプリは、iOS gefenceサービスにいくつかの地域を登録しています。アプリのロジックでは、各ジオフェンスの半径が40〜80メートルである必要があります。
これまでのところ、セルタワーとWifiホットスポットの数が多い地域では、地域に入る際にジオフェンスの検出が十分であることがわかりました。つまり、市街地、ビジネスエリアなどでは、ジオフェンスの検出は正常に機能しています。

残念ながら、セルタワーとWi-Fiネットワークが少ない地域では逆のことが起こります。たとえば、私の近所は幅約1000メートル、高さ500(1KM x 0.5KM)で、セルタワーはありませんがあります。近隣を囲む境界線上には、考えられているセルタワーはほとんどありません。残念ながら、近所の周辺でジオフェンスサービスはnothingを検出します。

言うまでもなく、デバイスでWifiを有効にしてテストしています。

Androidでアプリをテストする場合:Android 4.3、4.4&5.1のジオフェンシングサービスはiOSよりもはるかに良好に動作します。Androidのジオフェンシングサービスは地域の移行を100%検出しませんが、検出します地域の移行の50%〜90%。

私は次のように結論します:セルタワーとWifiホットスポットがもっと多く、if Appleがジオフェンスサービスを改善した場合、iOSデバイスでの検出はAndroidのものと同じくらい良かったでしょう。

0
Omeriko