人生路上我们总在寻找捷径,当然,是合乎道德的那一种。但如果我告诉你,在你的移动应用中也能实现这种“捷径”呢?
本文将深度剖析 App Shortcuts 的原理、类型以及在 Flutter 中的完整落地方案。
过在学习这件事上,可没有捷径可言,所以请确保你读到了最后。
一、什么是 App Shortcuts?
作为开发者,我们可以定义快捷方式(Shortcuts),让用户直接跳转到应用内的特定页面或流程,大幅减少操作步骤。
最终目的:通过提升导航效率,极致优化用户体验。
你一定见过这种交互
长按任何应用图标,都会弹出一个快捷菜单。这些快捷方式分为两类:
系统快捷方式:如“应用锁”、“卸载”、“分享”等,各应用表现一致。 应用自定义快捷方式:如“扫一扫”、“付款”,由开发者定义。 
它们不仅出现在系统桌面,还能被 Google 助手等语音助手调用,让用户快速触达核心功能。
命名差异:在 Android 上称为 Shortcuts;在 iOS 上,桌面快捷方式通常被称为 Quick Actions(或 Home Screen Quick Actions)。
二、Shortcuts 的三大类型

1. 静态快捷方式 (Static Shortcuts)
提供对常用、预定义操作的快速访问。它们在应用安装后立即可用,即使从未打开过 App。
特点:因在编译时定义,运行时无法修改。任何变更都需要发版。
常见示例:Gmail 的“收件箱”、YouTube 的“搜索”。
Android 实现 (shortcuts.xml)
在 res/xml/ 目录下创建 shortcuts.xml:
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="new_post_static"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:shortcutShortLabel="@string/shortcut_new_post_short"
android:shortcutLongLabel="@string/shortcut_new_post_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.example.app_shortcuts"
android:targetClass="com.example.app_shortcuts.MainActivity">
<extra android:name="shortcutId" android:value="new_post" />
<extra android:name="source" android:value="static" />
</intent>
</shortcut>
<shortcut
android:shortcutId="test_shortcut_static"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:shortcutShortLabel="@string/shortcut_test_short"
android:shortcutLongLabel="@string/shortcut_test_long">
<!-- 省略 intent -->
</shortcut>
</shortcuts>
注意:由于无法访问外部 URL,此处为等效的本地实现示例。
并在 AndroidManifest.xml 中引用:
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
iOS 实现 (Info.plist)
在 Info.plist 中添加 UIApplicationShortcutItems 数组:
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>new_post_static</string>
<key>UIApplicationShortcutItemTitle</key>
<string>New Post</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>Create a new post</string>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeCompose</string>
<key>UIApplicationShortcutItemUserInfo</key>
<dict>
<key>shortcutId</key>
<string>new_post</string>
<key>source</key>
<string>static</string>
</dict>
</dict>
<!-- 更多 Shortcut ... -->
</array>
处理点击:需要通过 MethodChannel 在原生侧捕获启动事件,传递给 Flutter 侧进行路由跳转(完整代码见文末)。
2. 动态快捷方式 (Dynamic Shortcuts)
基于用户交互和应用内活动动态变化。与静态不同,它们可以在运行时创建、更新或删除。
特点:安装后不会立即可见,需等待应用逻辑触发。
常见示例:从最近的存档点恢复游戏,或打开用户上次阅读到的书籍页码。
Flutter 实现 (quick_actions 包)
初始化:在 App 生命周期早期初始化,并设置回调。 final QuickActions quickActions = const QuickActions();
quickActions.initialize((shortcutType) {
if (shortcutType == 'action_main') {
print('用户点击了 "主视图" 快捷方式');
}
// 更多处理逻辑...
});管理快捷方式: quickActions.setShortcutItems(<ShortcutItem>[
const ShortcutItem(type: 'action_main', localizedTitle: '主视图', icon: 'icon_main'),
const ShortcutItem(type: 'action_help', localizedTitle: '帮助', localizedSubtitle: '点击获取帮助', icon: 'icon_help'),
]);清除所有动态快捷方式: await quickActions.clearShortcutItems();
3. 固定快捷方式 (Pinned Shortcuts)
允许用户将特定操作直接钉在桌面上,实现一键直达。通常用于高度个性化或高频使用的功能。
示例:将特定聊天置顶、钉住支付流程入口。
平台支持:主要支持 Android。iOS 无直接等价物,但可通过 Widget 或 Siri Shortcuts 实现类似效果。 用户操作:长按应用图标 -> 长按快捷方式 -> 拖到桌面。
Flutter 实现 (pinned_shortcuts 包)
// 请求系统添加固定快捷方式。用户会看到系统确认弹窗。
// 注意:我们无法得知用户是接受还是取消,因此不要假设操作一定成功。
Future<void> createNetworkPinnedShortcut() {
return FlutterPinnedShortcuts.createPinnedShortcut(
id: AppConstants.defaultPinnedShortcutId,
label: AppConstants.defaultPinnedShortcutLabel,
imageSource: AppConstants.pinnedShortcutImageUrl,
imageSourceType: ImageSourceType.network,
adaptiveIconForeground: AppConstants.pinnedShortcutImageUrl,
adaptiveIconBackground: AppConstants.pinnedShortcutBgColor,
adaptiveIconBackgroundType: AdaptiveIconBackgroundType.color,
extraData: const {'type': 'adaptive_color'},
);
}
检测支持性与处理点击:
Future<void> _initPinned() async {
// 监听固定快捷方式的点击事件
_pinnedSub = FlutterPinnedShortcuts.onShortcutClick.listen((data) {
final id = data['id']?.toString();
if (id == null) return;
// 处理跳转逻辑...
});
await FlutterPinnedShortcuts.initialize();
final supported = await FlutterPinnedShortcuts.isSupported();
if (!supported) {
// 部分启动器或旧设备不支持固定。静默退出,不影响其他功能。
debugPrint('当前设备不支持固定快捷方式');
await _pinnedSub?.cancel();
_pinnedSub = null;
return;
}
}
三、集成前的关键考量
数量限制:可见的快捷方式数量受 OS 或启动器限制。通常最多显示 4 个(静态与动态混合)。 静态不可变:静态快捷方式在运行时无法修改,任何更改都需要应用更新。 动态排名:动态快捷方式的可见性取决于系统排名因素(如使用历史、最近使用、频率)。 排序规则:静态快捷方式遵循 XML 中的定义顺序;动态快捷方式通过代码分配排名。 固定快捷方式的差异:它们可以支持原生资源、Flutter 资源甚至网络图片(取决于实现)。 quick_actions包的局限性:不支持禁用快捷方式。 不暴露备份相关标志。 对于此类高级用例,需使用 平台通道 (Platform Channels) 自行实现。
四、最佳实践
确保唯一 ID:如果新快捷方式使用了现有 ID,它将更新旧的那个。 优先使用 Deep Link:对于动态快捷方式,使用深度链接而非硬编码的路由字符串。这能让你对导航有更好的灵活性和控制力。 妥善处理冷启动与热启动:确保快捷方式回调在 App 未运行(冷启动)和已运行(热启动)时都能正确初始化并跳转。 使用有意义的图标:静态和动态快捷方式应引用原生资源(iOS 的 xcassets或 Android 的 drawable资源)。保持动态快捷方式的相关性:根据用户的近期行为和频率更新它们。 拓展至搜索与助手:若想在启动器之外(如 Google 搜索)展示快捷方式,可集成 Google Shortcuts Integration Library。
五、结语
有人创建了一个示例应用,演示了静态、动态和固定快捷方式的实现,并处理了冷启动与热启动场景。它还包含使用 SharedPreferences 进行持久化的逻辑。感兴趣的可以看看https://github.com/anupam92402/app_shortcuts
掌握 App Shortcuts 不仅能提升你应用的用户体验,更是让你的产品融入系统生态、提升用户留存的关键一步。
💡 架构师视角 (Bonus)
Deep Link 路由设计
处理快捷方式点击的核心在于路由。推荐使用 go_router等支持深度链接的路由库,将快捷方式传递的 extraData映射为统一的路由路径。原生与 Flutter 的桥梁
对于 quick_actions或 pinned_shortcuts包未覆盖的高级功能(如禁用、备份标志),你需要编写 Platform Channel (MethodChannel) 代码,在 Android 侧调用 ShortcutManager或 iOS 侧调用 UIApplication的相关 API。国内 Android 生态适配
华为、小米、OPPO 等定制 ROM 对快捷方式的支持程度和交互略有差异。务必在主流国产机型上进行真机测试,并参考各厂商的桌面快捷方式适配文档。
夜雨聆风