如何在后台使用随播手表应用启动主iOS应用?

时间:2017-11-27 09:28:17

标签: ios iphone swift watch-os wcsession

情况:

由于我们的用户已将其iOS更新至11和/或WatchOS更新为4,因此当我们的WatchOS应用启动应用时,我们的iOS应用似乎无法触发任何预定的定时器。也许我们在从WatchOS应用程序启动主应用程序时做错了什么。

上下文&代码:

我们的WatchOS应用程序是一个配套应用程序,可让用户通过按下按钮在后台启动/停止我们的iPhone应用程序。我们通过使用:

来做到这一点
func startMainApp() {
    guard WCSession.default().isReachable == true else {
        print("Watch is not reachable")
        return
    }

    var data = [String : AnyObject]()
    data[WatchActions.actionKey()] = NSNumber.init(value: WatchActions.startApp.rawValue as Int)

    WCSession.default().sendMessage(data, replyHandler: { (result: [String : Any]) in
        let resultNumber = result[WatchActions.resultKey()] as? NSNumber
        let resultBool = resultNumber!.boolValue
        if resultBool == true {
            self.setModeActivated()
        } else {
            self.setModeActivationFailed()
        }

    }) { (error: Error) in
        if (error as NSError).code != 7012 {
            print("start app error: \(error.localizedDescription)")
            self.setModeActivationFailed()
        }
    }
}

然后在我们的主应用程序中,我们收到消息并启动我们的基本控制器:

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
    if let actionNumber : NSNumber = message[WatchActions.actionKey()] as? NSNumber {
        if let watchAction : WatchActions = WatchActions(rawValue: actionNumber.intValue) {

            switch(watchAction) {
                case .isAppActive:
                    let result = BaseController.sharedInstance.sleepAndWakeUpController.isAwake()
                     replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])
                return

                case .startApp:
                    AudioController.sharedInstance().playActivatedSound()

                    let isRunningOnForeground = ApplicationStateHelper.isActive()
                    if isRunningOnForeground == false {
                        BaseController.sharedInstance.start(inBackground: true)
                    }
                    let result = true
                    replyHandler([WatchActions.resultKey() : NSNumber.init(value: result as Bool)])

                    DDLogInfo("[APPLE WATCH] [didReceiveMessage] [.startApp]")
                return
            }
        }
    }

    replyHandler([WatchActions.resultKey() : NSNumber.init(value: false as Bool)])
    return
}

一切似乎都像以前一样工作,我们正确获取GPS位置,我们的所有流程都已启动,但是,Timer对象已启动,不会触发。

这在iOS 10之前完美无缺,所以我怀疑这与iOS 11背景状态有关,它们的工作方式不同。但是,我似乎无法找到任何这方面的文件。

额外信息:

  • 在iOS 10上,当我们以这种方式启动主应用程序时,应用程序在iPhone的多任务视图中可见。现在在iOS 11上,它在多任务视图中不可见,但它确实在后台运行。我成功地看到了我在后台安排的本地通知,我可以通过活动代码进行调试,当点击应用程序图标时,应用程序立即可用。
  • 我们的WatchOS应用的部署目标为2.0
  • 通过XCode进行调试,连接设备,使用Debug - >附加到PID或名称 - >输入应用名称。然后从Apple Watch启动我们的应用程序并进行调试。
  • 使用iPhone 6上的WatchOS 4.0在iOS 11.0.3上重现

问题: 从手表应用程序启动主应用程序的最佳方法是什么? iOS 11 / WatchOS 4中有关于背景状态的更改?我可以找到这方面的文件吗?这可能是iOS错误吗?

2 个答案:

答案 0 :(得分:3)

我能提供给你的是确认这种行为确实从iOS 10改为iOS 11.我怀疑iOS 10(及更早版本)的行为是不正确的。即使开发人员依赖这种行为,Apple也没有任何关于改变无意/他们认为不正确行为的疑虑(我很确定我在上一次观看项目中使用了这种行为) )。

事实是,来自观看的消息发起的UIApplication状态为background。除非使用特定的后台执行模式/后台任务,否则计时器不应该在应用程序处于后台运行时运行。这个事实是众所周知的,并且通常在iOS开发人员的职业生涯中很早就遇到过。我猜测,计时器从手表发出时会在后台运行,这是一个错误。

我不知道你的用例,也就是为什么你依赖那些计时器,但你可以做的一件事很简单就是创建一个空的后台任务,它可以让你在推出应用程序时多花一点时间。

var backgroundTask: UIBackgroundTaskIdentifier?
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "app Start Task", expirationHandler: {
    guard let task = backgroundTask else { return }
    UIApplication.shared.endBackgroundTask(task)
})

let timer = Timer(timeInterval: 1, repeats: true) { (timer) in
    print("Running")
}

如果您需要更一致,更长时间运行的解决方案,您可能需要利用您的位置更新作为执行计时器当前所做工作的机会。还有很多其他背景模式可以追求。

您的问题摘要:

问:从手表应用程序启动主应用程序的最佳方式是什么? 答:您提出的代码是启动配套应用的好方法。

问:iOS 11 / WatchOS 4中有关背景状态的变化吗?
答:不,特别是关于计时器。不同的行为可能是一种纠正。

问:我可以找到这方面的文件吗? A:我不能。有时您可以在论坛上通过苹果工程师或通过您的开发者帐户通过代码级支持问题来挤出这些信息,或者转到WWDC。

问:这可能是iOS的错误吗? 答:早期的行为可能是错误。

答案 1 :(得分:1)

当应用关闭且未在后台运行时,位置永远不会在iOS 11中跟踪,它不是iWatchOS 4和iOS 11 Bug。

iOS 11中位置跟踪的更改

  

请点击此文档链接:Changes to location tracking in iOS 11   iOS 11还对现有API进行了一些重大更改。其中一个受影响的区域是位置跟踪。

如果您的应用仅在应用处于前台时使用位置,就像大多数应用一样,您可能根本不需要更改任何内容;但是,如果它是那些在一天中持续跟踪用户位置的应用程序之一,那么您应该在今年夏天预订一些时间来对跟踪和测试可能的使用方案进行一些更改。

  

例如,我们再考虑这两个应用程序;连续的背景位置和重要的位置变化监控应用程序。假设用户使用连续背景位置应用程序进行运行。他们会继续奔跑,他们会回来,他们会一直看到坚固的箭头,当他们看到他们的地图时,他们会看到他们所采取的每一个扭曲和转弯。当他们安装使用重要位置变更监控的应用时,他们会看到相同的东西,一个坚实的箭头。就用户所知,此应用可能会收到与其运行跟踪应用相同数量的信息。因此,如果用户误解我们的信号,我们决定解决此问题的最佳方法是调整我们指示位置使用的方式。

watchOS可以访问iOS应用程序中的许多相同技术;但是,即使有技术可用,您也可能无法像在iPhone上那样使用它。

  

不要将背景执行模式用于技术。通常,Watch应用程序被视为前台应用程序; 它们仅在用户与其中一个接口交互时运行。因此,相应的WatchKit扩展无法利用大多数后台执行模式来执行任务。可能有助于此文档:   Leveraging iOS Technologies for watch