如何在后台模式下获取当前位置并在后台模式下继续将该位置发送到服务器

Posted

技术标签:

【中文标题】如何在后台模式下获取当前位置并在后台模式下继续将该位置发送到服务器【英文标题】:How to get current location in background mode and keep sending that location to server in background mode 【发布时间】:2019-07-02 10:18:06 【问题描述】:

当应用程序在后台时,我可以将用户的当前位置发送到服务器吗?例如:在我的应用程序中,我想每 2 分钟存储一次用户的当前位置,然后将他的当前位置发送到服务器。当应用程序在后台时我可以这样做吗?我可以在后台模式下向服务器发送位置更新吗?如何?

【问题讨论】:

【参考方案1】:

您可以编辑距离或精度,请确保在功能中检查背景模式的位置。此代码在应用关闭时有效。如果您只想要后台模式,您可以设置计时器并使用 UIBackgroundTask 发送发布请求,如下面的代码。

import UIKit
import Foundation
import CoreLocation

final class LocationManager: NSObject 
    static let shared = LocationManager()

    private var backgroundTask = UIBackgroundTaskIdentifier.invalid
    private let manager = CLLocationManager()    

    func startMonitoring() 
        manager.delegate = self
        manager.pausesLocationUpdatesAutomatically = false        
        manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
        manager.distanceFilter = 1000.0
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    


extension LocationManager: CLLocationManagerDelegate 
    func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) 
        print("LocationManager didStartMonitoringFor")
    

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) 
        print("LocationManager \(error)")
    

    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) 
        print("LocationManager \(error)")
    

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        postLocation(location: locations.first)
    

extension LocationManager 
    private func postLocation(location: CLLocation?) 
        guard let location = location else  return 

        if UIApplication.shared.applicationState == .background 

            backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "test_Location", expirationHandler: 
                UIApplication.shared.endBackgroundTask(self.backgroundTask)
                self.backgroundTask = UIBackgroundTaskIdentifier.invalid
            )

            DispatchQueue.global(qos: .background).async 
                self.postRequest(location: location)  [weak self] in
                    guard let self = self else  return 
                    UIApplication.shared.endBackgroundTask(self.backgroundTask)
                    self.backgroundTask = UIBackgroundTaskIdentifier.invalid
                
            
         else 
            postRequest(location: location)
        

    

    private func postRequest(location: CLLocation, completion: (() -> Void)? = nil) 
       // TODO Send Post
    

【讨论】:

【参考方案2】:

您无法保证获取位置的频率 重大变化的位置服务和监控位置不会每次都唤醒您的应用

如果您需要不时获取用户位置,您可以使用显着更改位置服务(Apple 推荐)-https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/using_the_significant-change_location_service

使用UIBackgroundTask - 发送位置,如果您的位置没有变化或变化不大,请不要发送位置

这篇文章也可以帮到你https://badootech.badoo.com/ios-location-tracking-aac4e2323629

附言 不要在模拟器中检查这个。在我的模拟器中,一切都很好,但在真实设备中,频率唤醒应用程序完全有问题。 用于调试一些日志文件,尽量让日志清晰。

【讨论】:

以上是关于如何在后台模式下获取当前位置并在后台模式下继续将该位置发送到服务器的主要内容,如果未能解决你的问题,请参考以下文章

应用程序处于后台模式时如何在 iOS5 上获取用户位置?

如何永远在后台模式下运行应用程序?

在后台模式和终止模式下获取位置更新 IOS

后台模式下的 iOS 区域监控

在位置后台模式下从核心数据访问数据

iOS iOS9.0 的CoreLocation定位