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

use*_*094 3 sockets cocoa-touch background-process core-location ios

概观

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

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

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

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

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

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

谢谢你的帮助.

ved*_*ucm 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];
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    为了避免将新位置发送到服务器的行为高度不可靠(有时可能有效),您应该事先告诉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
        }   
    }
    
    Run Code Online (Sandbox Code Playgroud)

这样,您就不需要运行计时器了.由于您每次发生重大变化时都会自动唤醒并将更新的位置发送到您的服务器.

当然,如果您想确保在特定时间间隔内发生这种情况,您仍然可以采用设置计时器的方法来开始接收位置更新,并在获得时立即将其发送到服务器.看一下这篇文章,讨论iOS中的背景模式(部分:接收位置更新)以及其他 问题,以了解如何详细地执行此操作.