簡體   English   中英

iOS Geofence CLCircularRegion監控。 locationManager:didExitRegion似乎沒有按預期工作

[英]iOS Geofence CLCircularRegion monitoring. locationManager:didExitRegion does not seem to work as expected

我目前正在嘗試讓我的應用程序使用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區域等提供代碼,因為我知道當我離監控區域超過100米時可以工作。

這是應用程序的屏幕截圖,當我距離地圖上的紫色位置超過10米時,確實的出口區域事件不會觸發,但是如果我將我的位置切換到倫敦則會觸發它並且當我設置我的位置時回到目前藍色位置的地方它也會發射。

示例區域

有沒有人知道最小區域半徑是否有限制,或者我做錯了什么。

謝謝亞倫

我認為區域監測不會對這么小的半徑有效。

  • GPS芯片和kCLLocationAccuracyBestForNavigation的最佳精度通常只有10米。
  • Apple表示(在位置和地圖PG中 )區域的最小距離應假設為200米
  • 我聽說區域監控正在使用WiFi來獲取它的位置(這對於省電是有意義的)。 WiFi精度更像是20m-100m。 我不確定如何使用其他應用程序使用背景位置(即使用GPS)會影響這一點。 也許,位置管理員會共享信息以提高准確性。
  • 區域監控可能需要30秒才能在區域內進行一次點火,並且在離開區域后需要幾分鍾才能點火(以防止位置故障觸發)。
  • 當首次引入區域監測時,他們表示只能在100米區域內工作,而任何較小的區域都會被抬高。 這可能仍然會發生。
  • 有一個不推薦使用的方法startMonitoringForRegion:desiredAccuracy:它允許您指定區域邊界之后的距離以開始生成通知。 據推測,這個功能已經進入了startMonitoringForRegion:但仍然存在。 一個10米的區域最終可能會有10米的緩沖區。
  • 如果要執行此操作,請在要監視的位置周圍指定一個更大的區域,當設備在該區域喚醒時,啟動后台位置更新(GPS)並使用CLCircularRegion -containsCoordinate:在設備位於其中時觸發手動10米。 該方法由Apple正式批准(參見WWDC 2013 Session 307)。

來自CLCircularRegion文檔:

請記住,位置管理器在跨越區域邊界時不會立即生成通知。 相反,它應用時間和距離標准來確保交叉是有意的並且應該真正觸發通知。 因此,選擇適當的中心點和半徑,並給您足夠的時間提醒用戶。

位置和地圖PG

區域事件可能不會在跨越區域邊界后立即發生。 為防止虛假通知,iOS在滿足某些閾值條件之前不會發送區域通知。 具體而言,用戶的位置必須越過區域邊界,遠離邊界移動最小距離,並在報告通知之前保持在該最小距離至少20秒。
特定閾值距離由當前可用的硬件和定位技術確定。 例如,如果禁用Wi-Fi,則區域監控的准確性要低得多。 但是,出於測試目的,您可以假設最小距離約為200米。

凱文·麥克馬洪(Kevin McMahon)這篇文章中進一步深入了解了這篇文章 ,他在2012年WWDC實驗室向核心位置工程師詢問了區域監測情況。此信息在此期間會發生變化,但有關區域類別的部分很有意思。 這是一個編輯:

精細區域(0 - 150米)
- 在100米的地板上,這個類別的范圍實際上是100-150米。
- 對於區域而言,此大小的性能在很大程度上取決於與位置相關的硬件
- 在跨越區域邊界后,Core Location檢測並調用適當的委托方法所花費的時間大約為2-3分鍾。
- 一些開發人員已經獨立地發現,較小的區域會看到更快的回調,並且會聚集較小的區域以覆蓋一個大區域以改善區域交叉通知。

這似乎是CLLocationManager一個錯誤。 我已經使用各種區域半徑配置和locationManager:didExitRegion進行了大量測試locationManager:didExitRegion不會以預期的方式觸發。 這似乎是一個相當討厭的錯誤或區域監控根本沒有像文檔建議那樣發生。 我有任何想要它的人都可以使用測試工具:

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

在模擬器中運行它並通過在iOS模擬器菜單中選擇Debug - > Location - > Freeway Drive來開始測試。 您看到的數字是距受監控區域中心的距離。 設備位於受監控區域內時背景顏色為綠色,區域外時背景顏色為紅色。 距離下方的文本是事件日志。

在此輸入圖像描述

運行應用程序后,您應該看到locationManager:didExitRegion從受監控區域5319米處開火。 該路線將每37分鍾循環一次,您將看到離開該區域的設備總是在5319米處。

我已經提交了Apple雷達(17064346) 一旦我收到他們的回復,我會更新這個答案。 至少那時我們會從規范來源獲得一些意見。

這是發送給Apple的詳細文本:

使用iOS模擬器以及iPhone 5S上的測試應用程序,CLLocationManager似乎不會以預期的方式觸發didExitRegion回調。 無論被監視的圓形區域的半徑如何,在達到約5000米的閾值之前不會發生回調。

重現步驟:
1.運行附加的應用程序
2.通過在iOS模擬器中選擇Debug - > Location - > Freeway Drive來啟動區域跟蹤
3.監控應用程序。 大#表示距監視區域中心的距離。
在大約190秒和5300米后,退出地點終於開火了。

該問題似乎與該地區的規模無關。 根據Apple文檔 ,甚至支持小區域:

在iOS 6中,半徑在1到400米之間的區域在iPhone 4S或更高版本的設備上運行得更好。 (在iOS 5中,半徑在1到150米之間的區域在iPhone 4S和更高版本的設備上運行得更好。)在這些設備上,應用程序可以在3到5分鍾內平均接收輸入的適當區域或區域退出通知,如果不是更快。

雖然地區事件不會立即發生,但它們應該很快發生。 來自Apple文檔

區域事件可能不會在跨越區域邊界后立即發生。 為防止虛假通知,iOS在滿足某些閾值條件之前不會發送區域通知。 具體而言,用戶的位置必須越過區域邊界,遠離邊界移動最小距離,並在報告通知之前保持在該最小距離至少20秒。

這完全不是我在測試工具中看到的。 在模擬器上,在發生locationManager:didExitRegion事件之前,設備將始終距離該區域5000米以上。

我喜歡Michael和Nevan的答案。 我想從個人經驗/意見中添加更多信息,以開發基於位置的iOS應用程序區域監控 ,並重點介紹一些要點: -

對區域監測要切合實際

區域監控使用全球定位系統(GPS),Wifi和其他技術來確定設備是在監控區域內還是外。 不要忘記,我們的地球是510平方公里,約30%是土地(1.49億平方公里)。 這是一個巨大的領域。 還記得最近的MH370丟失案嗎? 我們目前最先進的技術甚至無法確定丟失飛機的估計區域。

如果要監視半徑僅為10米的小區域。 它可能在一個高密度城市內工作,有很多手機信號塔和無線連接區域。 但與此同時,信號可能被高層塔阻擋,這可能導致信號丟失幾秒/分鍾,從而導致通知延遲。

因此,在決定要監控的區域有多大之前,您必須考慮上述信息。 我個人認為10米半徑太小了。

在監測區域數量上要切合實際

當前的核心位置技術只能在一個應用程序上監控最多20個區域 確保受監控的區域也不要太靠近。

我親自測試了3個半徑約100米的區域,這些區域彼此相差約200米。 有時,當我開車經過時,我可以收到來自所有這3個地區的通知,但有時候,我只能從第一個地區收到通知。 可能是什么原因? 我不知道。 這些地區可能彼此太靠近。 或者手機信號塔決定我的設備實際上並不在受監控區域內。

StackOverFlow上有一個人想監視我們地球上的1800點。 不要像他一樣,因為他是非常不現實的,可能不理解當前Core Location技術的局限性。 鏈接檢查用戶位置是否接近某些點

微調LocationManager

如果您的應用需要監控小區域或需要經常更新位置。 以下是您的位置管理器的潛在屬性。

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

kCLLocationAccuracyBestForNavigation會消耗更多的電池比較kCLLocationAccuracyBest 但是,它會更准確。

當在不同的受監控區域同時觸發多個通知時,我發現iOS 7中的區域監控存在故障。 我找到了一個解決這個故障的解決方案。 有關詳細信息,請訪問: iOS 7上的區域監控故障 - 同時發出多個通知

不要過於雄心勃勃

您可能已經使用了一些可以監控小區域的應用程序,並且非常准確,並且能夠在您踏入該區域的同一時間通知您。 而且你有靈感來開發完全相同的應用程序來與它們競爭。 但是你明白幕后發生了什么嗎? 他們使用了哪些其他技術? 和他們合作的合作伙伴是什么?

我對此做了一些研究,發現他們使用的一些技術不公開。 其中一些公司資金雄厚,可以向電信公司支付額外費用,以便獲得最佳的位置准確性,從而獲得最佳用戶體驗。 我不明白它是如何工作的細節。 我相信大多數位置確定實際上是在服務器端(后端),而不是移動(前端)。

因此,這些公司開發的應用程序不僅可以精確定位最准確的位置,而且不會消耗大量電池。

注意 :我只想分享我的2美分。 以上信息包括我的經驗和個人意見。 它可能不是100%准確,因為我仍在學習核心位置區域監控

我同意Michael G. Emmons的觀點 ,並希望分享我的經驗:

我用三個區域測試了我的代碼,如下圖所示:

在此輸入圖像描述

解釋行為:

  • 我當前的位置是Region-1,我開始監控上述三個區域,並調用requestStateForRegion,以確定內部是否有任何區域,我當前站在哪里。
  • 然后我得到“輸入”通知,前兩個區域(區域1和區域2),但它應該只檢測區域-1。
  • 現在當我進入region-2時,我收到了region-3的Enter通知。 但我應該在這里獲得region-2的通知。
  • 現在,當我再次進入region-1時,我為區域-3觸發了Exit事件,並且這仍然繼續。
  • 但我沒有得到前兩個區域的任何進入/退出事件,直到我距離前兩個區域至少超過7Km-10Km。

預期行為: - 只有當我越過區域邊界或區域內時,才會觸發進入/退出事件,而不是在距離該區域500米之前。

我的假設:

  • 在所有實驗之后我注意到的是,當我為所有三個區域調用“requestStateForRegion”時,
  • 它檢測半徑為5000m的區域內的所有區域,這就是為什么它同時檢測前兩個區域(區域-1創建一個半徑為5000m的圓,區域-2在其范圍內,這就是為什么區域-2也被檢測到) )。
  • 當用戶移動距離遠超過10Km時,將調用其Exit事件,當用戶返回這些區域時,將觸發其Enter事件。 與上面Aaron Wardle解釋的情況相同。
  • 正在檢測Region-3,因為當用戶進入region-1時,即。 距離region-3 8-9km,因此為此事件觸發了Exit事件,當用戶在區域2的路線上時,即使區域-3距離5000米,仍然會檢測到區域-3並且發射,輸入region-3的事件。

因此我認為5000米內的所有區域都被檢測到,並且當用戶從檢測到的區域移開10公里時,其Exit事件將被觸發。 否則,如果用戶在5Km范圍內,它將永遠不會再次調用它進入/退出事件。

如果有人解決了這個問題,請更新我,或者Apple在任何地方解決此問題。

這更像是一個重要的評論。 來自區域監控和iBeacon

測試iOS應用程序的區域監視支持

在iOS模擬器或設備上測試區域監控代碼時,請注意區域事件可能不會在跨越區域邊界后立即發生。 為防止虛假通知,iOS在滿足某些閾值條件之前不會發送區域通知。 具體而言,用戶的位置必須越過區域邊界,遠離邊界移動最小距離,並在報告通知之前保持在該最小距離至少20秒

特定閾值距離由當前可用的硬件和定位技術確定。 例如,如果禁用Wi-Fi,則區域監控的准確性要低得多 但是,出於測試目的,您可以假設最小距離約為200米

聽起來甚至1米應該可以工作(並且在iPhone 4S +設備上工作得更好):

startMonitoringForRegion:

(......)

在iOS 6中,半徑在1到400米之間的區域在iPhone 4S或更高版本的設備上運行得更好。 (在iOS 5中,半徑在1到150米之間的區域在iPhone 4S和更高版本的設備上運行得更好。)在這些設備上,應用程序可以在3到5分鍾內平均接收輸入的適當區域或區域退出通知,如果不是更快。

根據@ Nevan的答案,這表明在WWDC 2013 307中有一些報道(沒有直接解決這個問題),我提出了一個合理的解決方案,讓到達一個位置的精度<10m,盡管我有一種感覺實現-(void)locationManager:didVisit:可能會使這更加電池保守,但會提供更少的更新。

首先,有一些半徑為0..150米的區域,並開始監測。 並不重要,因為系統似乎在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數組元素),系統也會開始監視並向您的委托報告位置流。

要檢查其中一個位置是否位於您所在地區的中心,請執行以下操作:

-(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];
}

在過去的幾天里,我一直在測試我的iOS 8.1設備(iPhone 5S)上的地理圍欄功能,以便開發一款應用程序。
該應用程序正在向iOS gefence服務注冊少數幾個區域。 應用程序的邏輯需要每個地理圍欄半徑在40到80米之間。
到目前為止,我看到在具有更多蜂窩塔和Wifi熱點的地區,地理圍欄檢測在進入地區時已經足夠好了。 也就是說,在城鎮地區,商業區等地區,地理圍欄檢測工作正常。

不幸的是,相反的情況發生在少數蜂窩塔和wifi網絡的地區。 例如,我的社區寬約1000米,高度約為500米(1KM x 0.5KM),其中沒有單元塔 在附近的周邊,人們認為很少有蜂窩塔。 不幸的是,在附近的周邊,地理圍欄服務什么都沒檢測到。

毋庸置疑,我正在測試設備上啟用的Wifi。

當我在Android上測試我的應用程序時:Android 4.3,4.4和5.1上的地理圍欄服務比在iOS上運行得更好。 Android的地理圍欄服務沒有檢測到100%的區域轉換,但它檢測到50%-90%的區域轉換。

我得出以下結論:如果有更多的手機信號塔和Wifi熱點,如果蘋果公司改進了地理圍欄服務,那么iOS設備上的檢測就會像Android一樣好。

地理圍欄通過檢測從一個小區網絡塔移動到另一個小區網絡塔的用戶來工作。

因此,您可以定義的最小區域取決於細胞塔的接近程度。

在購物中心或體育場內,它可能能夠做10米 - 牢房塔通常非常靠近。 在區域內,任何小於100公里的地方都可能失敗。

如果您需要更小的區域,則需要使用藍牙而不是手機信號塔(iBeacons)。 如果目標區域中有藍牙低能耗設備,您可以將范圍設置為非常短(厘米)或相當大(最多30米左右)。 請注意,這一切都取決於iBeacon硬件的質量,有些比其他硬件好。

不幸的是,藍牙(4.0或更新版本)和蜂窩網絡塔是監控位置而不會顯着耗盡電池的唯一方法。 即使屏幕關閉,保持GPS激活以檢查10米邊界也會在約2小時內將電池從完全耗盡到完全平坦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM