You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS15 SwiftUI VPN应用Siri快捷方式连接/断开功能配置求助

iOS 15 VPN应用Siri快捷方式配置方案

问题背景

开发iOS 15目标版本的VPN应用,需实现Siri快捷功能:用户打开YouTube等特定App时,自动触发VPN连接/断开操作。已通过NSUserActivity捐赠快捷方式并配置Info.plist的activityTypes,但功能未生效,现有代码见下方。

现有代码问题排查

  1. 捐赠时机不合理:仅在App启动时执行一次捐赠,系统难以关联用户实际行为,无法有效触发场景预测
  2. Activity配置缺失:未添加场景关联的关键词或目标App标识,Siri无法识别触发场景
  3. 后台操作权限不足:VPN连接/断开操作在后台执行时,未延长App后台生命周期,可能被系统终止
  4. Info.plist配置需验证:需确保NSUserActivityTypes数组包含正确的ActivityType字符串

修正后的可行配置方案

1. 调整捐赠时机,关联用户实际操作

将快捷方式捐赠逻辑从App启动时,移至用户手动完成VPN连接/断开操作的回调中,确保系统收录用户真实行为:

// 示例:VPN连接成功后调用
func vpnDidConnect() {
    donateConnectVPNShortcut()
}

// 示例:VPN断开成功后调用
func vpnDidDisconnect() {
    donateDisconnectVPNShortcut()
}

2. 完善NSUserActivity场景关联配置

为Activity添加关键词和目标App标识,帮助Siri识别触发场景(如YouTube):

private func donateConnectVPNShortcut() {
    let title = NSLocalizedString("siriShortcutConnectVPNTitle", comment: "Title for Connect VPN Shortcut")
    let activity = NSUserActivity(activityType: Constants.connectVPNSiriActivityType)
    
    activity.title = title
    activity.suggestedInvocationPhrase = title
    activity.isEligibleForSearch = true
    activity.isEligibleForPrediction = true
    activity.persistentIdentifier = NSUserActivityPersistentIdentifier(Constants.connectVPNSiriActivityType)
    // 添加场景关联关键词和目标App Bundle ID
    activity.keywords = Set(["YouTube", "视频", "VPN连接"])
    activity.userInfo = ["triggerBundleID": "com.google.ios.youtube"]
    
    activity.becomeCurrent()
}

private func donateDisconnectVPNShortcut() {
    let title = NSLocalizedString("siriShortcutDisconnectVPNTitle", comment: "Title for disconnect VPN Shortcut")
    let activity = NSUserActivity(activityType: Constants.disconnectVPNSiriActivityType)
    
    activity.title = title
    activity.suggestedInvocationPhrase = title
    activity.isEligibleForSearch = true
    activity.isEligibleForPrediction = true
    activity.persistentIdentifier = NSUserActivityPersistentIdentifier(Constants.disconnectVPNSiriActivityType)
    activity.keywords = Set(["YouTube", "视频", "VPN断开"])
    activity.userInfo = ["triggerBundleID": "com.google.ios.youtube"]
    
    activity.becomeCurrent()
}

3. 验证Info.plist配置

确保NSUserActivityTypes数组包含你的ActivityType常量对应的字符串(需为反向域名格式,如com.yourcompany.vpn.connect):

<key>NSUserActivityTypes</key>
<array>
    <string>com.yourcompany.vpn.connect</string>
    <string>com.yourcompany.vpn.disconnect</string>
</array>

4. 优化后台操作逻辑,延长生命周期

处理NSUserActivity时,使用后台任务延长App生命周期,确保VPN操作完成:

func application(_ application: UIApplication, 
                 continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
    var backgroundTask: UIBackgroundTaskIdentifier = .invalid
    backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "VPNSiriOperation") {
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = .invalid
    }

    defer {
        if backgroundTask != .invalid {
            UIApplication.shared.endBackgroundTask(backgroundTask)
        }
    }
    
    if userActivity.activityType == Constants.connectVPNSiriActivityType {
        guard let status = packetTunnelManager.status, status == .disconnected else { return true }
        Task {
            do {
                try await packetTunnelManager.start()
            } catch {
                print("Siri触发VPN连接失败: \(error.localizedDescription)")
            }
        }
    } else if userActivity.activityType == Constants.disconnectVPNSiriActivityType {
        guard let status = packetTunnelManager.status, status == .connected else { return true }
        packetTunnelManager.stop()
    }
    
    return true
}

5. 添加手动快捷方式入口(可选)

在App内提供手动添加Siri快捷方式的界面,让用户快速配置:

// 示例:设置页面按钮点击事件
@IBAction func addConnectShortcutTapped(_ sender: UIButton) {
    let activity = NSUserActivity(activityType: Constants.connectVPNSiriActivityType)
    activity.title = NSLocalizedString("siriShortcutConnectVPNTitle", comment: "")
    let shortcut = INShortcut(userActivity: activity)
    let vc = INUIAddVoiceShortcutViewController(shortcut: shortcut)
    vc.delegate = self
    present(vc, animated: true)
}

// 实现代理方法
extension SettingsViewController: INUIAddVoiceShortcutViewControllerDelegate {
    func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
        dismiss(animated: true)
    }
    
    func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
        dismiss(animated: true)
    }
}

测试步骤

  1. 运行App,手动连接/断开VPN各一次,触发快捷方式捐赠
  2. 进入「设置」-「Siri与搜索」-「我的快捷方式」,确认VPN快捷方式已收录
  3. 打开YouTube,观察是否弹出Siri建议的VPN操作;或直接用语音触发(如“嘿Siri,连接VPN”)
  4. 若场景预测未自动触发,先手动添加快捷方式,再重复测试

内容的提问来源于stack exchange,提问作者максим мартынов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:19:53