2013-02-24 44 views
2

我需要在應用程序轉到後臺時繼續獲取用戶的位置更新,並且正如我在Apple的文檔中發現的那樣,這是允許執行的長時間運行的後臺任務之一。我還需要進行一些處理和網絡調用,以便在通知位置更新時向服務器發送一些信息。我正在試圖做的,在廣招,是這樣的:瞭解iOS中用戶位置的後臺跟蹤

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    // Background task   
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSLog(@"Background time remaining: %f seconds (%d mins)", 
    [[UIApplication sharedApplication] backgroundTimeRemaining], 
    (int)([[UIApplication sharedApplication] backgroundTimeRemaining]/60)); 

     // Need to get data from database here 

     // Finished 
     if (bgTask != UIBackgroundTaskInvalid) { 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
     } 

    }); 

    // Start location manager 
    locationManager = [[CLLocationManager alloc] init]; 
    if ([CLLocationManager locationServicesEnabled]) {   
     locationManager.delegate = self; 
     locationManager.distanceFilter = 20; 
     locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
     [locationManager startUpdatingLocation]; 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Want to perform some data processing here, including concurrent tasks 
     // and several network calls to get and send data to server 

     [self locationProcessingCompleted]; 

    }); 
} 

- (void)locationProcessingCompleted 
{ 
    // Check results. If needed, some more data processing and several network 
    // calls to send data to server 

    // Close background task 
    if (bgTask != UIBackgroundTaskInvalid) { 
     [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    } 
} 

我不`噸找到關於位置的服務的長期運行的後臺任務的任何代碼示例,我有一些關於它的幾個問題:

一)是否有必要到dispatch_async隊列中執行所有的後臺代碼?換句話說,applicationDidEnterBackground:中的所有代碼都是異步執行的,包括位置管理器設置?

b)[[UIApplication sharedApplication] backgroundTimeRemaining]正在返回非常長的值。這次不應該在10分鐘左右?

c)我想要做的是:執行初始有限長任務,開始位置更新,然後每次觸發didUpdateToLocation:時執行一些其他有限長度的任務。我在Info.plist中設置了location的值UIBackgroundModes。我的方法是否正確?我是否會無限期地更新位置,然後在每次更新時,我可以執行長度不超過10分鐘的有限長度任務嗎?

請幫我解決這個問題。在此先感謝

回答

2

所有你需要做的是增加「應用程序註冊了位置更新」下的「所需的背景模式」,您可以在文本編輯器或者編輯plist文件,並添加以下代碼,也可以使用Xcode中添加所需的背景模式。

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

didUpdateToLocation方法將被調用(即使您的應用程序在後臺)。您可以在調用此方法的基礎執行任何東西......

快照的Xcode

Snapshot of Xcode

+1

+1這是一個解決方案在iOS 6! – 2013-08-21 12:53:20

+0

這並沒有解決原來的海報問題。設置UIBackgroundModes可以獲得更新,但它不會讓您有足夠的處理時間來實際建立網絡連接並進行實際工作。即使您在位置處理方法中創建了後臺任務,backgroundTimeRemaining仍然是一個巨大的數字,表明它尚未設置。我的經驗是我的後臺操作在幾秒鐘內就被殺死了。 – 2013-10-01 23:18:45

+2

對不起,我不同意,我的一個應用程序在App Store上運行,它在後臺位置更新(網絡訪問,數據操作和發送本地通知等)的基礎上做了很多事情。我猜(可能是錯誤的)你的評論是基於假設/知識而不是這種特殊情況的經驗,或者如果在類似情況下進行處理時遇到問題,你可能做錯了什麼。 – Zee 2013-10-02 12:39:02

0

的按照您在applicationDidEnterBackground分配的LocationManager您提供的代碼,我想向您建議在didFinishLaunchingWithOptions方法中分配LocationManager,然後在applicationDidEnterBackground方法中調用startUpdatingLocation方法。

您可能還需要調用stopUpdatingLocation在applicationWillEnterForeground方法(如果您不需要接收位置更新時,應用程序是在前臺)。

提示:不要啓用與最佳精度的GPS很長一段時間,因爲它會吃掉你的電池非常快(3至4小時內,按我的經驗)。

+0

一個設計問題:如果我還想在前臺應用程序中偵聽位置更新並將它們顯示在地圖上,那麼最好的方法是什麼?我應該在'AppDelegate'中保存'locationManager'實例並以前臺模式向viewControllers發送通知? – AppsDev 2013-03-12 09:49:02

+0

它是否需要在後臺進行位置更新,在AppDelegate中擁有'locationManager'及其委託方法,還是有可能/正確/最好的解決方案,以使用另一個具有自己的'locationManager'和委託方法的類實例,以及那麼讓'AppDelegate'創建它? – AppsDev 2013-03-12 09:53:31

0

聲明:我Cintric

我們也希望能夠在後臺(應用程序已被殺害即使)準確地跟蹤用戶位置的工作。我們花了很長時間解決了這個問題,特別是關注電池消耗。

我們發佈了一篇關於如何解決這個問題的好博客文章。 http://www.blog.cintric.com/?p=121也提供免費的拖放SDK解決方案。使用一行代碼,您可以不斷跟蹤背景中的位置並僅使用1%的電池。此外,您可以設置一個類爲代理,以便您可以將信息發送到您的服務器(包括在後臺而不必使用後臺任務API)。

您也可以下載.framework文件,將其拖放到你的項目,並用一行代碼初始化: [CintricFind initWithApiKey:@"YOUR_API_KEY_HERE" andSecret:@"YOUR_SECRET_HERE"];

你可以免費獲得一個API密鑰。有文件解釋everythin在這裏:https://www.cintric.com/docs/ios