文档管理中心
FAQ应用服务开发联系人服务(Contacts Kit)调用queryContactsByPhoneNumber接口异常怎么解决

调用queryContactsByPhoneNumber接口异常怎么解决

问题现象

开发者在使用Contacts Kit开发联系人相关功能时会遇到以下常见问题:

  • 参照官方文档在AGC中已经配置了通讯录读写权限,工程中也配置了通讯录读权限,但是在启动调试或运行应用/服务时,安装HAP出现错误,提示:
    收起
    自动换行
    深色代码主题
    复制
    1. error: install failed due to grant request permissions failed
  • 根据电话号码使用contact.queryContactsByPhoneNumber查出来的联系人缺少name信息。

背景知识

Contacts Kit可以帮助开发者轻松实现联系人的增删改查等功能。该Kit提供了一系列API,可以让开发者在应用中快速集成联系人管理功能,详情请参考@ohos.contact API

问题定位

  1. 检查ACL受限权限是否申请成功,生成Profile时是否进行勾选对应受限权限。然后检查手动签名是否更新了Profile文件等签名信息。
  2. 检查接口使用是否正确,接口返回值是否有name字段。

分析结论

  1. ohos.permission.READ_CONTACTS是受限开放权限,授权方式是用户授权(user_grant)。该问题是由于默认应用等级为normal,只能使用normal等级的权限,如果使用了system_basic、system_core等级或受限开放的权限,将导致报错。
  2. contact.queryContactsByPhoneNumber接口仅返回联系人信息中的id、key、phoneNumbers属性。
    • 如果要查询联系人的所有信息,建议使用contact.queryContact接口,根据contact.queryContactsByPhoneNumber接口返回的属性key查询。
    • contact.queryContact有多个入参不同的同名接口,详情参考@ohos.contact API。其中入参含有attrs联系人的属性列表的接口需要注意,attrs不传默认查询所有联系人属性,如果传了就需要包含contact.Attribute.ATTR_NAME接口才会返回name。

修改建议

查询联系人信息有两种方式,一种是使用Picker选择联系人获取信息,另一种是使用@ohos.contact API查询联系人信息:

  • 使用Picker选择联系人:

    通过Picker的方式,拉起联系人列表,引导用户完成界面操作,接口本身无需申请权限,因此推荐使用这种方式。

    收起
    自动换行
    深色代码主题
    复制
    1. // 1.调用联系人接口,拉起联系人列表,用户点击对应的联系人后返回
    2. if (canIUse('SystemCapability.Applications.Contacts')) {
    3. contact.selectContacts({
    4. isMultiSelect: false
    5. }, (err: BusinessError, data) => {
    6. if (err) {
    7. console.error('selectContact callback, errCode:' + err.code + ', errMessage:' + err.message);
    8. return;
    9. }
    10. // 2.完成操作,返回想要的data数据
    11. console.info(`selectContact callback: success data->${JSON.stringify(data)}`);
    12. });
    13. } else {
    14. console.error('The current device does not support contact queries.');
    15. }
  • 使用@ohos.contact API查询联系人信息:
    • Contacts Kit当前能力受限开放,需要申请受限开放权限ohos.permission.READ_CONTACTS或ohos.permission.WRITE_CONTACTS。该权限通常不允许三方应用申请,仅符合指定场景的应用可申请该权限。
    • 使用@ohos.contact API查询联系人信息:此方式需要关注使用的接口的入参是否含有attrs联系人的属性列表。以contact.queryContact接口为例,attrs不传默认查询所有联系人属性,如果传了就需要包含contact.Attribute.ATTR_NAME接口才会返回name。
      收起
      自动换行
      深色代码主题
      复制
      1. let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
      2. const permissions: Array<Permissions> = ['ohos.permission.READ_CONTACTS'];
      3. abilityAccessCtrl.createAtManager()
      4. .requestPermissionsFromUser(context, permissions)
      5. .then((result: PermissionRequestResult) => {
      6. if (result.authResults[0] !== 0) { // 0 表示请求权限成功,其他任何非零值表示请求失败
      7. console.error('request contact permissions failed');
      8. return;
      9. }
      10. if (canIUse('SystemCapability.Applications.ContactsData')) {
      11. contact.queryContactsByPhoneNumber(context, '138xxxxxxxx', {
      12. attributes: [contact.Attribute.ATTR_NAME, contact.Attribute.ATTR_PHONE]
      13. }, (err: BusinessError, data) => {
      14. if (err) {
      15. console.error(`Failed to query Contacts By PhoneNumber. Code: ${err.code}, message: ${err.message}`);
      16. return;
      17. }
      18. console.info(`Succeeded in querying Contacts By PhoneNumber. data->${JSON.stringify(data)}`);
      19. if (data.length !== 0) {
      20. contact.queryContact(context, data[0].key, {
      21. attributes: [contact.Attribute.ATTR_NAME, contact.Attribute.ATTR_PHONE]
      22. }, (err: BusinessError, data) => {
      23. if (err) {
      24. console.error(`Failed to query Contact. Code: ${err.code}, message: ${err.message}`);
      25. return;
      26. }
      27. console.info(`Succeeded in querying Contact. data->${JSON.stringify(data)}`);
      28. });
      29. }
      30. });
      31. } else {
      32. console.error('The current device does not support contact queries.');
      33. }
      34. })
      35. .catch((err: BusinessError) => {
      36. console.error(`Failed to queryContactsByPhoneNumber. Code: ${err.code}, message: ${err.message}`);
      37. });

完整示例参考如下:

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit';
  2. import { contact } from '@kit.ContactsKit';
  3. import { abilityAccessCtrl, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit';
  4. @Entry
  5. @Component
  6. struct ContactExample {
  7. build() {
  8. Column({ space: 20 }) {
  9. Button('使用Picker选择联系人')
  10. .onClick(() => {
  11. // 1.调用联系人接口,拉起联系人列表,用户点击对应的联系人后返回
  12. if (canIUse('SystemCapability.Applications.Contacts')) {
  13. contact.selectContacts({
  14. isMultiSelect: false
  15. }, (err: BusinessError, data) => {
  16. if (err) {
  17. console.error('selectContact callback, errCode:' + err.code + ', errMessage:' + err.message);
  18. return;
  19. }
  20. // 2.完成操作,返回想要的data数据
  21. console.info(`selectContact callback: success data->${JSON.stringify(data)}`);
  22. });
  23. } else {
  24. console.error('The current device does not support contact queries.');
  25. }
  26. });
  27. Button('根据电话号码和attrs查询联系人')
  28. .onClick(() => {
  29. let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  30. const permissions: Array<Permissions> = ['ohos.permission.READ_CONTACTS'];
  31. abilityAccessCtrl.createAtManager()
  32. .requestPermissionsFromUser(context, permissions)
  33. .then((result: PermissionRequestResult) => {
  34. if (result.authResults[0] !== 0) { // 0 表示请求权限成功,其他任何非零值表示请求失败
  35. console.error('request contact permissions failed');
  36. return;
  37. }
  38. if (canIUse('SystemCapability.Applications.ContactsData')) {
  39. contact.queryContactsByPhoneNumber(context, '138xxxxxxxx', {
  40. attributes: [contact.Attribute.ATTR_NAME, contact.Attribute.ATTR_PHONE]
  41. }, (err: BusinessError, data) => {
  42. if (err) {
  43. console.error(`Failed to query Contacts By PhoneNumber. Code: ${err.code}, message: ${err.message}`);
  44. return;
  45. }
  46. console.info(`Succeeded in querying Contacts By PhoneNumber. data->${JSON.stringify(data)}`);
  47. if (data.length !== 0) {
  48. contact.queryContact(context, data[0].key, {
  49. attributes: [contact.Attribute.ATTR_NAME, contact.Attribute.ATTR_PHONE]
  50. }, (err: BusinessError, data) => {
  51. if (err) {
  52. console.error(`Failed to query Contact. Code: ${err.code}, message: ${err.message}`);
  53. return;
  54. }
  55. console.info(`Succeeded in querying Contact. data->${JSON.stringify(data)}`);
  56. });
  57. }
  58. });
  59. } else {
  60. console.error('The current device does not support contact queries.');
  61. }
  62. })
  63. .catch((err: BusinessError) => {
  64. console.error(`Failed to queryContactsByPhoneNumber. Code: ${err.code}, message: ${err.message}`);
  65. });
  66. });
  67. }
  68. .height('100%')
  69. .width('100%')
  70. .justifyContent(FlexAlign.Center);
  71. }
  72. }
在 FAQ 中进行搜索
请输入您想要搜索的关键词