HOW-TO

How to fetch Contacts in Xamarin?

We know that Xamarin is a platform that enables fantastic mobile app developments. With Material visual support in Xamarin forms, you could probably create an impeccable design, handling the layout and look of an app. In this blog, we will create a project in Xamarin forms to fetch contacts with a search bar option.

With any mobile app development, there is one common thing that permit access to read the phone contacts. Here some plugins are available for getting the phone contacts you have to make sure that Plugin.CurrentActivity and Acr.UserDialogs packages are installed. You can also apply Material design rule in Xamarin.Forms applications.

The following step shows how to fetch phone contacts.

Step: 1

Open Visual Studio and select Xamarin project.

After selecting Xamarin forms, give it the appropriate name and select Blank App for Android and iOS platforms.

Step: 2

First, create a Model.

 

GetContact.cs

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace FetchContact.Model

{

public class GetContact

{

public string NameofContact { get; set; }

public string ImageofContact { get; set; }

public string[] Emailsofperson { get; set; }

public string[] Numberofperson { get; set; }

}

}

 

Step: 3

 

Create an Interface.

 

IGetContactServices.cs

 

using FetchContact.Model;

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

 

namespace FetchContact.Service

{

public class IGetContactServices : EventArgs

{

public GetContact getContact { get; }

public IGetContactServices(GetContact contact)

{

getContact = contact;

}

}

public interface IContacts

{

event EventHandler<IGetContactServices> OnContactLoad;

bool IsLoading { get; }

Task<IList<GetContact>> RetrieveContacts(CancellationToken? token = null);

}

}

 

Step: 4

 

After creating the interface open AndroidManifest.xml in the Android project and add the below permission.

 

<uses-permission android:name=”android.permission.READ_CONTACTS” />

 

Step: 5

 

After adding the user permission, add the implementation for the contact service in the Android project.

 

AndroidContactService.cs

 

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Threading;

using System.Threading.Tasks;

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 FetchContact.Model;

using FetchContact.Service;

using Plugin.CurrentActivity;

 

namespace FetchContact.Droid.Services

{

public class AndroidContactsService : IContacts

{

const string Thumbnail = “thumbIcon”;

bool stopLoad = false;

static TaskCompletionSource<bool> contactPermission;

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<IGetContactServices> OnContactLoad;

 

async void RequestContactsPermissions()

{

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

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

{

 

await UserDialogs.Instance.AlertAsync(“Permission”, “Set the permission”, “Ok”);

}

else

{

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

}

}

public static void RqstPermissionsData(int rqstpermission, string[] permissions, [GeneratedEnum] Permission[] grants)

{

if (rqstpermission == AndroidContactsService.RequestContacts)

{

if (PermissionUtil.VerifyPermissions(grants))

{

contactPermission.TrySetResult(true);

}

else

{

contactPermission.TrySetResult(false);

}

 

}

}

 

public async Task<bool> RequestPermission()

{

contactPermission = 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

{

contactPermission.TrySetResult(true);

}

 

return await contactPermission.Task;

}

 

public async Task<IList<GetContact>> RetrieveContacts(CancellationToken? cancelToken = null)

{

stopLoad = false;

 

if (!cancelToken.HasValue)

cancelToken = CancellationToken.None;

 

var taskCompletionSource = new TaskCompletionSource<IList<GetContact>>();

 

cancelToken.Value.Register(() =>

{

stopLoad = true;

taskCompletionSource.TrySetCanceled();

});

 

_isLoading = true;

 

var task = LoadContacts();

 

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

_isLoading = false;

 

return await completedTask;

}

async Task<IList<GetContact>> LoadContacts()

{

IList<GetContact> contacts = new List<GetContact>();

var hasPermission = await RequestPermission();

if (hasPermission)

{

var uri = ContactsContract.Contacts.ContentUri;

var ctx = Application.Context;

await Task.Run(() =>

{

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.NameofContact))

{

OnContactLoad?.Invoke(this, new IGetContactServices(contact));

contacts.Add(contact);

}

 

if (stopLoad)

break;

}

}

});

 

}

return contacts;

 

}

 

GetContact 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(), $”{Thumbnail}-{Guid.NewGuid()}”);

using (var str = new FileStream(path, FileMode.Create))

{

stream.CopyTo(str);

str.Close();

}

 

stream.Close();

}

 

 

}

catch (Exception ex)

{

System.Diagnostics.Debug.WriteLine(ex);

}

 

}

var contact = new GetContact

{

NameofContact = GetString(cursor, ContactsContract.Contacts.InterfaceConsts.DisplayName),

Emailsofperson = emails,

ImageofContact = path,

Numberofperson = 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));

}

 

}

}

 

Step: 6

 

Now, add one more class in the Android project to handle permissions.

 

PermissionUtil.cs

 

using Android.Content.PM;

 

namespace FetchContact.Droid

{

public static class PermissionUtil

{

public static bool VerifyPermissions(Permission[] grant)

{

if (grant.Length < 1)

return false;

 

foreach (Permission result in grant)

{

if (result != Permission.Granted)

{

return false;

}

}

return true;

}

}

}

 

Step: 7

In MainActivity class, we can add the RequestPermission method and also use contact service.

Step: 8

Now, create a view model in the main project and use contact services.

MainViewModel.cs

using FetchContact.Model;

using FetchContact.Service;

using System;

using System.Collections;

using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Linq;

using System.Threading.Tasks;

 

namespace FetchContact.ViewModel

{

public class MainViewModel : INotifyPropertyChanged

{

IContacts _contactService;

 

public event PropertyChangedEventHandler PropertyChanged;

 

public string Title => “Contacts”;

 

public string SearchContactText { get; set; }

public ObservableCollection<GetContact> Contacts { get; set; }

public ObservableCollection<GetContact> ListContacts

{

get

{

return string.IsNullOrEmpty(SearchContactText) ? Contacts : new ObservableCollection<GetContact>(Contacts?.ToList()?.Where(s => !string.IsNullOrEmpty(s.NameofContact) && s.NameofContact.ToLower().Contains(SearchContactText.ToLower())));

}

}

public MainViewModel(IContacts contactService)

{

_contactService = contactService;

Contacts = new ObservableCollection<GetContact>();

Xamarin.Forms.BindingBase.EnableCollectionSynchronization(Contacts, null, ObservableCollection);

_contactService.OnContactLoad += OnContactLoaded;

LoadContacts();

}

void ObservableCollection(IEnumerable collection, object context, Action accessMethod, bool writeAccess)

{

lock (collection)

{

accessMethod?.Invoke();

}

}

 

private void OnContactLoaded(object sender, IGetContactServices e)

{

Contacts.Add(e.getContact);

}

async Task LoadContacts()

{

try

{

await _contactService.RetrieveContacts();

}

catch (TaskCanceledException)

{

Console.WriteLine(“Something Went Wrong.”);

}

}

 

}

}

 

Step: 9

Add contact service in App.Xaml.cs file.

App.Xaml.cs

public partial class App : Application

{

IContacts _contactsService;

public App(IContacts contactsService)

{

_contactsService = contactsService;

InitializeComponent();

 

MainPage = new NavigationPage(new MainPage(_contactsService));

}

 

Step: 10

 

All steps are done now, we can create a page for display contacts. Using listview we can bind all contacts and also use a search bar for searching.

 

MainPage.Xaml

 

<?xml version=”1.0″ encoding=”utf-8″ ?>

<ContentPage xmlns=”http://xamarin.com/schemas/2014/forms”

xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml”>

<ContentPage.Content>

<StackLayout>

<SearchBar x:Name=”SearchContact”

HeightRequest=”40″

Text=”{Binding SearchContactText}” />

<ListView   ItemsSource=”{Binding ListContacts}”

HasUnevenRows=”True”>

<ListView.ItemTemplate>

<DataTemplate>

<ViewCell>

<StackLayout Padding=”10″

Orientation=”Horizontal”>

<Image  Source=”{Binding ImageofContact}”

VerticalOptions=”Center”

x:Name=”image”

Aspect=”AspectFit”

HeightRequest=”60″/>

<StackLayout VerticalOptions=”Center”>

<Label Text=”{Binding NameofContact}”

FontAttributes=”Bold”/>

<Label Text=”{Binding Numberofperson[0]}”/>

<Label Text=”{Binding Emailsofperson[0]}”/>

</StackLayout>

</StackLayout>

</ViewCell>

</DataTemplate>

</ListView.ItemTemplate>

</ListView>

</StackLayout>

</ContentPage.Content>

</ContentPage>

 

MainPage.Xaml.cs

 

using FetchContact.Service;

using FetchContact.ViewModel;

using System.ComponentModel;

using Xamarin.Forms;

 

namespace FetchContact

{

[DesignTimeVisible(false)]

public partial class MainPage : ContentPage

{

public MainPage(IContacts services)

{

BindingContext = new MainViewModel(services);

InitializeComponent();

}

}

}

Output:

Conclusion

In this blog, we have discussed how to fetch contacts on Android. For fetching the contacts, you need to permit access to your phone contact and also need to install Plugin.CurrentActivity and Acr.UserDialogs packages in the Android project.

Author Bio: Vinod Satapara – Technical Director, iFour Technolab Pvt. Ltd.

Technocrat and entrepreneur with years of experience building large scale enterprise web, cloud and mobile applications using latest technologies like ASP.NET, CORE, .NET MVC, Angular and Blockchain. Keen interest in addressing business problems using latest technologies and have been associated with Mobile Application Development Companies.

ImageLinkedIn: https://www.linkedin.com/in/vinodsatapara/

 

Was this article helpful?
YesNo
Shankar

Shankar is a tech blogger who occasionally enjoys penning historical fiction. With over a thousand articles written on tech, business, finance, marketing, mobile, social media, cloud storage, software, and general topics, he has been creating material for the past eight years.

Recent Posts

From Standard Definition to Ultra-HD: The Streaming Journey So Far

It only seems like yesterday when people were ordering VHS, CDs, and DVDs from their… Read More

4 hours ago

SEO vs. Paid Ads: Which is better for Our Businesses?

Large, small, and mid-sized businesses are continuously looking for better ways to improve their online… Read More

23 hours ago

Strategies for Incorporating Wellness Programs in Rehab Marketing

Are you ready to transform lives? As a rehab marketer, you hold the power to… Read More

1 day ago

Key Applications of VLSI in Today’s Tech Industry

VLSI (Very Large Scale Integration) technology is at the core of modern electronics, enabling the… Read More

4 days ago

How to Align Your Financial Goals with the Best SIP Plan for Long-Term Returns?

Planning for the future can be challenging, but with the right strategy, you can steadily… Read More

6 days ago

The Role of Time Management in Overcoming Remote Work Distractions

Work distractions are estimated to cost U.S. businesses around $650 billion annually. Unlike in an… Read More

1 week ago