如何从 watchOS 2 唤醒 iPhone 应用程序?
Posted
技术标签:
【中文标题】如何从 watchOS 2 唤醒 iPhone 应用程序?【英文标题】:How to wake up iPhone app from watchOS 2? 【发布时间】:2015-07-24 19:40:14 【问题描述】:我的应用程序具有非常丰富的网络层,而我的 Apple Watch 应用程序依赖于所有型号。不幸的是,该应用的模块化程度不足以使该层在手表应用中可用。
我通过使用 openParentApplication 解决了这个问题:唤醒 iPhone 应用,执行请求并返回结果。
在 watchOS 2 中,这种方法已经消失,我应该使用 WatchConnectivity。使用它的最佳方法是发送 userInfo 字典。
但是如何唤醒 iPhone 应用程序来处理我的请求?要获得有关新用户信息的通知,我必须使用 WCSessionDelegate,为此我需要一个 WCSession 对象。但是我什么时候应该创建它?以及如何唤醒应用程序?
【问题讨论】:
【参考方案1】:我就此询问了一位 Apple 工程师并得到以下提示:ios 应用程序应该在后台任务中启动。所以以下对我来说非常有效:
UIApplication *application = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid;
dispatch_block_t endBlock = ^
if (identifier != UIBackgroundTaskInvalid)
[application endBackgroundTask:identifier];
identifier = UIBackgroundTaskInvalid;
;
identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock];
将此添加到您的 session:didReceiveMessage:
或 session:didReceiveMessageData:
方法以启动具有三分钟超时的后台任务。
【讨论】:
我不明白“关于以 3 分钟超时启动后台任务”你能解释一下吗? 是的,“beginBackgroundTaskWithExpirationHandler:”方法启动了一个后台任务,默认超时为3分钟。根据 Apple 的说法,这是我们应该启动它们的方式。 所以如果我想在 iPhone 上从 Watch 打开应用程序,它会在 3 分钟后打开? 不,您无法在前台打开应用程序。这将在后台打开 iPhone 应用程序,如果后台没有其他请求,系统将在 3 分钟后终止任务。 有官方回答不能从watch os2在前台打开应用吗?【参考方案2】:以下 Benjamin Herzog 建议的 Swift 版本。值得注意的是,虽然我确实选择将 Watch 发起的工作推送到后台任务,但只要我的应用程序在后台,系统就可以正常唤醒它。在后台任务中执行这项工作似乎不是必需的,但这是最佳做法。
override init()
super.init()
if WCSession.isSupported()
session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
let taskID = self.beginBackgroundUpdateTask()
//Do work here...
self.endBackgroundUpdateTask(taskID)
)
var replyValues = Dictionary<String, AnyObject>()
let status = "\(NSDate()): iPhone message: App received and processed a message: \(message)."
print(status)
replyValues["status"] = status
replyHandler(replyValues)
func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier
return UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler()
func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier)
UIApplication.sharedApplication().endBackgroundTask(taskID)
【讨论】:
不好意思问了,//Do work here...
应该做什么样的工作?
这是您在唤醒设备后放置要执行的代码的位置。
啊,好吧,那我只是有点误解了示例代码.. :),因为你打电话给replyHandler()
“早期”,我有点困惑。【参考方案3】:
在 WatchKit 扩展中,您需要使用 WatchConnectivity WCSession sendMessage API。在扩展中检查 iOS 应用是否可访问,然后发送消息:
let session = WCSession.defaultSession();
if session.reachable
let message = ["foo":"bar"]
session.sendMessage(message, replyHandler: nil, errorHandler: (error) -> Void in
print("send failed with error \(error)")
)
此消息将导致系统在后台唤醒 iOS 应用程序,因此请确保在后台运行时调用的一段 iOS 应用程序代码中设置 WCSession(例如:您不这样做)不想把它放在 UIViewController 的子类的 viewDidLoad) 中以便接收到消息。由于您将请求一些信息,因此您可能希望利用回复块。
这就是您在后台启动 iOS 应用程序的方式,尽管 WatchConnectivity WWDC 会议建议尽可能尝试使用“后台”传输方法。如果您的手表应用程序是只读的,那么您应该能够使用后台传输将 iOS 设备上的任何更改排队,然后它们将在下次运行时传送到手表应用程序。
【讨论】:
感谢您的回答,但是WatchConnectivity的API不是问题,而是后台任务。 (见我上面的回答) 实际上,根据文档,这就是在后台启动 iOS 应用程序并自动访问(无需检查)所需要做的一切。使用 sendMessage 对其进行一次 ping 操作后,您可以以正常方式发送 userInfos 或 applicationContexts。请参阅developer.apple.com/library/ios/documentation/WatchConnectivity/…:-“在 WatchKit 扩展程序处于活动状态和运行状态时调用此方法会在后台唤醒相应的 iOS 应用程序并使其可访问。” 它不会在 watchOS 3 上启动任何东西。session.reachable
是 NO。
手表端可达性一般只有手表应用在前台运行时才为YES
我的意思是代码在 watchOS 3 上运行时不会启动 iOS 应用程序。以上是关于如何从 watchOS 2 唤醒 iPhone 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 WatchOS 3 中的自定义通知操作中打开特定的视图控制器
使用应用程序上下文将数据从 iPhone 发送到 WatchOS 时遇到问题