关于 capacitor-app-intents
这项技能指导 Capacitor 应用开发者为 iOS 添加原生 App Intents,并将前台操作连接到 Web 层,涵盖冷启动路由和后台执行限制。
主要功能
- 01配置原生 Swift App Intents
- 02将前台 Intent 路由至 Web 层
- 03处理后台 Intent 限制
- 04支持快捷指令、小组件和控制项
- 05按系统版本选择 API
- 06构建与设备验证
适用场景
- 01添加 Siri 或快捷指令操作
- 02处理 Intent 冷启动路由
- 03排查无界面 Intent 故障
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ cap-go/ capgo-skills --skill capacitor-app-intents安装后在 Claude Code 中输入/capacitor-app-intents确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/intent-traps.mdios-26-27-apis.mdproject-setup.mdweb-bridge.mdwidgets-and-controls.md详细介绍
Capacitor 应用的 App Intents
向 iOS 项目添加原生 App Intents,让系统界面可以执行应用操作,并将其连接到 Web 层。App Intents 仅支持 Swift。它们没有 JavaScript API,因此每个 intent 都必须是在 App 目标或扩展中的原生代码,并通过 URL 或小型本地插件访问 Web 层。
适用场景
在以下情况使用:
- 用户希望 Capacitor 应用支持 Siri 短语、Shortcuts 操作、App Shortcuts、Spotlight 操作、操作按钮或 Apple Intelligence 集成
- 用户希望小组件按钮或控制中心控件执行应用操作
- intent 打开了应用,但 Web 视图没有导航,或仅在热启动时导航
- 后台 intent 崩溃、超时或试图调用 JS
- 将
openAppWhenRun迁移到supportedModes,或采用 iOS 26/27 App Intents API - 插件作者希望随插件提供 App Intents
不要用于:
- Universal Links/自定义 scheme/
appUrlOpen设置:capacitor-deep-linking - AppDelegate 迁移到 SceneDelegate:
capacitor-uiscene-migration - 推送通知操作:
capacitor-push-notifications - 由 JS 驱动的 Live Activities 或 SVG 小组件:
capacitor-plugins(@capgo/capacitor-widget-kit) - Android 应用快捷方式和 intents:此处不涉及
影响设计的事实
- App Intents 需要 iOS 16。 Capacitor 8 的最低部署版本为 iOS 15,因此每种 intent 类型、实体、查询和
AppShortcutsProvider都需要添加@available(iOS 16.0, *),或者用户提高最低部署版本。Capacitor 9 的最低部署版本为 iOS 16,因此基础 API 无需添加可用性限制。较新的 API 仍需添加限制(参见 references/ios-26-27-apis.md 中的表格)。 - 后台 intent 没有 WebView。 iOS 可以无界面地启动应用进程,以运行
.backgroundintents。AppDelegate.application(_:didFinishLaunchingWithOptions:)会运行,但没有 scene 连接,且CAPBridgeViewController不会加载。后台 intents 必须只执行原生操作(网络、存储、HealthKit 等)。它们不能通过桥接调用 JS 或插件。 perform()不在主线程上运行,而且可能运行多次。 在操作 UIKit、桥接或@MainActor状态前,显式切换到主线程(使用await MainActor.run或@MainActor func perform())。将不可逆操作放在最后执行。详情见:references/intent-traps.md。- 使用 UIScene(Capacitor 8.5+)时,URL 的传递方式已改变。 Universal Links 和自定义 scheme 打开操作会到达
SceneDelegate,并由SceneDelegateProxy转发;它会发布@capacitor/app监听的通知。如果应用仍在AppDelegate中包含自定义 URL 代码,该代码将不再运行。如果普通链接触发不了appUrlOpen,请先检查capacitor-deep-linking。intent 无法修复已损坏的链接传递流程。 - 冷启动时,JS 监听器尚不存在。 intent 交给 Web 层的任何路由都必须留存,直到 JS 请求它:对于 URL,使用
App.getLaunchUrl();对于本地插件路径,使用待处理路由存储,并调用notifyListeners(..., retainUntilConsumed: true)。 - 标识符是公开契约。 intent 类型名称、
AppEntity.id值、AppEnum原始值、URL 格式和已发布的短语都会保存在用户已保存的快捷指令中。请添加新的标识符;未经用户同意,不要重命名或移除已发布的标识符。
参考资料
仅在涉及对应主题时加载参考资料。
| 文件 | 加载时机 |
|---|---|
| references/project-setup.md | 创建文件、配置目标成员资格、扩展、App Groups、可用性限制、构建验证 |
| references/web-bridge.md | 将意图连接到 Web 层:URL 路由、本地 AppIntentsBridge 插件、待处理路由、共享数据 |
| references/intent-traps.md | 编写或审查任何意图、实体、查询、短语、依赖项、错误或捐赠 |
| references/ios-26-27-apis.md | supportedModes、前台延续、长时间运行/可取消/可撤销的意图、执行目标、片段、Spotlight 索引、架构、测试 |
| references/widgets-and-controls.md | 小组件配置意图、交互式小组件按钮、控制中心控件 |
工作流
1. 检查(只读)
- 阅读
package.json(@capacitor/ios版本)、ios/App/App/Info.plist(是否存在场景清单?)、ios/App/App/AppDelegate.swift、ios/App/App/SceneDelegate.swift、App 目标的最低部署版本,以及任何现有的*.entitlements(关联域、App Groups)。 - 检查应用是否已在 JS 中处理深层链接(
App.addListener('appUrlOpen', ...)、App.getLaunchUrl()),以及现有哪些路由。 - 搜索现有意图:
grep -rn "AppIntent\|AppShortcutsProvider\|openAppWhenRun" ios/App。 - 在
ios/App/App.xcodeproj/project.pbxproj中列出扩展目标(小组件)的PBXNativeTarget条目(除App外)。
2. 与用户一起设计
针对用户需要的每项操作,决定并确认:
| 问题 | 选项 |
|---|---|
| 是否需要 UI? | 否:后台意图,仅限原生。是:前台意图,路由到 Web 应用 |
| 如何连接到 JS? | 通过 OpenURLIntent 使用通用链接(iOS 18+,需要关联域),或使用带待处理路由存储的本地插件(支持自定义方案和 iOS 16+) |
| 需要哪些数据? | 固定集合:AppEnum。动态、可查询的数据:AppEntity + EntityQuery。自由文本或数字:普通 @Parameter |
| 必须在哪里运行? | 仅限 App 目标,或也支持小组件/控件(此时意图文件需要同时加入这两个目标) |
| 用于哪些入口? | App Shortcut 短语(每个应用最多 10 个 App Shortcuts)、Spotlight、小组件、控件 |
每个原子任务使用一个意图。编辑前报告计划(要添加的文件、目标、权限配置、JS 更改)。
3. 实现
- 在
ios/App/App/Intents/中创建 Swift 文件,并将其加入 App 目标(参见 references/project-setup.md)。 - 按照 references/intent-traps.md 编写意图。按版本限制 API 的使用。
- 添加 Web 桥接(参见 references/web-bridge.md):要么复用深层链接路由器,要么添加本地插件,并在
CAPBridgeViewController子类中注册。 - 添加一个
AppShortcutsProvider,并在每个短语中使用shortTitle、systemImageName和\(.applicationName)。 - 仅在需要时添加权限配置(共享数据使用 App Groups,通用链接使用关联域),并应用到所有需要它们的目标。
- JS 端:处理应用热启动和冷启动时的路由。
4. 验证
npx cap sync ios
xcodebuild -project ios/App/App.xcodeproj -scheme App \
-destination 'generic/platform=iOS Simulator' build
# CocoaPods projects: -workspace ios/App/App.xcworkspace
- 构建日志会显示 App Intents 元数据提取步骤,且不会出现有关短语的警告。不含
\(.applicationName)的短语会产生构建警告,并在运行时被丢弃。 - 在 Xcode 中打开 Product > App Shortcuts Preview,确认短语匹配。
- 在模拟器或设备上运行:打开 Shortcuts 应用,找到该应用的操作,并逐一运行。
- 后台意图:完成时应用不会切换到前台。检查原生日志(
ios-android-logs)。 - 前台意图:分别在先结束应用后(冷启动)和应用正在运行时(热启动)测试;两种情况下,Web 视图都会进入正确的路由。
- 后台意图:完成时应用不会切换到前台。检查原生日志(
- Spotlight:搜索快捷指令标题。
- 如果存在测试,请为 iOS 27 测试运行器添加 AppIntentsTesting 覆盖(references/ios-26-27-apis.md)。
错误处理
| 症状 | 原因 | 修复方法 |
|---|---|---|
'AppIntent' is only available in iOS 16.0 or newer | Capacitor 8 项目部署到 iOS 15 | 为每个 App Intents 类型添加 @available(iOS 16.0, *),或在获得用户批准后提高部署目标 |
| 安装后在 Shortcuts 中找不到意图 | 文件不在 App 目标中,或元数据提取失败 | 检查目标成员资格。查看构建日志中的 App Intents 元数据步骤。重新安装应用 |
| Siri 从不触发该短语;构建警告提及应用名称 | 短语缺少 \(.applicationName) | 为每个短语添加该标记 |
| 构建错误:App Shortcuts 超过 10 个 | 每个应用的数量上限 | 合并操作或移除价值较低的操作 |
@Dependency 报错 "...was not initialized prior to access" 并导致崩溃 | 在依赖项注册过晚(例如在视图控制器中) | 在 AppDelegate.application(_:didFinishLaunchingWithOptions:) 中注册,该方法在无界面启动时也会运行 |
| 前台意图打开应用,但冷启动时 Web 视图仍停留在主页路由 | 在 JS 添加监听器之前就发布了路由 | 使用待处理路由存储和 retainUntilConsumed,或使用 App.getLaunchUrl() |
OpenURLIntent 不会触发 appUrlOpen | 未配置 Universal Links,或在 UIScene 下使用了自定义 AppDelegate URL 代码 | 使用 capacitor-deep-linking 修复。OpenURLIntent 需要真实的 https Universal Link |
| Swift 6 错误:主线程隔离属性无法满足非隔离要求 | 意图类型标记了 @MainActor | 从类型上移除 @MainActor。将其添加到 perform() 上,或在内部切换执行上下文 |
| 后台意图在约 30 秒后被终止 | iOS 对后台意图的时长限制 | 缩短任务,或在 iOS 27 上使用 LongRunningIntent |
'openAppWhenRun' was deprecated in iOS 26.0 | iOS 26 SDK | 添加受条件控制的 supportedModes(references/ios-26-27-apis.md)。在部署目标低于 26 时保留 openAppWhenRun |
相关技能
capacitor-deep-linking:意图依赖的 Universal Links 和appUrlOpen路由capacitor-uiscene-migration:Xcode 27 之前必需;将 URL 处理迁移到SceneDelegatecapacitor-plugins:用于 Live Activities 和 JS 驱动的小组件的@capgo/capacitor-widget-kitcapacitor-testing:原生单元测试和设备验证流程ios-android-logs:无界面意图运行的日志
评论
支持 Markdown