日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 获取通讯录全选反选_Xamarin.Forms读取并展示Android和iOS通讯录 TerminalMACS客户端...

發布時間:2024/9/27 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 获取通讯录全选反选_Xamarin.Forms读取并展示Android和iOS通讯录 TerminalMACS客户端... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文同步更新地址:

  • https://dotnet9.com/11520.html

  • https://terminalmacs.com/861.html

閱讀導航:

  • 一、功能說明

  • 二、代碼實現

  • 三、源碼獲取

  • 四、參考資料

  • 五、后面計劃

一、功能說明

完整思維導圖:https://github.com/dotnet9/TerminalMACS/blob/master/docs/TerminalMACS.xmind?

本文介紹圖中右側畫紅圈處的功能,即使用Xamarin.Forms獲取和展示Android和iOS的通訊錄信息,下面是最終效果,由于使用的是真實手機,所以聯系人姓名及電話號碼打碼顯示。

并簡單的進行了搜索功能處理,之所以說簡單,是因為通訊錄列表是全部讀取出來了,搜索是直接從此列表進行過濾的。

下圖來自:https://www.xamboy.com/2019/10/10/getting-phone-contacts-in-xamarin-forms/,本功能是參考此文所寫,所以直接引用文中的圖片。

二、代碼實現

1、共享庫工程創建聯系人實體類:Contacts.cs

  • namespace TerminalMACS.Clients.App.Models

  • {

  • ? ///

  • ? /// 通訊錄

  • ? ///

  • ? ?public class Contact

  • ? ?{

  • ? ? ? ///

  • ? ? ? /// 獲取或者設置名稱

  • ? ? ? ///

  • ? ? ? ?public string Name { get; set; }

  • ? ? ? ///

  • ? ? ? /// 獲取或者設置 頭像

  • ? ? ? ///

  • ? ? ? ?public string Image { get; set; }

  • ? ? ? ///

  • ? ? ? /// 獲取或者設置 郵箱地址

  • ? ? ? ///

  • ? ? ? ?public string[] Emails { get; set; }

  • ? ? ? ///

  • ? ? ? /// 獲取或者設置 手機號碼

  • ? ? ? ///

  • ? ? ? ?public string[] PhoneNumbers { get; set; }

  • ? ?}

  • }

  • 2、共享庫創建通訊錄服務接口:IContactsService.cs

    包括:

    • 一個通訊錄獲取請求接口:RetrieveContactsAsync

    • 一個讀取一條通訊結果通知事件:OnContactLoaded

  • using System;

  • using System.Collections.Generic;

  • using System.Threading;

  • using System.Threading.Tasks;

  • using TerminalMACS.Clients.App.Models;

  • namespace TerminalMACS.Clients.App.Services

  • {

  • ? ///

  • ? /// 通訊錄事件參數

  • ? ///

  • ? ?public class ContactEventArgs:EventArgs

  • ? ?{

  • ? ? ? ?public Contact Contact { get; }

  • ? ? ? ?public ContactEventArgs(Contact contact)

  • ? ? ? ?{

  • ? ? ? ? ? ?Contact = contact;

  • ? ? ? ?}

  • ? ?}

  • ? ///

  • ? /// 通訊錄服務接口,android和iOS終端具體的通訊錄獲取服務需要繼承此接口

  • ? ///

  • ? ?public interface IContactsService

  • ? ?{

  • ? ? ? ///

  • ? ? ? /// 讀取一條數據通知

  • ? ? ? ///

  • ? ? ? ?event EventHandler OnContactLoaded;

  • ? ? ? ///

  • ? ? ? /// 是否正在加載

  • ? ? ? ///

  • ? ? ? ?bool IsLoading { get; }

  • ? ? ? ///

  • ? ? ? /// 嘗試獲取所有通訊錄

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?Task> RetrieveContactsAsync(CancellationToken? token = null);

  • ? ?}

  • }

  • 3、iOS工程中添加通訊錄服務,實現IContactsService接口:

  • using Contacts;

  • using Foundation;

  • using System;

  • using System.Collections.Generic;

  • using System.IO;

  • using System.Linq;

  • using System.Threading;

  • using System.Threading.Tasks;

  • using TerminalMACS.Clients.App.Models;

  • using TerminalMACS.Clients.App.Services;

  • namespace TerminalMACS.Clients.App.iOS.Services

  • {

  • ? ///

  • ? /// 通訊錄獲取服務

  • ? ///

  • ? ?public class ContactsService : NSObject, IContactsService

  • ? ?{

  • ? ? ? ?const string ThumbnailPrefix = "thumb";

  • ? ? ? ?bool requestStop = false;

  • ? ? ? ?public event EventHandler OnContactLoaded;

  • ? ? ? ?bool _isLoading = false;

  • ? ? ? ?public bool IsLoading => _isLoading;

  • ? ? ? ///

  • ? ? ? /// 異步請求權限

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?public async Task<bool> RequestPermissionAsync()

  • ? ? ? ?{

  • ? ? ? ? ? ?var status = CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts);

  • ? ? ? ? ? ?Tuple<bool, NSError> authotization = new Tuple<bool, NSError>(status == CNAuthorizationStatus.Authorized, null);

  • ? ? ? ? ? ?if (status == CNAuthorizationStatus.NotDetermined)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?using (var store = new CNContactStore())

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?authotization = await store.RequestAccessAsync(CNEntityType.Contacts);

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?return authotization.Item1;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步請求通訊錄,此方法由界面真正調用

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?public async Task> RetrieveContactsAsync(CancellationToken? cancelToken = null)

  • ? ? ? ?{

  • ? ? ? ? ? ?requestStop = false;

  • ? ? ? ? ? ?if (!cancelToken.HasValue)

  • ? ? ? ? ? ? ? ?cancelToken = CancellationToken.None;

  • ? ? ? ? ? // 我們創建了一個十進制的TaskCompletionSource

  • ? ? ? ? ? ?var taskCompletionSource = new TaskCompletionSource>();

  • ? ? ? ? ? // 在cancellationToken中注冊lambda

  • ? ? ? ? ? ?cancelToken.Value.Register(() =>

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 我們收到一條取消消息,取消TaskCompletionSource.Task

  • ? ? ? ? ? ? ? ?requestStop = true;

  • ? ? ? ? ? ? ? ?taskCompletionSource.TrySetCanceled();

  • ? ? ? ? ? ?});

  • ? ? ? ? ? ?_isLoading = true;

  • ? ? ? ? ? ?var task = LoadContactsAsync();

  • ? ? ? ? ? // 等待兩個任務中的第一個任務完成

  • ? ? ? ? ? ?var completedTask = await Task.WhenAny(task, taskCompletionSource.Task);

  • ? ? ? ? ? ?_isLoading = false;

  • ? ? ? ? ? ?return await completedTask;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步加載通訊錄,具體的通訊錄讀取方法

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?async Task> LoadContactsAsync()

  • ? ? ? ?{

  • ? ? ? ? ? ?IList contacts = new List();

  • ? ? ? ? ? ?var hasPermission = await RequestPermissionAsync();

  • ? ? ? ? ? ?if (hasPermission)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?NSError error = null;

  • ? ? ? ? ? ? ? ?var keysToFetch = new[] { CNContactKey.PhoneNumbers, CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.EmailAddresses, CNContactKey.ImageDataAvailable, CNContactKey.ThumbnailImageData };

  • ? ? ? ? ? ? ? ?var request = new CNContactFetchRequest(keysToFetch: keysToFetch);

  • ? ? ? ? ? ? ? ?request.SortOrder = CNContactSortOrder.GivenName;

  • ? ? ? ? ? ? ? ?using (var store = new CNContactStore())

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?var result = store.EnumerateContacts(request, out error, new CNContactStoreListContactsHandler((CNContact c, ref bool stop) =>

  • ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ?string path = null;

  • ? ? ? ? ? ? ? ? ? ? ? ?if (c.ImageDataAvailable)

  • ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?path = path = Path.Combine(Path.GetTempPath(), $"{ThumbnailPrefix}-{Guid.NewGuid()}");

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (!File.Exists(path))

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?var imageData = c.ThumbnailImageData;

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?imageData?.Save(path, true);

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ? ? ? ? ?var contact = new Contact()

  • ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?Name = string.IsNullOrEmpty(c.FamilyName) ? c.GivenName : $"{c.GivenName} {c.FamilyName}",

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?Image = path,

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?PhoneNumbers = c.PhoneNumbers?.Select(p => p?.Value?.StringValue).ToArray(),

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?Emails = c.EmailAddresses?.Select(p => p?.Value?.ToString()).ToArray(),

  • ? ? ? ? ? ? ? ? ? ? ? ?};

  • ? ? ? ? ? ? ? ? ? ? ? ?if (!string.IsNullOrWhiteSpace(contact.Name))

  • ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?OnContactLoaded?.Invoke(this, new ContactEventArgs(contact));

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?contacts.Add(contact);

  • ? ? ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ? ? ? ? ?stop = requestStop;

  • ? ? ? ? ? ? ? ? ? ?}));

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?return contacts;

  • ? ? ? ?}

  • ? ?}

  • }

  • 4、在iOS工程中的Info.plist文件添加通訊錄權限使用說明

    5、在Android工程中添加讀取通訊錄權限配置:AndroidManifest.xml

  • android:name="android.permission.READ_CONTACTS"/>

  • 完整權限配置如下

  • xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.terminalmacs.clients.app">

  • ? android:minSdkVersion="21" android:targetSdkVersion="28" />

  • ? android:label="TerminalMACS.Clients.App.Android">

  • ? android:name="android.permission.ACCESS_NETWORK_STATE" />

  • ? android:name="android.permission.READ_CONTACTS"/>

  • ? android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  • 6、在Android工程中添加通訊錄服務,實現IContactServer接口:ContactsService.cs

  • using Acr.UserDialogs;

  • using Android;

  • using Android.App;

  • using Android.Content;

  • using Android.Content.PM;

  • using Android.Database;

  • using Android.Provider;

  • using Android.Runtime;

  • using Android.Support.V4.App;

  • using Plugin.CurrentActivity;

  • using System;

  • using System.Collections.Generic;

  • using System.IO;

  • using System.Linq;

  • using System.Threading;

  • using System.Threading.Tasks;

  • using TerminalMACS.Clients.App.Models;

  • using TerminalMACS.Clients.App.Services;

  • namespace TerminalMACS.Clients.App.Droid.Services

  • {

  • ? ///

  • ? /// 通訊錄獲取服務

  • ? ///

  • ? ?public class ContactsService : IContactsService

  • ? ?{

  • ? ? ? ?const string ThumbnailPrefix = "thumb";

  • ? ? ? ?bool stopLoad = false;

  • ? ? ? ?static TaskCompletionSource<bool> contactPermissionTcs;

  • ? ? ? ?public string TAG

  • ? ? ? ?{

  • ? ? ? ? ? ?get

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?return "MainActivity";

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ?bool _isLoading = false;

  • ? ? ? ?public bool IsLoading => _isLoading;

  • ? ? ? //權限請求狀態碼

  • ? ? ? ?public const int RequestContacts = 1239;

  • ? ? ? ///

  • ? ? ? /// 獲取通訊錄需要的請求權限

  • ? ? ? ///

  • ? ? ? ?static string[] PermissionsContact = {

  • ? ? ? ? ? ?Manifest.Permission.ReadContacts

  • ? ? ? ?};

  • ? ? ? ?public event EventHandler OnContactLoaded;

  • ? ? ? ///

  • ? ? ? /// 異步請求通訊錄權限

  • ? ? ? ///

  • ? ? ? ?async void RequestContactsPermissions()

  • ? ? ? ?{

  • ? ? ? ? ? //檢查是否可以彈出申請讀、寫通訊錄權限

  • ? ? ? ? ? ?if (ActivityCompat.ShouldShowRequestPermissionRationale(CrossCurrentActivity.Current.Activity, Manifest.Permission.ReadContacts)

  • ? ? ? ? ? ? ? ?|| ActivityCompat.ShouldShowRequestPermissionRationale(CrossCurrentActivity.Current.Activity, Manifest.Permission.WriteContacts))

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 如果未授予許可,請向用戶提供其他理由用戶將從使用權限的附加上下文中受益。

  • ? ? ? ? ? ? ? // 例如,如果請求先前被拒絕。

  • ? ? ? ? ? ? ? ?await UserDialogs.Instance.AlertAsync("通訊錄權限", "此操作需要“通訊錄”權限", "確定");

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?else

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 尚未授予通訊錄權限。直接請求這些權限。

  • ? ? ? ? ? ? ? ?ActivityCompat.RequestPermissions(CrossCurrentActivity.Current.Activity, PermissionsContact, RequestContacts);

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 收到用戶響應請求權限操作后的結果

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?public static void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)

  • ? ? ? ?{

  • ? ? ? ? ? ?if (requestCode == RequestContacts)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 我們請求了多個通訊錄權限,因此需要檢查相關的所有權限

  • ? ? ? ? ? ? ? ?if (PermissionUtil.VerifyPermissions(grantResults))

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? // 已授予所有必需的權限,顯示聯系人片段。

  • ? ? ? ? ? ? ? ? ? ?contactPermissionTcs.TrySetResult(true);

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?else

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?contactPermissionTcs.TrySetResult(false);

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步請求權限

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?public async Task<bool> RequestPermissionAsync()

  • ? ? ? ?{

  • ? ? ? ? ? ?contactPermissionTcs = new TaskCompletionSource<bool>();

  • ? ? ? ? ? // 驗證是否已授予所有必需的通訊錄權限。

  • ? ? ? ? ? ?if (Android.Support.V4.Content.ContextCompat.CheckSelfPermission(CrossCurrentActivity.Current.Activity, Manifest.Permission.ReadContacts) != (int)Permission.Granted

  • ? ? ? ? ? ? ? ?|| Android.Support.V4.Content.ContextCompat.CheckSelfPermission(CrossCurrentActivity.Current.Activity, Manifest.Permission.WriteContacts) != (int)Permission.Granted)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 尚未授予通訊錄權限。

  • ? ? ? ? ? ? ? ?RequestContactsPermissions();

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?else

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 已授予通訊錄權限。

  • ? ? ? ? ? ? ? ?contactPermissionTcs.TrySetResult(true);

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?return await contactPermissionTcs.Task;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步請求通訊錄,此方法由界面真正調用

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?public async Task> RetrieveContactsAsync(CancellationToken? cancelToken = null)

  • ? ? ? ?{

  • ? ? ? ? ? ?stopLoad = false;

  • ? ? ? ? ? ?if (!cancelToken.HasValue)

  • ? ? ? ? ? ? ? ?cancelToken = CancellationToken.None;

  • ? ? ? ? ? // 我們創建了一個十進制的TaskCompletionSource

  • ? ? ? ? ? ?var taskCompletionSource = new TaskCompletionSource>();

  • ? ? ? ? ? // 在cancellationToken中注冊lambda

  • ? ? ? ? ? ?cancelToken.Value.Register(() =>

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 我們收到一條取消消息,取消TaskCompletionSource.Task

  • ? ? ? ? ? ? ? ?stopLoad = true;

  • ? ? ? ? ? ? ? ?taskCompletionSource.TrySetCanceled();

  • ? ? ? ? ? ?});

  • ? ? ? ? ? ?_isLoading = true;

  • ? ? ? ? ? ?var task = LoadContactsAsync();

  • ? ? ? ? ? // 等待兩個任務中的第一個任務完成

  • ? ? ? ? ? ?var completedTask = await Task.WhenAny(task, taskCompletionSource.Task);

  • ? ? ? ? ? ?_isLoading = false;

  • ? ? ? ? ? ?return await completedTask;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步加載通訊錄,具體的通訊錄讀取方法

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?async Task> LoadContactsAsync()

  • ? ? ? ?{

  • ? ? ? ? ? ?IList contacts = new List();

  • ? ? ? ? ? ?var hasPermission = await RequestPermissionAsync();

  • ? ? ? ? ? ?if (!hasPermission)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?return contacts;

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?var uri = ContactsContract.Contacts.ContentUri;

  • ? ? ? ? ? ?var ctx = Application.Context;

  • ? ? ? ? ? ?await Task.Run(() =>

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? // 暫時只請求通訊錄Id、DisplayName、PhotoThumbnailUri,可以擴展

  • ? ? ? ? ? ? ? ?var cursor = ctx.ApplicationContext.ContentResolver.Query(uri, new string[]

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ?ContactsContract.Contacts.InterfaceConsts.Id,

  • ? ? ? ? ? ? ? ? ? ? ? ?ContactsContract.Contacts.InterfaceConsts.DisplayName,

  • ? ? ? ? ? ? ? ? ? ? ? ?ContactsContract.Contacts.InterfaceConsts.PhotoThumbnailUri

  • ? ? ? ? ? ? ? ?}, null, null, $"{ContactsContract.Contacts.InterfaceConsts.DisplayName} ASC");

  • ? ? ? ? ? ? ? ?if (cursor.Count > 0)

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?while (cursor.MoveToNext())

  • ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ?var contact = CreateContact(cursor, ctx);

  • ? ? ? ? ? ? ? ? ? ? ? ?if (!string.IsNullOrWhiteSpace(contact.Name))

  • ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? // 讀取出一條,即通知界面展示

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?OnContactLoaded?.Invoke(this, new ContactEventArgs(contact));

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?contacts.Add(contact);

  • ? ? ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ? ? ? ? ?if (stopLoad)

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;

  • ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?});

  • ? ? ? ? ? ?return contacts;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 讀取一條通訊錄數據

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?Contact CreateContact(ICursor cursor, Context ctx)

  • ? ? ? ?{

  • ? ? ? ? ? ?var contactId = GetString(cursor, ContactsContract.Contacts.InterfaceConsts.Id);

  • ? ? ? ? ? ?var numbers = GetNumbers(ctx, contactId);

  • ? ? ? ? ? ?var emails = GetEmails(ctx, contactId);

  • ? ? ? ? ? ?var uri = GetString(cursor, ContactsContract.Contacts.InterfaceConsts.PhotoThumbnailUri);

  • ? ? ? ? ? ?string path = null;

  • ? ? ? ? ? ?if (!string.IsNullOrEmpty(uri))

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?try

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?using (var stream = Android.App.Application.Context.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(uri)))

  • ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ?path = Path.Combine(Path.GetTempPath(), $"{ThumbnailPrefix}-{Guid.NewGuid()}");

  • ? ? ? ? ? ? ? ? ? ? ? ?using (var fstream = new FileStream(path, FileMode.Create))

  • ? ? ? ? ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?stream.CopyTo(fstream);

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?fstream.Close();

  • ? ? ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ? ? ? ? ?stream.Close();

  • ? ? ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?catch (Exception ex)

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?System.Diagnostics.Debug.WriteLine(ex);

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?var contact = new Contact

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?Name = GetString(cursor, ContactsContract.Contacts.InterfaceConsts.DisplayName),

  • ? ? ? ? ? ? ? ?Emails = emails,

  • ? ? ? ? ? ? ? ?Image = path,

  • ? ? ? ? ? ? ? ?PhoneNumbers = numbers,

  • ? ? ? ? ? ?};

  • ? ? ? ? ? ?return contact;

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 讀取聯系人電話號碼

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?string[] GetNumbers(Context ctx, string contactId)

  • ? ? ? ?{

  • ? ? ? ? ? ?var key = ContactsContract.CommonDataKinds.Phone.Number;

  • ? ? ? ? ? ?var cursor = ctx.ApplicationContext.ContentResolver.Query(

  • ? ? ? ? ? ? ? ?ContactsContract.CommonDataKinds.Phone.ContentUri,

  • ? ? ? ? ? ? ? ?null,

  • ? ? ? ? ? ? ? ?ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + " = ?",

  • ? ? ? ? ? ? ? ?new[] { contactId },

  • ? ? ? ? ? ? ? ?null

  • ? ? ? ? ? ?);

  • ? ? ? ? ? ?return ReadCursorItems(cursor, key)?.ToArray();

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 讀取聯系人郵箱地址

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?string[] GetEmails(Context ctx, string contactId)

  • ? ? ? ?{

  • ? ? ? ? ? ?var key = ContactsContract.CommonDataKinds.Email.InterfaceConsts.Data;

  • ? ? ? ? ? ?var cursor = ctx.ApplicationContext.ContentResolver.Query(

  • ? ? ? ? ? ? ? ?ContactsContract.CommonDataKinds.Email.ContentUri,

  • ? ? ? ? ? ? ? ?null,

  • ? ? ? ? ? ? ? ?ContactsContract.CommonDataKinds.Email.InterfaceConsts.ContactId + " = ?",

  • ? ? ? ? ? ? ? ?new[] { contactId },

  • ? ? ? ? ? ? ? ?null);

  • ? ? ? ? ? ?return ReadCursorItems(cursor, key)?.ToArray();

  • ? ? ? ?}

  • ? ? ? ?IEnumerable<string> ReadCursorItems(ICursor cursor, string key)

  • ? ? ? ?{

  • ? ? ? ? ? ?while (cursor.MoveToNext())

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?var value = GetString(cursor, key);

  • ? ? ? ? ? ? ? ?yield return value;

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?cursor.Close();

  • ? ? ? ?}

  • ? ? ? ?string GetString(ICursor cursor, string key)

  • ? ? ? ?{

  • ? ? ? ? ? ?return cursor.GetString(cursor.GetColumnIndex(key));

  • ? ? ? ?}

  • ? ?}

  • }

  • 需要添加?Plugin.CurrentActivity?和?Acr.UserDialogs?包。

    7、Android工程添加權限處理判斷類

    Permission.Util.cs

  • using Android.Content.PM;

  • namespace TerminalMACS.Clients.App.Droid

  • {

  • ? ?public static class PermissionUtil

  • ? ?{

  • ? ? ? ?/**

  • ? ?* 通過驗證給定數組中的每個條目的值是否為Permission.Granted,檢查是否已授予所有給定權限。

  • ? ?*

  • ? ?* See Activity#onRequestPermissionsResult (int, String[], int[])

  • ? ?*/

  • ? ? ? ?public static bool VerifyPermissions(Permission[] grantResults)

  • ? ? ? ?{

  • ? ? ? ? ? // 必須至少檢查一個結果.

  • ? ? ? ? ? ?if (grantResults.Length < 1)

  • ? ? ? ? ? ? ? ?return false;

  • ? ? ? ? ? // 驗證是否已授予每個必需的權限,否則返回false.

  • ? ? ? ? ? ?foreach (Permission result in grantResults)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?if (result != Permission.Granted)

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?return false;

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?return true;

  • ? ? ? ?}

  • ? ?}

  • }

  • MainActivity.OnRequestPermissionResult是權限申請結果處理函數,在此函數中調用ContactsService.OnRequestPermissionsResult通知通訊錄服務權限處理結果。

    MainActivity.cs

  • using Acr.UserDialogs;

  • using Android.App;

  • using Android.Content.PM;

  • using Android.OS;

  • using Android.Runtime;

  • using TerminalMACS.Clients.App.Droid.Services;

  • using TerminalMACS.Clients.App.Services;

  • namespace TerminalMACS.Clients.App.Droid

  • {

  • ? ?[Activity(Label = "TerminalMACS.Clients.App", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

  • ? ?public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity

  • ? ?{

  • ? ? ? ?IContactsService contactsService = new ContactsService();

  • ? ? ? ?protected override void OnCreate(Bundle savedInstanceState)

  • ? ? ? ?{

  • ? ? ? ? ? ?TabLayoutResource = Resource.Layout.Tabbar;

  • ? ? ? ? ? ?ToolbarResource = Resource.Layout.Toolbar;

  • ? ? ? ? ? ?base.OnCreate(savedInstanceState);

  • ? ? ? ? ? ?Xamarin.Essentials.Platform.Init(this, savedInstanceState);

  • ? ? ? ? ? ?global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

  • ? ? ? ? ? ?UserDialogs.Init(() => this);

  • ? ? ? ? ? // 將通訊錄服務實例傳遞給共享庫,由共享庫使用讀取通訊錄接口

  • ? ? ? ? ? ?LoadApplication(new App(contactsService));

  • ? ? ? ?}

  • ? ? ? ?public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)

  • ? ? ? ?{

  • ? ? ? ? ? ?Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

  • ? ? ? ? ? // 通訊錄服務處理權限請求結果

  • ? ? ? ? ? ?ContactsService.OnRequestPermissionsResult(requestCode, permissions, grantResults);

  • ? ? ? ? ? ?base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

  • ? ? ? ?}

  • ? ?}

  • }

  • 8、創建通訊錄ViewModel,并使用通訊錄服務

  • using System;

  • using System.Collections;

  • using System.Collections.Generic;

  • using System.Collections.ObjectModel;

  • using System.Linq;

  • using System.Threading.Tasks;

  • using System.Windows.Input;

  • using TerminalMACS.Clients.App.Models;

  • using TerminalMACS.Clients.App.Services;

  • using Xamarin.Forms;

  • namespace TerminalMACS.Clients.App.ViewModels

  • {

  • ? ///

  • ? /// 通訊錄ViewModel

  • ? ///

  • ? ?public class ContactViewModel : BaseViewModel

  • ? ?{

  • ? ? ? ///

  • ? ? ? /// 通訊錄服務接口

  • ? ? ? ///

  • ? ? ? ?IContactsService _contactService;

  • ? ? ? ///

  • ? ? ? /// 標題

  • ? ? ? ///

  • ? ? ? ?public new string Title => "通訊錄";

  • ? ? ? ?private string _SearchText;

  • ? ? ? ///

  • ? ? ? /// 搜索關鍵字

  • ? ? ? ///

  • ? ? ? ?public string SearchText

  • ? ? ? ?{

  • ? ? ? ? ? ?get { return _SearchText; }

  • ? ? ? ? ? ?set

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?SetProperty(ref _SearchText, value);

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 通訊錄搜索命令

  • ? ? ? ///

  • ? ? ? ?public ICommand RaiseSearchCommand { get; }

  • ? ? ? ///

  • ? ? ? /// 通訊錄列表

  • ? ? ? ///

  • ? ? ? ?public ObservableCollection Contacts { get; set; }

  • ? ? ? ?private List _FilteredContacts;

  • ? ? ? ///

  • ? ? ? /// 通訊錄過濾列表

  • ? ? ? ///

  • ? ? ? ?public List FilteredContacts

  • ? ? ? ?{

  • ? ? ? ? ? ?get { return _FilteredContacts; }

  • ? ? ? ? ? ?set

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?SetProperty(ref _FilteredContacts, value);

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ?public ContactViewModel(IContactsService contactService)

  • ? ? ? ?{

  • ? ? ? ? ? ?_contactService = contactService;

  • ? ? ? ? ? ?Contacts = new ObservableCollection();

  • ? ? ? ? ? ?Xamarin.Forms.BindingBase.EnableCollectionSynchronization(Contacts, null, ObservableCollectionCallback);

  • ? ? ? ? ? ?_contactService.OnContactLoaded += OnContactLoaded;

  • ? ? ? ? ? ?LoadContacts();

  • ? ? ? ? ? ?RaiseSearchCommand = new Command(RaiseSearchHandle);

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 過濾通訊錄

  • ? ? ? ///

  • ? ? ? ?void RaiseSearchHandle()

  • ? ? ? ?{

  • ? ? ? ? ? ?if (string.IsNullOrEmpty(SearchText))

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?FilteredContacts = Contacts.ToList();

  • ? ? ? ? ? ? ? ?return;

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?Funcbool> checkContact = (s) =>

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?if (!string.IsNullOrWhiteSpace(s.Name) && s.Name.ToLower().Contains(SearchText.ToLower()))

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?return true;

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?else if (s.PhoneNumbers.Length > 0 && s.PhoneNumbers.ToList().Exists(cu => cu.ToString().Contains(SearchText)))

  • ? ? ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ? ? ?return true;

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ? ? ?return false;

  • ? ? ? ? ? ?};

  • ? ? ? ? ? ?FilteredContacts = Contacts.ToList().Where(checkContact).ToList();

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// BindingBase.EnableCollectionSynchronization 為集合啟用跨線程更新

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?void ObservableCollectionCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess)

  • ? ? ? ?{

  • ? ? ? ? ? // `lock` ensures that only one thread access the collection at a time

  • ? ? ? ? ? ?lock (collection)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?accessMethod?.Invoke();

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 收到事件通知,讀取一條通訊錄信息

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?private void OnContactLoaded(object sender, ContactEventArgs e)

  • ? ? ? ?{

  • ? ? ? ? ? ?Contacts.Add(e.Contact);

  • ? ? ? ? ? ?RaiseSearchHandle();

  • ? ? ? ?}

  • ? ? ? ///

  • ? ? ? /// 異步讀取終端通訊錄

  • ? ? ? ///

  • ? ? ? ///

  • ? ? ? ?async Task LoadContacts()

  • ? ? ? ?{

  • ? ? ? ? ? ?try

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?await _contactService.RetrieveContactsAsync();

  • ? ? ? ? ? ?}

  • ? ? ? ? ? ?catch (TaskCanceledException)

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?Console.WriteLine("任務已經取消");

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ?}

  • }

  • 9、添加通訊錄頁面展示通訊錄數據

  • <?xml version="1.0" encoding="utf-8" ?>

  • "http://xamarin.com/schemas/2014/forms"

  • ? ? ? ? ? ? xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

  • ? ? ? ? ? ? xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

  • ? ? ? ? ? ? xmlns:d="http://xamarin.com/schemas/2014/forms/design"

  • ? ? ? ? ? ? xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"

  • ? ? ? ? ? ? mc:Ignorable="d"

  • ? ? ? ? ? ? Title="{Binding Title}"

  • ? ? ? ? ? ? x:Class="TerminalMACS.Clients.App.Views.ContactPage"

  • ? ? ? ? ? ? ios:Page.UseSafeArea="true">

  • ? ? ? ? ? ?"filterText"

  • ? ? ? ? ? ? ? ? ? ? ? ?HeightRequest="40"

  • ? ? ? ? ? ? ? ? ? ? ? ?Text="{Binding SearchText}"

  • ? ? ? ? ? ? ? ? ? ? ? SearchCommand="{Binding RaiseSearchCommand}"/>

  • ? ? ? ? ? ?"{Binding FilteredContacts}"

  • ? ? ? ? ? ? ? ? ? ? ? ?HasUnevenRows="True">

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?"10"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Orientation="Horizontal">

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"{Binding Image}"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?VerticalOptions="Center"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?x:Name="image"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Aspect="AspectFit"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?HeightRequest="60"/>

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"Center">

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"{Binding Name}"

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FontAttributes="Bold"/>

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"{Binding PhoneNumbers[0]}"/>

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"{Binding Emails[0]}"/>

  • 三、源碼獲取

    • 1.完整源碼:https://github.com/dotnet9/TerminalMACS

    • 2.Android客戶端可成功取得通訊錄數據,并可查詢;

    已編譯的Android客戶端:https://terminalmacs.com/terminalmacs-clients-app-android

    • 3.iOS讀取通訊錄功能代碼也已添加,但由于本人沒有iOS測試環境,所以未驗證,有條件的朋友可以測試下iOS的通訊錄讀取功能,如果代碼不起作用,可參考本文參考的文章檢查iOS代碼。

    四、參考資料

    Getting phone contacts in Xamarin Forms:https://www.xamboy.com/2019/10/10/getting-phone-contacts-in-xamarin-forms/

    參考文章末尾有源代碼鏈接。

    五、后面計劃

    Xamarin.Forms客戶端基本信息獲取,比如IMEI、IMSI、本機號碼、Mac地址等。

    總結

    以上是生活随笔為你收集整理的android 获取通讯录全选反选_Xamarin.Forms读取并展示Android和iOS通讯录 TerminalMACS客户端...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。