uni-app App端无法使用uni.getContact和uni.chooseContact,因二者仅支持小程序平台;全量读取须用plus.contacts原生方案,且需严格处理iOS/Android权限、字段白名单及跳转设置页的校验链路。

uni-app 在 App 端无法通过 uni.getContact 或 uni.chooseContact 直接读取或选择联系人——这两个 API 在 App 平台(iOS/Android)根本不存在,调用后静默失败或返回空数组,不是你代码写错了,是平台根本不支持。
为什么 uni.chooseContact 在 App 里点不动
它只在微信小程序、支付宝小程序等轻应用环境生效;App 端调用后无弹窗、无报错、无回调,直接走 .catch 或返回空数组。官方文档已明确标注“App 不支持”。如果你只需要让用户选一个联系人(比如填紧急联系人),这是唯一能跨平台跑通的方案,但必须满足两个前提:
- iOS 需在
manifest.json的ios→permissions里配置NSContactsUsageDescription字段,否则首次调用直接 crash - Android 12+ 需在
AndroidManifest.xml中显式声明android.permission.READ_CONTACTS,哪怕你没真读通讯录,部分厂商(如小米、华为)会校验该权限是否存在 - 调用前必须先检查授权状态:
uni.getAuthSetting确认authSetting['scope.contact']为true,否则跳转设置页也无效
plus.contacts 是 App 端唯一可批量读取通讯录的路径
它不是 npm 包,也不是 Vue 插件,而是 HBuilderX 打包时内置的 5+ 引擎原生能力,仅限 app-plus 平台,web 和小程序完全不可用。常见错误 Cannot read property 'contacts' of undefined 基本是因为:没在真机或模拟器运行、没用 HBuilderX 打包(比如 npm run dev:app 启动调试)、或在 data 初始化阶段就访问 plus.contacts。
- 必须在
onLoad或用户点击事件中调用,且需前置判断:if (!plus || !plus.contacts) return - Android 和 iOS 实现差异极大:Android 可用
plus.contacts.getAddressBook+find;iOS 模拟器受限于 Native.js bug,真机需用CNContactPickerViewController代理方式,不能直接查全量 - 字段要白名单控制:只请求
['displayName', 'phoneNumbers'],避免拉取头像、地址等冗余字段导致内存溢出或超时
权限拒绝后跳转设置页的正确链路
uni.openSetting 不是万能钥匙,乱用会导致 iOS 静默失败、Android 闪退。它只能在系统已记录“用户拒绝”之后触发,而这个状态只有 uni.getAuthSetting 能确认。
- 错误流程:
uni.authorize失败 → 立刻uni.openSetting→ 无效(系统还没记下拒绝) - 正确流程:
uni.authorize失败 → 调uni.getAuthSetting→ 检查authSetting['scope.contact'] === false→ 再调uni.openSetting - 跳转回来后,必须在页面
onShow中重新执行uni.getAuthSetting并更新 UI(例如按钮文字从“去授权”变“已授权”),否则状态永远不同步 - iOS 用户跳转后只到 App 主设置页,无法直达「通讯录」开关,必须提示:“请手动进入设置 → [你的App名] → 通讯录 → 开启”
三个容易被忽略的硬性失效点
即使代码全对、权限配置完整,以下三点仍会让功能在部分设备上彻底不可用:
- Android 10+ 隐私沙盒机制下,
READ_CONTACTS权限默认只允许访问“最近交互联系人”,全量读取需额外申请READ_PRIVILEGED_CONTACTS(系统级权限,普通应用无法获取) - iOS 17+ 对
CNContactStore的访问限制更严,未在Info.plist中配置NSContactsUsageDescription的 App,首次调用直接终止进程 - HBuilderX 版本低于 3.99 时,
plus.contacts在 Android 14 设备上会因 ContentResolver 权限变更而抛出SecurityException,必须升级打包环境


















