I have background mode on for location services and aiming to send out location (latitude and longitude) to the server every 30 minutes. For now I am printing the same in the console. It seems to work for a while but I am wondering how do I work with NSTimer in this case. And from where should I be calling it?
我有位置服务的后台模式,并且目标是每30分钟向服务器发送一个位置(经度和纬度)。现在我在控制台中打印相同的内容。它似乎工作了一段时间,但我想知道如何在这种情况下使用NSTimer。我应该从哪里打电话呢?
import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
self.locationManager.delegate = self
self.locationManager.startUpdatingLocation() // I know i should be using signification location option here. this is just for testing now.
}
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
self.sendBackgroundLocationToServer(newLocation);
}
func sendBackgroundLocationToServer(location: CLLocation) {
var bgTask = UIBackgroundTaskIdentifier()
bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
UIApplication.sharedApplication().endBackgroundTask(bgTask)
}
println(location.coordinate.latitude)
if (bgTask != UIBackgroundTaskInvalid)
{
UIApplication.sharedApplication().endBackgroundTask(bgTask);
bgTask = UIBackgroundTaskInvalid;
}
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
application.beginBackgroundTaskWithExpirationHandler{}
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
application.beginBackgroundTaskWithExpirationHandler{}
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
application.beginBackgroundTaskWithExpirationHandler{}
}
}
Maybe calling application.beginBackgroundTaskWithExpirationHandler{}
is a bad idea? What options do I go with here?
也许调用application.beginBackgroundTaskWithExpirationHandler {}是一个坏主意?我在这里有什么选择?
3 个解决方案
#1
10
The idea of beginBackgroundTask...
is to start a finite length task so that if the user leaves the app, it will keep running in the background task for some short, finite period of time (3 minutes, I believe). And before the time runs out, you have to call endBackgroundTask
or else the app will be summarily terminated.
beginBackgroundTask ...的想法是启动一个有限长度的任务,这样如果用户离开应用程序,它将继续在后台任务中运行一段短暂的有限时间(我相信3分钟)。在时间用完之前,你必须调用endBackgroundTask,否则应用程序将被立即终止。
So, sadly, the background task mechanism is not really suited for your desired intent. There are, though, a narrow set of special background modes designed for continued background operation outside a narrow set of functions (VOIP, audio, etc.). For more information, see the Implementing Long-Running Tasks section of the App Programming Guide for iOS: Background Execution.
所以,遗憾的是,后台任务机制并不适合你想要的意图。但是,有一组狭窄的特殊背景模式,用于在一组狭窄的功能(VOIP,音频等)之外继续进行后台操作。有关更多信息,请参阅“适用于iOS的应用程序编程指南:后台执行”中的“实现长时间运行任务”部分。
Now, one of those background modes is for a "location" service. So, if that is a central feature of your app, essential for proper function, then you can register for the location
background mode, and your app will continue to run in the background. From there, you can monitor for location updates, and if a sufficient amount of time has elapsed, trigger some process. But if this background location mode is not an essential feature of your app, Apple is likely to reject your app for requesting a background mode that it doesn't need.
现在,其中一种背景模式是“位置”服务。因此,如果这是您的应用程序的核心功能,对于正常功能至关重要,那么您可以注册位置背景模式,您的应用程序将继续在后台运行。从那里,您可以监视位置更新,如果已经过了足够的时间,则触发一些进程。但是,如果此背景位置模式不是您应用的基本功能,Apple可能会拒绝您的应用请求其不需要的后台模式。
By the way, you should be aware that starting standard location services may drain the device battery. You might consider using the battery efficient "significant change" location service. This also has the virtue of automatically waking your app every time the user moves some significant distance (e.g. measured in km; I believe it's triggered by moving to different cell tower).
顺便说一下,您应该知道启动标准位置服务可能会耗尽设备电池。您可以考虑使用电池高效的“重大变化”位置服务。这也具有每次用户移动一些显着距离时自动唤醒您的应用程序的优点(例如以km为单位测量;我相信它是通过移动到不同的手机信号塔触发的)。
#2
8
Couple of notes, since we've been fighting the location issues and struggling with background applications that don't seem to wake us up.
几个笔记,因为我们一直在与位置问题作斗争,并努力应对那些似乎没有唤醒我们的背景应用程序。
-
NSTimer is only good as long as your application is not suspended. Sure, it's in the background, but onlyinasmuchas it is capable of receiving notifications from the iOS (APN, location, ...). Eventually, your timer WILL stop firing while you run in the BG. So, you are relying on one of the BG modes to kick you.
只要您的申请未被暂停,NSTimer就是好的。当然,它在后台,但只有它能够接收来自iOS(APN,位置,...)的通知。最终,当你在BG中跑步时,你的计时器将停止射击。所以,你依靠其中一种BG模式来踢你。
-
If you ARE using CLLocationManager.startUpdatingLocation, you're going to notice that you quit getting those after a bit. Especially when the phone relaxes and tries to sleep. This is because of a poorly documented feature called CLLocationManager.pausesLocationUpdatesAutomatically ... which decides to stop sending those when set to "true" (the DEFAULT setting). You can set this to "false", and you'll continue to get your position updates. Which will pretty much make sure your app does what you are wanting.
如果你正在使用CLLocationManager.startUpdatingLocation,你会注意到你稍后退出了那些。特别是当手机放松并试图入睡时。这是因为一个名为CLLocationManager.pausesLocationUpdatesAutomatically的文档记录不佳...当设置为“true”(DEFAULT设置)时,它决定停止发送它们。您可以将其设置为“false”,然后您将继续获得您的职位更新。这将确保您的应用程序能够满足您的需求。
-
As noted above, you must make sure when you get your locationManager.didUpdateLocations callback that you begin a backgroundTask to keep your application working while you process that information and send your network data. But you seem to understand that.
如上所述,您必须确保在获得locationManager.didUpdateLocations回调时,您开始使用backgroundTask来保持应用程序正常工作,同时处理该信息并发送网络数据。但你似乎明白这一点。
-
Just waking up long enough to "record" a location update isn't so bad. Just make sure you don't spawn your network code unless you've clearly hit your 30 min expectation.
只是醒来足够“记录”位置更新并不是那么糟糕。只要确保你没有产生你的网络代码,除非你明显达到30分钟的预期。
#3
3
try this:
尝试这个:
- Make a singleton for Location Service. Registered it with a
NSNotification
- 为位置服务制作单身人士。注册它与NSNotification
- In
AppDelegate
'swillEnterBackGround
, you send a notification viaNSNotificationCenter
- 在AppDelegate的willEnterBackGround中,您通过NSNotificationCenter发送通知
then, your singleton will start updatingLocation
and send it to server when location's data received.
然后,您的单身人士将开始更新位置,并在收到位置数据时将其发送到服务器。
#1
10
The idea of beginBackgroundTask...
is to start a finite length task so that if the user leaves the app, it will keep running in the background task for some short, finite period of time (3 minutes, I believe). And before the time runs out, you have to call endBackgroundTask
or else the app will be summarily terminated.
beginBackgroundTask ...的想法是启动一个有限长度的任务,这样如果用户离开应用程序,它将继续在后台任务中运行一段短暂的有限时间(我相信3分钟)。在时间用完之前,你必须调用endBackgroundTask,否则应用程序将被立即终止。
So, sadly, the background task mechanism is not really suited for your desired intent. There are, though, a narrow set of special background modes designed for continued background operation outside a narrow set of functions (VOIP, audio, etc.). For more information, see the Implementing Long-Running Tasks section of the App Programming Guide for iOS: Background Execution.
所以,遗憾的是,后台任务机制并不适合你想要的意图。但是,有一组狭窄的特殊背景模式,用于在一组狭窄的功能(VOIP,音频等)之外继续进行后台操作。有关更多信息,请参阅“适用于iOS的应用程序编程指南:后台执行”中的“实现长时间运行任务”部分。
Now, one of those background modes is for a "location" service. So, if that is a central feature of your app, essential for proper function, then you can register for the location
background mode, and your app will continue to run in the background. From there, you can monitor for location updates, and if a sufficient amount of time has elapsed, trigger some process. But if this background location mode is not an essential feature of your app, Apple is likely to reject your app for requesting a background mode that it doesn't need.
现在,其中一种背景模式是“位置”服务。因此,如果这是您的应用程序的核心功能,对于正常功能至关重要,那么您可以注册位置背景模式,您的应用程序将继续在后台运行。从那里,您可以监视位置更新,如果已经过了足够的时间,则触发一些进程。但是,如果此背景位置模式不是您应用的基本功能,Apple可能会拒绝您的应用请求其不需要的后台模式。
By the way, you should be aware that starting standard location services may drain the device battery. You might consider using the battery efficient "significant change" location service. This also has the virtue of automatically waking your app every time the user moves some significant distance (e.g. measured in km; I believe it's triggered by moving to different cell tower).
顺便说一下,您应该知道启动标准位置服务可能会耗尽设备电池。您可以考虑使用电池高效的“重大变化”位置服务。这也具有每次用户移动一些显着距离时自动唤醒您的应用程序的优点(例如以km为单位测量;我相信它是通过移动到不同的手机信号塔触发的)。
#2
8
Couple of notes, since we've been fighting the location issues and struggling with background applications that don't seem to wake us up.
几个笔记,因为我们一直在与位置问题作斗争,并努力应对那些似乎没有唤醒我们的背景应用程序。
-
NSTimer is only good as long as your application is not suspended. Sure, it's in the background, but onlyinasmuchas it is capable of receiving notifications from the iOS (APN, location, ...). Eventually, your timer WILL stop firing while you run in the BG. So, you are relying on one of the BG modes to kick you.
只要您的申请未被暂停,NSTimer就是好的。当然,它在后台,但只有它能够接收来自iOS(APN,位置,...)的通知。最终,当你在BG中跑步时,你的计时器将停止射击。所以,你依靠其中一种BG模式来踢你。
-
If you ARE using CLLocationManager.startUpdatingLocation, you're going to notice that you quit getting those after a bit. Especially when the phone relaxes and tries to sleep. This is because of a poorly documented feature called CLLocationManager.pausesLocationUpdatesAutomatically ... which decides to stop sending those when set to "true" (the DEFAULT setting). You can set this to "false", and you'll continue to get your position updates. Which will pretty much make sure your app does what you are wanting.
如果你正在使用CLLocationManager.startUpdatingLocation,你会注意到你稍后退出了那些。特别是当手机放松并试图入睡时。这是因为一个名为CLLocationManager.pausesLocationUpdatesAutomatically的文档记录不佳...当设置为“true”(DEFAULT设置)时,它决定停止发送它们。您可以将其设置为“false”,然后您将继续获得您的职位更新。这将确保您的应用程序能够满足您的需求。
-
As noted above, you must make sure when you get your locationManager.didUpdateLocations callback that you begin a backgroundTask to keep your application working while you process that information and send your network data. But you seem to understand that.
如上所述,您必须确保在获得locationManager.didUpdateLocations回调时,您开始使用backgroundTask来保持应用程序正常工作,同时处理该信息并发送网络数据。但你似乎明白这一点。
-
Just waking up long enough to "record" a location update isn't so bad. Just make sure you don't spawn your network code unless you've clearly hit your 30 min expectation.
只是醒来足够“记录”位置更新并不是那么糟糕。只要确保你没有产生你的网络代码,除非你明显达到30分钟的预期。
#3
3
try this:
尝试这个:
- Make a singleton for Location Service. Registered it with a
NSNotification
- 为位置服务制作单身人士。注册它与NSNotification
- In
AppDelegate
'swillEnterBackGround
, you send a notification viaNSNotificationCenter
- 在AppDelegate的willEnterBackGround中,您通过NSNotificationCenter发送通知
then, your singleton will start updatingLocation
and send it to server when location's data received.
然后,您的单身人士将开始更新位置,并在收到位置数据时将其发送到服务器。