1. 程式人生 > >定期iOS的後臺位置更新-- 相關資料收集,待有時間進行整理

定期iOS的後臺位置更新-- 相關資料收集,待有時間進行整理

1,材料一:(http://codego.net/610454/
我正在寫,需要具有高精確度和低頻率的後臺位置更新的應用程式。該解決方案似乎是一個後臺任務的啟動位置管理器的更新,然後關機。這個問題已經被問過: 我如何獲得一個後臺位置更新每隔n分鐘在我的iPhone應用程式? 位置的應用程式分鐘後每隔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秒至零(在記錄的位置),然後將到期處理程式執行和不產生進一步的位置更新。如何修改上面的程式碼,以便接收在後臺週期性位置更新下去? 更新:我針對iOS的7似乎有證據表明,後臺任務有不同的行為: 從後臺任務啟動位置管理器中的iOS 7

  1. 似乎stopUpdatingLocation是什麼觸發了看門狗的背景,所以我在更換它didUpdateLocation有:
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];

這似乎有效斷電的全域性定位系統。選擇為背景NSTimer然後

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

我做的是定期切換的準確性得到高精度的座標每隔幾分鐘和locationManager一直沒有停止,backgroundTimeRemaining保持在其最大值。從〜每小時10%這減少電池消耗(恆定kCLLocationAccuracyBest在背景中),以每小時1〜2%我的裝置上。
2. 如果你有UIBackgroundModes在你的plist出現,location鍵,那麼你就不需要beginBackgroundTaskWithExpirationHandler方法。這是多餘的。還錯誤地’它(見這裡),但是這毫無意義 CodeGo.net,因為你的plist設定。 同UIBackgroundModes location在plist中的應用程式將繼續在後臺只能無限期只要執行CLLocationManger正在執行。如果你打電話stopUpdatingLocation而在後臺,然後應用程式將停止,將無法再次啟動。 也許你可以呼叫beginBackgroundTaskWithExpirationHandler之前呼叫stopUpdatingLocation然後呼叫後startUpdatingLocation你可以呼叫endBackgroundTask以保持中背景而GPS已停止,但我從來沒有嘗試過的-它只是一個想法。 另一種選擇(我沒試過)是保持位置管理器,同時在後臺執行,但一旦你得到一個準確的位置改變requiredAccuracy財產1000米或更高,以使GPS晶片得到關閉(以儲存電池)。然後10多分鐘後,當你需要另一個位置更新,改變requiredAccuracy回至100m開啟GPS,直到你得到一個準確的位置,重複。 當你呼叫startUpdatingLocation上的位置管理,你必須給它得到一個位置。你不應該呼叫stopUpdatingLocation。我們讓它最多10秒執行,直到我們得到一個非快取的高精度定位。 你需要過濾掉快取的位置,並檢查你確保你的最低要求的精度(見這裡)位置的準確性。你得到的優先個更新可能是10分鐘或10天之久。優先精度你可能3000米。 在顯著位置變化的API來代替.a旦你獲得了顯著變更通知,你可以開始CLLocationManager幾秒鐘獲得高精度的位置。我不能肯定,我已經在顯著位置變更服務。
3. 怎麼樣給它一個嘗試startMonitoringSignificantLocationChanges:API?這肯定與激發頻率較低,準確度是相當不錯的。此外,它有很多其他的優點locationManager的API。 關於這個API很多已經是這個連結
4. 你需要通過新增下列鍵新增的位置更新模式,在你的應用程式

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

didUpdateToLocation方法會被呼叫(即使你的應用程式是在後臺)。您可以在通話的base進行任何東西

蘋果對iOS的規範性在提升了app的品質的同時也帶來了對開發者的限制。翻閱了各種官方文件和資料,得出結論如下:
1、實現後臺定位有2種方式:
standard location service(呼叫CLLocationManager的startUpdatingLocation)
significant-change location service(呼叫CLLocationManager 的startMonitoringSignificantLocationChanges)
2、兩者區別:
前者(startUpdatingLocation)是標準定位,想要在後臺使用必須在info.plist檔案中增加Required background modes屬性,並選擇App registers for location updates值。
前者(startUpdatingLocation)在後臺執行時可能會因為資源問題被系統掛起(suspend)或終止(terminate),但一旦有更新會被喚起,但是當更新時系統任然資源緊張,則會被延遲呼叫委託。如果對於實時性要求高的可能不適合這個,很難控制使用者機器效能狀況。
前者(startUpdatingLocation)如果被使用者手動關閉,就不會再被喚醒。
前者定位基於gps/基站/wifi定位,具體使用哪一種CoreLocation框架有一套自己的規則。
後者(startMonitoringSignificantLocationChanges)是使用基站定位的,所以裝置一定要有電話模組,在plist中可以設定xx屬性來限制可被下載安裝的裝置。
後者(startMonitoringSignificantLocationChanges)不管是在後臺還是使用者手動關閉都會被喚醒呼叫委託,只有3種方法可以阻止它的更新。(1)使用者關閉定位服務(2)使用者關閉對該app的定位服務(3)裝置處於飛航模式或者無法開啟必要的硬體(猜測是定位模組的硬體)。
後者(startMonitoringSignificantLocationChanges)什麼時候更新呢?是在更換基站的時候更新。所以更新頻率與基站密度有關。市區更新頻率較郊區高。所以很多同學說沒有更新是因為還在同一組基站範圍內。
前者較後者耗電且精度高。
3、兩者共性:
兩者都更新位置資訊時都回調相同的委託方法:-(void)locationManager:(CLLocationManager )manager didUpdateLocations:(NSArray )locations;
4、上傳資訊:
由於後臺任務只分配了有限時間執行必要的操作,所以如果在超時之前未完成(比如網路請求),app將會被終止。這裡有一個方法,可以申請額外的10分鐘讓你執行想要的操作,申請後臺任務:beginBackgroundTaskWithExpirationHandler(不詳細說了,使用方法可以查一下資料)。
5、總結:
2種方式各有利弊,根據使用場景而決定,前臺執行的app通常要求準確實時定位,並且執行時間有限,考慮用第一種標準定位,比如導航應用。如果移動速度快(距離變化明顯),長時間定位(監控),可以考慮後者,比如打車應用。
reference:
[1]http://www.mindsizzlers.com/2011/07/ios-background-location/
[2]https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html

這段程式碼可以放在
- (void)applicationWillResignActive:(UIApplication )application
或者
- (void)applicationDidEnterBackground:(UIApplication )application 中,當然,當程式重新被啟用的時候,需要將timer invalidate掉。

UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgTask != UIBackgroundTaskInvalid) {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }
    });
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        testTimer = [NSTimer scheduledTimerWithTimeInterval:(0.01) target:self selector:@selector(doSomeTest) userInfo:nil repeats:YES];
        [testTimer fire];
        [[NSRunLoop currentRunLoop] addTimer:testTimer forMode:NSRunLoopCommonModes];

        [[NSRunLoop currentRunLoop] run];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (bgTask != UIBackgroundTaskInvalid) {
                [app endBackgroundTask:bgTask];
                bgTask = UIBackgroundTaskInvalid;
            }
        });
});