跳过主要内容

Capacitor 社区联系人替代方案

An alternative to the @capacitor-community/contacts plugin: update contacts, groups, pagination and permission-free picking, with a full migration guide.

文章来源

马丁·多纳迪尤

作者

瓦莱里亚

审阅者

乔丹

编辑

Capacitor 社区联系人替代方案

If you need a Capacitor community contacts alternative, the most complete drop-in replacement is @capgo/capacitor-contacts它涵盖了 @capacitor-community/contacts 做什么(读取、创建、删除和选择联系人)并添加更新联系人(不改变其 ID),分页、组、帐户、原生联系人屏幕和 Android 上的免许可选择,这对于 Google Play 的 2027 年联系人政策至关重要。 本指南将两者进行比较,并映射每个调用,以便您在下午内进行迁移。

为何寻找替代方案

@capacitor-community/contacts 维护并且有一个 Capacitor 8 版本。它是适合简单的读取和创建流程的选择。团队通常因为以下原因超出了它的使用范围:

  • 没有更新方法。 您可以创建和删除联系人,但无法编辑一个联系人。删除并重新创建会为联系人生成一个新的 ID,这会破坏任何存储的引用并可能丢失未读取的插件数据。
  • 没有分页。 getContacts 一次返回整个通讯录。对于具有 5,000 个联系人和照片的设备,这是慢且占用内存的。
  • 在 Android 中,需要权限才能选择联系人。 Android pickContact 在打开选择器之前,请求联系人权限组,然后从通讯录中读取联系人。根据 Google Play 的联系人权限政策,针对 Android 17 的应用程序只能保留 READ_CONTACTS 用于核心功能的权限
  • 没有群组、账户或原生屏幕。 没有列出群组、选择新联系人保存的账户或打开系统“新联系人”表单的方法。

功能比较

功能 @capacitor-社区/联系人 8.0 @capgo/capacitor-联系人 8.1
读取联系人/所有联系人 getContact, getContacts getContactById, getContacts
字段选择 projection 对象 fields 数组
分页 没有 limit, offset
联系人数量 没有 countContacts
创建 createContact createContact
在原地更新 没有 updateContactById
删除 deleteContact deleteContactById
选择一个联系人 pickContact pickContact
选择多个联系人 没有 pickContacts({ multiple: true })
选择一个电话/邮箱/地址(无权限) 没有 pickContacts({ property })
组 否 getGroups, getGroupById, createGroup, deleteGroupById
账户 否 getAccounts
原生创建/查看/编辑屏幕 否 displayCreateContact, displayContactById, displayUpdateContactById
分离读取和写入权限状态 否 (单个别名) readContacts, writeContacts
iOS 受限访问状态 limited limited
打开设置 否 openSettings

安装

bun add @capgo/capacitor-contacts
bunx cap sync

该插件不会添加权限到您的Android清单文件中。只添加您使用的权限:

<!-- Needed for getContacts, getContactById, countContacts, groups, accounts -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- Needed for createContact, updateContactById, deleteContactById, groups writes -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

在 iOS 上,添加 NSContactsUsageDescription 到 Info.plist 如果您阅读或写入通讯录,选择不需要它

迁移指南,逐步调用

权限

// Before
import { Contacts } from '@capacitor-community/contacts';
const perm = await Contacts.requestPermissions();
if (perm.contacts !== 'granted') return;

// After
import { CapacitorContacts } from '@capgo/capacitor-contacts';
const status = await CapacitorContacts.requestPermissions({ permissions: ['readContacts'] });
if (status.readContacts !== 'granted' && status.readContacts !== 'limited') {
  await CapacitorContacts.openSettings();
  return;
}

On iOS 18 或更高版本,用户可以授予对联系人子集的访问权限。该插件报告它作为 limited。将其视为已授权,仅期望共享联系人

读取所有联系人

// Before: whole address book, projection object
const { contacts } = await Contacts.getContacts({
  projection: { name: true, phones: true, emails: true },
});
const first = contacts[0];
console.log(first.name?.display, first.phones?.[0]?.number);

// After: fields array, paginated
const pageSize = 200;
let offset = 0;
for (;;) {
  const { contacts } = await CapacitorContacts.getContacts({
    fields: ['displayName', 'givenName', 'familyName', 'phoneNumbers', 'emailAddresses'],
    limit: pageSize,
    offset,
  });
  render(contacts);
  if (contacts.length < pageSize) break;
  offset += pageSize;
}

declare function render(list: unknown[]): void;

使用 countContacts() 首先,如果您想显示进度条

读取一个联系人

// Before
const { contact } = await Contacts.getContact({
  contactId: id,
  projection: { name: true, phones: true },
});

// After
const { contact } = await CapacitorContacts.getContactById({
  id,
  fields: ['displayName', 'phoneNumbers'],
});
if (!contact) console.log('Not found');

创建一个联系人

// Before
const { contactId } = await Contacts.createContact({
  contact: {
    name: { given: 'Ada', family: 'Lovelace' },
    phones: [{ type: PhoneType.Mobile, number: '+44 20 7946 0000' }],
    emails: [{ type: EmailType.Work, address: 'ada@example.com' }],
  },
});

// After
const { id } = await CapacitorContacts.createContact({
  contact: {
    givenName: 'Ada',
    familyName: 'Lovelace',
    phoneNumbers: [{ type: 'MOBILE', value: '+44 20 7946 0000' }],
    emailAddresses: [{ type: 'WORK', value: 'ada@example.com' }],
  },
});

displayName 在 Capgo 插件中只读。写入 givenName 和 familyName, 设备会格式化显示名称。

更新联系人 (新)

await CapacitorContacts.updateContactById({
  id,
  contact: {
    givenName: 'Ada',
    familyName: 'King',
    jobTitle: 'Analyst',
    phoneNumbers: [{ type: 'MOBILE', value: '+44 20 7946 0000' }],
  },
});

ID 保持不变,因此您保存的任何引用仍然有效。 请先阅读联系人,然后返回您要保留的字段,以免意外清除内容。

如果您愿意让用户编辑,请打开系统编辑器:

await CapacitorContacts.displayUpdateContactById({ id });

删除联系人

// Before
await Contacts.deleteContact({ contactId: id });

// After
await CapacitorContacts.deleteContactById({ id });

选择联系人

// Before: requests the contacts permission on Android first
const { contact } = await Contacts.pickContact({
  projection: { name: true, phones: true },
});

// After: one phone number, no permission on Android or iOS
import { ContactProperty } from '@capgo/capacitor-contacts';

const { contacts } = await CapacitorContacts.pickContacts({
  property: ContactProperty.PhoneNumber,
});
const phone = contacts[0]?.phoneNumbers?.[0]?.value;

如果您需要从选择器中获取完整的联系人记录,请调用 pickContact() 不 property. 在 Android 上,只有当 READ_CONTACTS 已授权时才会返回完整的联系人。

Field mapping

社区 payload Capgo Contact
contactId id
name.display displayName 社区提交
name.given / middle / family givenName / middleName / familyName
name.prefix / suffix namePrefix / nameSuffix
organization.company organizationName
organization.jobTitle jobTitle
birthday { day, month, year } birthday { day, month, year }
note note
phones[].number phoneNumbers[].value
emails[].address emailAddresses[].value
urls[] 只读 urlAddresses[].value
postalAddresses[].region / postcode postalAddresses[].state / postalCode
image.base64String photo 字符串

类型值也会改变:Capgo 插件使用大写字符串,如 'MOBILE', 'HOME', 'WORK' 类型值也会发生变化:__CAPGO_KEEP_0__插件使用大写字符串,如

用于手机和电子邮件。

逐步迁移Contacts and CapacitorContacts和

import { CapacitorContacts } from '@capgo/capacitor-contacts';

export interface AppContact {
  id: string;
  name: string;
  phones: string[];
}

export async function listContacts(limit = 200, offset = 0): Promise<AppContact[]> {
  const { contacts } = await CapacitorContacts.getContacts({
    fields: ['displayName', 'phoneNumbers'],
    limit,
    offset,
  });
  return contacts.map((c) => ({
    id: c.id ?? '',
    name: c.displayName ?? '',
    phones: (c.phoneNumbers ?? []).map((p) => p.value),
  }));
}

当最后一个调用站点被移动时,移除社区插件,运行 bunx cap sync,并检查合并的Android清单文件以确认您需要的权限仍然存在。

故障排除

getContacts 上下文:支持/高级支持页面或底部支持部分。角色:部分或页面标题。见于:页面support-policy.astro。消息键`support_policy_troubleshooting_title`(支持政策故障排除标题)。 返回iOS时为空列表。 readContacts 并提供 openSettings().

并提供 传递一个 account 传递一个 getAccounts()(来自

)在您创建的联系人中。 照片使列表变慢。 photo 在列表视图中。使用 getContactById 当用户打开联系人时

Play Console 标志 READ_CONTACTS. 将邀请和分享流程移至 pickContacts({ property }) 并在没有其他需要时删除权限

发布

__CAPGO_KEEP_0__ 构建 Capgo 构建 可以在云端生成 iOS 和 Android 构建。然后,修复您的联系人屏幕的 JavaScript 修复可以与 Capgo 实时更新. The full API is in the 。完整的 __CAPGO_KEEP_0__ 在联系人插件文档中.

为Capacitor应用提供实时更新

当Web层bug出现时,通过Capgo发布修复,而不是等待几天的应用商店审批。用户在后台接收更新,而原生变化仍在正常审批路径中。

最新博客

Capgo为您提供创建真正专业的移动应用所需的最佳见解。