CLLocationManager startUpdatingLocation()在后台调用时不工作 [英] CLLocationManager startUpdatingLocation() doesn't work when called in background

查看:373
本文介绍了CLLocationManager startUpdatingLocation()在后台调用时不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有,我希望能够启动位置更新时,应用程序已经在后台特定的用例。具体来说,我希望能够为preSS对我的卵石watchapp一个按钮,导致我的同伴iOS应用程序,开始位置更新。

我能够成功启动从我的卵石的位置更新仅在iOS应用无论是在前台或刚刚进入过去的几秒钟内背景(如5?)。几秒钟后,已在后台应用过去了,我再也不能启动的更新。我知道的更新还没开始,因为backgroundTimeRemaining开始递减计数为0(如果没有更新启动,它保持在最大值)。我也有在显示时的位置更新的(_____正在使用你的位置)顶部的蓝色栏和也没有出现这个奇怪〜5个第二临界过后。

我看了几乎所有的SO相关的问题,我已经基本上尝试过的被建议的一切,如右侧开始的位置更新之前启动一个后台任务。我也试着启动后台任务后延迟一个几秒钟的位置更新的开始,那也不行。

但奇怪的是,我也有一个苹果关注的应用程序,做同样的事情,卵石应用程序,苹果的手表是能够启动位置更新没有失败所有的时间。也许它unsuspends的iOS应用苹果观察可以做一些特别的东西?

这是iOS上的9。

任何形式的帮助是AP preciated,我会尝试任何的建议。

更新:我放在一起,演示该问题的快速示例应用程序。
在code下面贴出来,也可以从GitHub下载项目:
https://github.com/JessicaYeh/BackgroundLocationTest

如果你尝试一下,你可以看到,延迟设置为2秒钟的作品,但是当延迟较长(如10秒),更新不会启动。

  //
// AppDelegate.swift
// BackgroundLocationTest
//
//创建者杰西卡星爷在16年2月18日。
//版权所有©2016年叶。版权所有。
//进口的UIKit
进口CoreLocation@UIApplicationMain
一流的AppDelegate:UIResponder,UIApplicationDelegate {    VAR窗口:一个UIWindow?    让我们的LocationManager = CLLocationManager(CLLocationManager为)
    VAR backgroundTask:UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    VAR定时器:的NSTimer?    FUNC应用程序(应用程序:UIApplication的,didFinishLaunchingWithOptions launchOptions:[NSObject的:AnyObject]) - GT;布尔{        debugPrint(__ FUNCTION__)        //设置位置管理器
        locationManager.delegate =自
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.allowsBackgroundLocationUpdates =真        返回true
    }    @objc FUNC checkBackgroundTimeRemaining(){
        debugPrint(UIApplication.sharedApplication()。backgroundTimeRemaining)
    }    @objc FUNC endBackgroundTask(){
        如果self.backgroundTask!= {UIBackgroundTaskInvalid
            UIApplication.sharedApplication()。endBackgroundTask(self.backgroundTask)
            self.backgroundTask = UIBackgroundTaskInvalid
        }
    }    FUNC applicationWillResignActive(应用程序:的UIApplication){
        debugPrint(__ FUNCTION__)
    }    FUNC applicationDidEnterBackground(应用程序:的UIApplication){
        debugPrint(__ FUNCTION__)        //取消旧定时器和后台任务
        计时器?.invalidate()
        endBackgroundTask()        //开始一个新的后台任务
        backgroundTask = UIApplication.sharedApplication()。beginBackgroundTaskWithExpirationHandler {
            self.endBackgroundTask()
        }        //开始更新位置
//让delaySec = 2.0 //成功启动位置更新
        让delaySec = 10.0 //不启动位置更新
        让delayTime = dispatch_time(DISPATCH_TIME_NOW,Int64的(delaySec *双(NSEC_PER_SEC)))
        dispatch_after(delayTime,dispatch_get_main_queue(),{
            debugPrint(试图开始更新位置)
            self.locationManager.startUpdatingLocation()
        })        //继续检查,每3秒多的时间背景程序已经如何离开
        定时器= NSTimer.scheduledTimerWithTimeInterval(3.0,目标:自我,选择:选择(checkBackgroundTimeRemaining),用户信息:无,重复:真)
    }    FUNC applicationWillEnterForeground(应用程序:的UIApplication){
        debugPrint(__ FUNCTION__)
    }    FUNC applicationDidBecomeActive(应用程序:的UIApplication){
        debugPrint(__ FUNCTION__)
    }    FUNC applicationWillTerminate(应用程序:的UIApplication){
        debugPrint(__ FUNCTION__)
    }
}扩展的AppDelegate:CLLocationManagerDelegate {
    FUNC的LocationManager(经理:CLLocationManager,didUpdateLocations地点:[CLLocation]){
        debugPrint(__ FUNCTION__)
    }}


解决方案

好吧,我做你试过没有什么,但要确保你已经打开了位置更新你的目标的能力(能力 - >后台模式)而且,适用于iOS 9.0,补充一点:

 如果(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@9.0)){    self.locationManager.allowsBackgroundLocationUpdates = YES;
}

和更改行:

  locationManager.requestWhenInUseAuthorization()

  locationManager.requestAlwaysAuthorization()。

祝你好运!

I have a particular use case where I want to be able to start location updates when the app is already in the background. Specifically, I want to be able to press a button on my Pebble watchapp, and that causes my companion iOS app to begin location updates.

I am able to successfully start the location updates from my Pebble only if the iOS app is either in the foreground or has just entered the background within the past few seconds (like 5?). After a few seconds has passed with the app in the background, I can no longer start the updates. I know that the updates haven't started, since the backgroundTimeRemaining starts counting down to 0 (and if the updates did start, it stays at the max value). I also have the blue bar at the top that shows when location updates are on ("_____ is Using Your Location") and that also fails to show up after this weird ~5 second threshold has passed.

I've looked at almost all of the related questions on SO, and I've already tried basically everything that's been suggested, such as starting a background task right before starting the location updates. I've also tried delaying the start of the location updates by a couple seconds after starting the background task, and that doesn't work either.

The strange thing is, I also have an Apple Watch app that does the same things as the Pebble app, and the Apple Watch is able to start the location updates without fail all the time. Maybe the Apple Watch can do something special where it unsuspends the iOS app?

This is on iOS 9.

Any kind of help is appreciated, I'll try anything that's suggested.

Update: I put together a quick sample app that demonstrates the issue. The code is posted below, or you can download the project from GitHub: https://github.com/JessicaYeh/BackgroundLocationTest

If you try it out, you can see that setting the delay to 2 seconds works, but when the delay is longer (like 10 seconds), the updates don't start.

//
//  AppDelegate.swift
//  BackgroundLocationTest
//
//  Created by Jessica Yeh on 2/18/16.
//  Copyright © 2016 Yeh. All rights reserved.
//

import UIKit
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    let locationManager = CLLocationManager()
    var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    var timer: NSTimer?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        debugPrint(__FUNCTION__)

        // Setup location manager
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.allowsBackgroundLocationUpdates = true

        return true
    }

    @objc func checkBackgroundTimeRemaining() {
        debugPrint(UIApplication.sharedApplication().backgroundTimeRemaining)
    }

    @objc func endBackgroundTask() {
        if self.backgroundTask != UIBackgroundTaskInvalid {
            UIApplication.sharedApplication().endBackgroundTask(self.backgroundTask)
            self.backgroundTask = UIBackgroundTaskInvalid
        }
    }

    func applicationWillResignActive(application: UIApplication) {
        debugPrint(__FUNCTION__)
    }

    func applicationDidEnterBackground(application: UIApplication) {
        debugPrint(__FUNCTION__)

        // Cancel old timer and background task
        timer?.invalidate()
        endBackgroundTask()

        // Start a new background task
        backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
            self.endBackgroundTask()
        }

        // Start updating location
//        let delaySec = 2.0 // successfully starts location update
        let delaySec = 10.0 // doesn't start location update
        let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delaySec * Double(NSEC_PER_SEC)))
        dispatch_after(delayTime, dispatch_get_main_queue(), {
            debugPrint("Attempting to start updating location")
            self.locationManager.startUpdatingLocation()
        })

        // Keep checking every 3 sec how much background time app has left
        timer = NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: Selector("checkBackgroundTimeRemaining"), userInfo: nil, repeats: true)
    }

    func applicationWillEnterForeground(application: UIApplication) {
        debugPrint(__FUNCTION__)
    }

    func applicationDidBecomeActive(application: UIApplication) {
        debugPrint(__FUNCTION__)
    }

    func applicationWillTerminate(application: UIApplication) {
        debugPrint(__FUNCTION__)
    }
}

extension AppDelegate: CLLocationManagerDelegate {
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        debugPrint(__FUNCTION__)
    }

}

解决方案

Well, I don't exactly what you tried, but make sure you've turned on the Location updates on your target's Capabilities (Capabilities -> Background Modes) and also, for iOS 9.0, add this:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0")) {

    self.locationManager.allowsBackgroundLocationUpdates = YES;
}

and change the line:

locationManager.requestWhenInUseAuthorization() 

to:

locationManager.requestAlwaysAuthorization().

Good luck!

这篇关于CLLocationManager startUpdatingLocation()在后台调用时不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆