【问题标题】:iOS best practice for background location updateiOS 后台位置更新最佳实践
【发布时间】:2013-07-31 19:00:40
【问题描述】:

概述

我的公司要求我发布一个可以每两小时检查一次设备位置的应用程序。该应用程序将通过 TCP/IP 套接字将这些位置数据发送到我的服务器,然后根据这些数据接收信息(直接通过相同的 TCP/IP 套接字)。所以我试图让我的应用程序在后台模式下连续运行(实际上,这似乎是 iOS 中的热门话题,它也不适合我的项目)。

问题

为了可靠,实现这一目标的最佳做法是什么?所以,我想知道:

  • 由于我的应用已暂停(= 不活动),Apple 是否允许在 didUpdateToLocation 唤醒时打开套接字以发送位置?
  • 我必须在多长时间内通过我的套接字执行发送/接收任务?
  • 我是否应该使用beginBackgroundTaskWithExpirationHandler 创建一个真正的后台任务并使用 Cocoa 允许的 10 分钟来执行我的发送/接收任务?
  • 是否可以(Apple 允许)要求每 2 小时执行一次 10 分钟的后台任务,无需人工交互(即用户应重新打开应用等)?

到目前为止我取得的成就/发现

  • 我在Info.plist 中添加了location 键,以便在我的应用处于非活动状态时能够运行didUpdateToLocation 处理程序。
  • 当我的应用程序处于前台(= 活动)时,我能够通过打开的套接字发送和接收数据。
  • didUpdateToLocation 被调用时,我尝试检查backgroundTimeRemaining。我得到了一个非常大的结果数字,这似乎很正常,因为此时applicationState 不在UIApplicationStateBackground 中,而是在UIApplicationStateActive 中。

这些点在官方文档中不是很清楚,也没有找到与我具体案例相关的话题。

感谢您的帮助。

【问题讨论】:

  • beginBackgroundTaskWithExpirationHandler 不会创建后台任务,它会将当前线程标记为希望在应用程序处于后台时继续运行的线程。
  • @user1382094:请记住将正确答案标记为您的问题的已接受答案,以防它帮助您。谢谢!

标签: ios cocoa-touch sockets core-location background-process


【解决方案1】:

根据Apple's documentation,您可以使用与您描述的方法非常相似的方法来实现这些。我要做的是类似于this post by mindsizzlers 中解释的内容:

  • 建议在应用进入后台时开启重要的位置更新,这样可以节省电池电量。您可以在应用进入后台时执行此操作:

    - (void) applicationDidEnterBackground:(UIApplication *) application
    {
        // Create the location manager if you do not already have one.
        if (nil == locationManager)
            locationManager = [[CLLocationManager alloc] init];
    
        locationManager.delegate = self;
        [locationManager startMonitoringSignificantLocationChanges];
    }
    

    然后,系统会在位置发生变化时唤醒您的应用,如documentation 中所述。

    如果您让此服务继续运行并且您的应用随后被暂停或终止,则该服务会在新的位置数据到达时自动唤醒您的应用。在唤醒时,您的应用程序将进入后台并给予少量时间来处理位置数据。因为您的应用程序在后台,所以它应该做最少的工作并避免任何可能阻止它在分配的时间到期之前返回的任务(例如查询网络)。如果没有,您的应用可能会被终止。

    为了避免将新位置发送到服务器的操作高度不可靠(有时可能会起作用),您应该提前告诉 iOS 您正在执行一个应该允许运行完成的后台任务。

  • 更改您的位置管理器委托 (didUpdateToLocation) 以处理后台位置更新。

    - (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
    {
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
            // Send the new location to your server in a background task
            // bgTask is defined as an instance variable of type UIBackgroundTaskIdentifier
            bgTask = [[UIApplication sharedApplication] 
            beginBackgroundTaskWithExpirationHandler:
            ^{
                [[UIApplication sharedApplication] endBackgroundTask:bgTask];
            }];
    
            // Make a SYNCHRONOUS call to send the new location to our server
    
            // Close the task
            if (bgTask != UIBackgroundTaskInvalid) {
                [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                bgTask = UIBackgroundTaskInvalid;
            }
    
        } else {
                // Handle location updates in the normal way
        }   
    }
    

这样,您将不需要运行计时器。因为您将被自动唤醒,并在每次发生重大变化时将更新后的位置发送到您的服务器。

当然,如果您想确保在特定的时间间隔内发生这种情况,您仍然可以采用设置计时器的方法来开始接收位置更新,并在收到位置更新后立即将其发送到服务器。看看 this post 谈论 iOS 中的后台模式(部分:接收位置更新)和这个 other questions 详细了解如何执行此操作.

【讨论】:

    猜你喜欢
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多