【问题标题】:How to prevent iOS app from being suspended如何防止iOS应用被暂停
【发布时间】:2018-12-26 15:49:42
【问题描述】:

我有一个 iOS 应用程序需要跟踪用户的地理位置以进行研究项目。但是,该应用程序会在几个小时后被 iOS 自动暂停,并且地理位置跟踪停止工作。

地理围栏不够准确,因为它不够准确。

有什么方法可以防止应用被暂停(除非用户手动终止它)?

我想到的一种方法是无限播放无声音乐,并通过MPRemoteCommandCenter在锁屏上显示音乐控件,就像Spotify的工作原理一样。

这会让应用保持活力吗? (因为我相信 Spotify 永远不会被杀死,除非用户手动终止它?)

【问题讨论】:

  • @TarasChernyshenko 我已经实现了所有这些,但它不起作用。在答案中:“应用程序可以进入暂停状态,但是当位置管理器收到新的位置应用程序进入后台状态”时,情况似乎并非如此。我的应用在暂停后停止向服务器发送位置更新(通常在几小时/几天后发生)。

标签: ios swift geolocation mpnowplayinginfocenter mpremotecommandcenter


【解决方案1】:

我有类似的应用程序,它使用用户位置进行跟踪。检查您是否在 info.plist 中拥有所有这些权限。并具体告诉用户您为什么使用位置权限

<key>NSLocationAlwaysUsageDescription</key>
<string>Application needs permission to access your current location. 
</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Application needs permission to access your current location. 
</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>

【讨论】:

  • 是的,这些我都有。即使用户在 iOS 上几天没有打开应用,您的应用也能继续跟踪用户位置吗?
  • 否,如果应用程序已关闭。它不会跟踪。如果应用处于后台,则启用跟踪
  • 但是应用在后台停留时间过长会被挂起。当用户位置发生变化时,您的应用会自动从暂停状态中恢复吗?
  • 如果没有,用户必须定期打开应用程序以防止它被暂停?
  • 它停留在后台,应用程序不断更新位置。到达办公室后,我将在几个小时内分享代码
【解决方案2】:

这是我的代码的一部分。我已删除不需要的部分,因此您可能需要在使用时进行编辑。

import GooglePlaces
import GoogleMaps



class StartRideViewController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate{

var mapView: GMSMapView!
var locationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

let notificationCenter = NotificationCenter.default
    notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
    notificationCenter.addObserver(self, selector: #selector(appMovedToForeGround), name: Notification.Name.UIApplicationDidBecomeActive, object: nil)

}


@objc func appMovedToBackground() {
    print("App moved to background!")
    print(isStartRide)
    if isStartRide == false{
        btn_Share.isHidden = true
        locationManager.allowsBackgroundLocationUpdates = false
        locationManager.stopUpdatingLocation()
    }
}

@objc func appMovedToForeGround() {
    //getMeRidersData()
}

func initiateLocation(){
locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.distanceFilter = 1
        locationManager.startUpdatingLocation()
        //locationManager.startUpdatingHeading()
        locationManager.allowsBackgroundLocationUpdates = true

        //checkForLocationServices()
        checkLocationAuthorizationStatus()

guard let myLatitude = locationManager.location?.coordinate.latitude else{
        return
    }
    guard let myLongitude = locationManager.location?.coordinate.longitude 
else{
        return
    }


    showMap(myLatitude:myLatitude, myLongitude:myLongitude)

}
func showMap(myLatitude:Double, myLongitude:Double){
    let camera = GMSCameraPosition.camera(withLatitude: myLatitude, 
longitude: myLongitude, zoom: 17)
    mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
    //mapView = GMSMapView.map(withFrame: CGRect(x: 0, y: 0, width: 
self.view.frame.width, height: self.view.frame.height - 250), camera: camera)

    mapView?.center = self.view.center
    self.view.addSubview(mapView!)

    mapView.padding = UIEdgeInsetsMake(150, 0, 80, 0)
    mapView.settings.myLocationButton = true
    mapView.delegate = self
    //mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    mapView.isMyLocationEnabled = true
    frameForMapView.addSubview(mapView)

}

func checkLocationAuthorizationStatus() {
    let status = CLLocationManager.authorizationStatus()
    if status == CLAuthorizationStatus.notDetermined{
        print("NotDetermined")
        locationManager.requestWhenInUseAuthorization()
        CLLocationManager.locationServicesEnabled()
        locationManager.requestLocation()
    }else {
        print("Problem with authorization")
    }
}


// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let location: CLLocation = locations.last!
    print("Location: \(location)")
    moveMyImageOnMap()
    print(isStartRide, gotCounterFromLastRide , counter)
    if isStartRide && gotCounterFromLastRide{
        updateMyLocationToDataBase()
    }
}

//    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
//        print(newHeading)
//    }

// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    switch status {
    case .restricted:
        print("Location access was restricted.")
    case .denied:
        print("User denied access to location.")
        // Display the map using the default location.
    case .notDetermined:
        print("Location status not determined.")
    case .authorizedAlways: fallthrough
    case .authorizedWhenInUse:
        print("Location status is OK.")
        if mapView != nil {
            mapView.isMyLocationEnabled = true
        }

    }
}

// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    locationManager.stopUpdatingLocation()
    print("Error: \(error)")

    let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as! String

    let msg :String = "You have denied the app to access your location. Please enable the location services in your settings for the app to get the location";
    let alertController = UIAlertController(title: "Allow \(appName) to access your location while you are using the app?", message: msg, preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.default, handler: nil)

    let settingsAction = UIAlertAction(title: "SETTINGS", style: .default) { (_) -> Void in
        guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                print("Settings opened: \(success)") // Prints true
            })
        }
    }


    alertController.addAction(cancelAction)
    alertController.addAction(settingsAction)

    self.present(alertController, animated: true, completion: nil)
}


}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    相关资源
    最近更新 更多