Flutter使用contacts_service读取手机通讯录时遭遇权限拒绝报错:Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord
解决Contacts Service权限拒绝问题
我之前在使用contacts_service包读取通讯录时也遇到过一模一样的权限拒绝错误,下面是我整理的排查和解决步骤,亲测有效:
1. Android端:别只配置Manifest,必须加运行时权限请求
很多人误以为在AndroidManifest.xml里加了权限就万事大吉,但Android 6.0(API 23)及以上系统要求动态申请权限,光靠Manifest声明是不够的。
首先检查你的AndroidManifest.xml,确保在<manifest>标签下(不是<application>里面)添加了正确的权限:
<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- 如果需要写入通讯录,再加上下面这个 --> <uses-permission android:name="android.permission.WRITE_CONTACTS" />
然后在Flutter代码里配合permission_handler包来请求权限(contacts_service本身不处理权限逻辑):
import 'package:permission_handler/permission_handler.dart'; import 'package:contacts_service/contacts_service.dart'; // 先检查并请求通讯录权限 Future<bool> _getContactPermission() async { final permissionStatus = await Permission.contacts.status; if (permissionStatus.isDenied) { final result = await Permission.contacts.request(); return result.isGranted; } else if (permissionStatus.isPermanentlyDenied) { // 权限被永久拒绝,引导用户去设置页开启 await openAppSettings(); return false; } return permissionStatus.isGranted; } // 读取通讯录的核心方法 Future<void> _fetchContacts() async { final hasPermission = await _getContactPermission(); if (hasPermission) { final contacts = await ContactsService.getContacts(); // 这里处理拿到的通讯录数据 } else { // 提示用户权限不足,无法读取通讯录 } }
2. iOS端:确保Info.plist的权限描述正确
iOS这边除了在Info.plist里添加NSContactsUsageDescription,还要注意描述内容不能为空,否则会直接被系统拒绝权限:
<key>NSContactsUsageDescription</key> <string>需要访问您的通讯录来导入联系人信息</string>
把上面这段放在Info.plist的<dict>标签内,描述文字可以根据你的实际需求修改。
3. 最后几个容易忽略的小细节
- 检查AndroidManifest.xml的权限位置:一定要放在
<manifest>根标签下,别误放到<application>里面,不然权限声明无效。 - 清理项目缓存:有时候配置文件修改后不会立即生效,执行
flutter clean然后重新运行flutter run试试。 - 测试设备的系统版本:如果是Android 11+,用户拒绝权限后会直接变成永久拒绝,这时候必须引导用户去应用设置手动开启。
内容的提问来源于stack exchange,提问作者Mayur Agarwal




