3

概述

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

问题

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

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

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

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

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

谢谢你的帮助。

4

1 回答 1

5

根据Apple 的文档,您可以使用与您描述的方法非常相似的方法来实现这些。我要做的类似于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];
    }
    

    然后,系统将在位置更改时唤醒您的应用程序,如文档中所述。

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

    为了避免将新位置发送到服务器的操作高度不可靠(有时可能会起作用),您应该提前告诉 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
        }   
    }
    

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

当然,如果您想确保这发生在特定的时间间隔内,您仍然可以采用设置计时器的方法来开始接收位置更新,并在收到位置更新后立即将其发送到服务器。看看这篇关于iOS 中背景模式的帖子(部分:接收位置更新)和其他 问题,以了解如何详细了解如何执行此操作。

于 2013-07-31T13:31:30.313 回答