如何在Xamarin Forms跨平台应用中访问联系人并显示在ListView中
我完全懂你现在的困扰——找了一堆旧示例要么跑不起来,要么权限明明给了还报错,用着Visual Studio 2017和最新版Forms,却卡在联系人访问这一步,确实挺闹心的。别着急,我给你整理了一套适配当前版本的解决方案,亲测有效的那种:
一、先搞定权限配置(这是踩坑重灾区,旧示例的配置大多已经过时)
Xamarin.Forms是跨平台框架,得分别给Android和iOS配置权限,还要处理动态权限申请:
Android端配置
- 静态权限声明:打开
AndroidManifest.xml,添加以下权限代码到<manifest>标签内:<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> - 动态权限申请:Android 6.0+需要在运行时申请权限,我们用Xamarin.Essentials来简化操作。在
MainActivity.cs里添加以下代码:protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); // 启动时检查并申请联系人权限 CheckContactsPermissions(); LoadApplication(new App()); } private async void CheckContactsPermissions() { // 检查读取权限 var readStatus = await Permissions.CheckStatusAsync<Permissions.ContactsRead>(); if (readStatus != PermissionStatus.Granted) { readStatus = await Permissions.RequestAsync<Permissions.ContactsRead>(); } // 检查写入权限(如果需要修改联系人的话) var writeStatus = await Permissions.CheckStatusAsync<Permissions.ContactsWrite>(); if (writeStatus != PermissionStatus.Granted) { writeStatus = await Permissions.RequestAsync<Permissions.ContactsWrite>(); } } // 必须重写这个方法,让Xamarin.Essentials处理权限回调 public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); }
iOS端配置
iOS要求必须说明权限用途,否则会直接拒绝访问:
打开Info.plist,添加以下键值对(描述要写真实用途,比如“同步联系人信息”):
<key>NSContactsUsageDescription</key> <string>需要访问您的联系人列表以完成联系人同步操作</string>
iOS的权限申请可以在共享代码里统一处理,不用单独写原生代码。
二、共享代码里实现联系人读取逻辑
用官方维护的Xamarin.Essentials Contacts API,适配性比旧第三方库好太多,直接在共享项目里写代码就行:
using Xamarin.Essentials; using System.Collections.Generic; using System.Threading.Tasks; public async Task<List<Contact>> GetAllContactsAsync() { var contactsList = new List<Contact>(); try { // 先再次确认权限(防止用户后续关闭了权限) var status = await Permissions.CheckStatusAsync<Permissions.ContactsRead>(); if (status != PermissionStatus.Granted) { status = await Permissions.RequestAsync<Permissions.ContactsRead>(); if (status != PermissionStatus.Granted) { // 用户拒绝权限,这里可以弹提示让用户去设置里开启 return contactsList; } } // 获取所有联系人 var contacts = await Contacts.GetAllAsync(); foreach (var contact in contacts) { contactsList.Add(contact); // 可以提取联系人的详细信息,比如电话、邮箱 // 示例:var firstPhone = contact.Phones.FirstOrDefault()?.Number; } } catch (PermissionException ex) { System.Diagnostics.Debug.WriteLine($"权限异常:{ex.Message}"); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取联系人失败:{ex.Message}"); } return contactsList; }
之后你就可以在Forms页面里调用这个方法,比如按钮点击事件:
private async void FetchContactsBtn_Clicked(object sender, EventArgs e) { var contacts = await GetAllContactsAsync(); // 把contacts绑定到ListView或者其他控件展示即可 }
三、几个关键注意事项
- 确保你给解决方案里的所有项目(共享、Android、iOS)都安装了最新版的Xamarin.Essentials NuGet包;
- Visual Studio 2017建议更新到15.9.x及以上版本,不然可能对最新Forms和Essentials的支持有问题;
- 如果还是遇到权限报错,手动去手机设置里检查App的联系人权限是否真的开启了;
- iOS模拟器默认没有联系人数据,你可以在模拟器的「通讯录」里手动添加测试数据,或者用Xcode导入联系人文件。
内容的提问来源于stack exchange,提问作者Abdul Wahab
相关产品推荐
相关产品推荐

