从SiriKit中的INExtension启动应用程序

8

我希望使用SiriKit开始一项锻炼。开启锻炼需要从应用扩展中打开主应用程序。

苹果提供的INStartWorkoutIntentHandling处理程序的样板代码为:

func handle(startWorkout startWorkoutIntent: INStartWorkoutIntent, completion: (INStartWorkoutIntentResponse) -> Void) {
    let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartWorkoutIntent))
    let response = INStartWorkoutIntentResponse(code: .success, userActivity: userActivity)
    completion(response)
}

我该如何从这里打开我的应用程序?类似于 myapp://workout?action=start&name=pushups。这个答案似乎不相关,因为我没有一个具有extensionContext属性的UIViewController来处理这种扩展类型。
最后一个相关问题:对于其他操作(暂停、结束),我更喜欢不要打开主应用程序,而是仅暂停在主应用程序中运行的锻炼。我可以使用类似的自定义URL来暂停它,但那会打开应用程序,这是一个额外的不必要的步骤。有没有好方法告诉主应用程序从INExtension执行特定操作而不打开应用程序?

苹果已经定义了failureRequiringAppLaunch响应代码,这几乎意味着从苹果的角度来看,这不是一个有效的用例。要求应用程序扩展重新实现我的应用程序的核心用例(例如,锻炼不仅涉及音频)似乎是不合理的。我希望用户能够使用我的自定义词汇表说“Siri,从MY-APP开始进行10分钟的上半身锻炼”,然后它就会在应用程序中开始锻炼。 - Tyler Sheaffer
2个回答

3

对我来说,我可以这样启动应用程序:

let activity  = NSUserActivity(activityType: NSUserActivityTypeBrowsingWeb)
activity.webpageURL = URL(string: "https://mywebsite/...")        
completion(MyIntentResponse(code: .continueInApp, userActivity: activity))

那么这将会在AppDelegate中被调用。

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        if let url = userActivity.webpageURL {
            handleDeeplink(url)
        }
    }
    return false
}

2

留给后人:事实证明,这是在Xcode 8 beta之间逐步推出此功能,它已经在Xcode 8 beta 3中得到解决。他们在这个版本中添加了.continueInApp代码到INStartWorkoutIntentResponseCode,但在Xcode 8 beta 2中没有。该状态代码允许直接传递NSUserActivity(无需使用URL方案)。


顺便说一下,如果你的意图是让用户选择应用程序,你不需要去应用程序开始。你可以通过Siri来完成。 - Ace Green
最终我选择使用.continueInApp,因为我想在我的广告中展示锻炼过程。 - Ace Green
如果我想从RideIntentExtension Handler打开应用程序该怎么办?我在rideIntentExtension中找不到.continueInApp类型。 - Ashish P
@AshishPisey,你找到了不使用continueInApp打开主应用程序的方法吗? - Bubu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接