16、联系人快捷方式:创建联系人快捷方式
快捷方式这个东西,说白了就是让用户少点几下。我刚开始做Android开发那会儿,系统还不支持动态快捷方式,每次更新快捷方式都得卸载重装,那体验真是够呛。后来Android 8.0引入了ShortcutManager,这事儿才算真正靠谱了。
今天咱们就聊聊联系人快捷方式的创建。你想想看,用户每天可能要联系某个人十几次,如果能直接在桌面点一下就能拨号,那体验提升可不是一星半点。
快捷方式的三种形态
Android系统里,快捷方式其实分三种,我习惯把它们叫做“三兄弟”:
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 静态快捷方式 | 写在xml里,编译时就固定了 | 固定功能,比如“新建联系人” |
| 动态快捷方式 | 运行时通过ShortcutManager添加 | 最近联系人、常用联系人 |
| PinnedShortcut | 用户手动固定到桌面的快捷方式 | 用户主动选择的联系人 |
嗯,这里要注意:PinnedShortcut是唯一可以出现在桌面上的,其他两种只出现在长按应用图标后的菜单里。
创建动态快捷方式
动态快捷方式最适合联系人系统。用户每次拨号或接听,咱们就可以把那个联系人加到快捷方式列表里。我在项目里就是这么干的,效果还不错。
先看代码:
// 获取ShortcutManager
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
// 构建快捷方式
ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "contact_001")
.setShortLabel("张三")
.setLongLabel("打电话给张三")
.setIcon(Icon.createWithResource(this, R.drawable.ic_contact))
.setIntent(new Intent(Intent.ACTION_DIAL)
.setData(Uri.parse("tel:13800138000")))
.build();
// 添加动态快捷方式
shortcutManager.addDynamicShortcuts(Arrays.asList(shortcut));
这里有个坑,我踩过。setShortLabel最多只能10个字符,超了会被截断。setLongLabel可以长一些,但也不建议超过25个字。你想想看,桌面上就那么点地方,太长了也显示不全。
PinnedShortcut:用户说了算
动态快捷方式虽然方便,但用户没法把它拖到桌面上。PinnedShortcut就是干这个的。用户长按应用图标,看到“固定到桌面”的选项,点一下就能把快捷方式钉在桌面上。
实现起来也不复杂:
// 请求固定快捷方式
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
if (shortcutManager.isRequestPinShortcutSupported()) {
ShortcutInfo pinShortcut = new ShortcutInfo.Builder(this, "pinned_contact_001")
.setShortLabel("李四")
.setIntent(new Intent(Intent.ACTION_DIAL)
.setData(Uri.parse("tel:13900139000")))
.build();
// 创建PendingIntent,用于接收固定结果
Intent pinnedIntent = shortcutManager.createShortcutResultIntent(pinShortcut);
PendingIntent successCallback = PendingIntent.getBroadcast(this, 0,
pinnedIntent, PendingIntent.FLAG_IMMUTABLE);
shortcutManager.requestPinShortcut(pinShortcut, successCallback.getIntentSender());
}
我曾经遇到过一个情况:用户固定了快捷方式,但后来那个联系人被删了。这时候点击快捷方式就会报错。所以一定要做容错处理,比如在Intent里加一个fallback页面。
动态快捷方式更新
快捷方式不是一成不变的。用户今天常联系的人,下周可能就不联系了。所以咱们得定期更新。
更新的逻辑其实很简单:
// 更新动态快捷方式
List<ShortcutInfo> updatedShortcuts = new ArrayList<>();
// 假设这是从数据库查出来的最近联系人
List<Contact> recentContacts = contactDao.getRecentContacts(5);
for (Contact contact : recentContacts) {
ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "contact_" + contact.getId())
.setShortLabel(contact.getName())
.setLongLabel("打电话给" + contact.getName())
.setIcon(Icon.createWithResource(this, contact.getAvatarResId()))
.setIntent(new Intent(Intent.ACTION_DIAL)
.setData(Uri.parse("tel:" + contact.getPhone())))
.build();
updatedShortcuts.add(shortcut);
}
// 替换所有动态快捷方式
shortcutManager.setDynamicShortcuts(updatedShortcuts);
这里有个细节:setDynamicShortcuts会替换掉所有现有的动态快捷方式。如果你只想更新某几个,可以用updateShortcuts方法。我个人习惯每次全量替换,逻辑更清晰,不容易出bug。
适配Android 8+的注意事项
Android 8.0(API 26)是分水岭。在这之前,创建快捷方式用的是不同的API。咱们做联系人系统,最低支持版本一般都在API 26以上,所以直接用ShortcutManager就行。
但还是有几个点要注意:
- 权限问题:Android 8.0以后,应用图标长按菜单最多显示5个快捷方式,多了会被忽略
- 图标大小:快捷方式图标必须是自适应图标(Adaptive Icon),否则在Android 8+上会变形
- Intent必须明确:不要用隐式Intent,否则系统不知道该怎么处理
- 唯一ID:每个快捷方式的ID必须唯一,重复添加会覆盖旧的
知识体系总览
下面这张图是我整理的快捷方式知识结构,你看一眼就能明白整体脉络:
避坑指南
做快捷方式开发,有几个坑我不得不提:
- ID冲突:我曾经因为ID重复,导致快捷方式怎么更新都不变。后来排查了半天才发现是ID写死了。建议用“contact_”+数据库ID这种格式。
- 图标加载:联系人头像可能是从网络加载的,但快捷方式图标必须是本地资源。我一般会在下载头像后,先保存到本地缓存,再用本地路径创建图标。
- 权限检查:调用requestPinShortcut前,一定要先检查isRequestPinShortcutSupported()。有些厂商的ROM不支持这个功能,直接调用会崩溃。
- 数量限制:动态快捷方式最多5个,PinnedShortcut没有数量限制,但用户桌面空间有限,别一股脑全加上去。
嗯,快捷方式这块内容就这些。说白了就是让用户少走几步路,咱们开发者多花点心思。你只要把上面这些逻辑理清楚,联系人快捷功能基本就稳了。