用于后台位置更新的iOS最佳做法

时间:2013-07-31 09:55:28

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

概述

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

问题

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

  • 由于我的应用已暂停(=无效),Apple是否允许在didUpdateToLocation唤醒时允许打开套接字发送位置?
  • 我需要多长时间才能通过套接字执行发送/接收任务?
  • 我应该使用beginBackgroundTaskWithExpirationHandler创建真正的后台任务,并使用Cocoa允许的10分钟来执行我的发送/接收任务吗?
  • 可能(并允许Apple)每2小时要求一次10分钟的后台任务,没有人工干预(即用户应该重新打开应用程序等)?

到目前为止我取得的成就

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

这些要点在官方文档中并不十分清楚,我没有找到与我的具体案例相关的主题。

感谢您的帮助。

1 个答案:

答案 0 :(得分:5)

根据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您正在执行应该允许运行完成的后台任务。 / p>

  • 更改您的位置管理员委托(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如何做到这一点。