Xamarin Contacts Picker

Xamarin.Forms provide a powerful tool “Dependency Service” to access all native/platform specific services like choose contacts, open camera, choose pictures from gallery and GPS etc. In this blog, we will learn how to create a contacts picker in Xamarin.Forms application.

Step 1. Open visual studio and create a new Xamarin.Forms Shared project “ChooseContactDemo”. I am going to implement it for Android and iOS only so remove additional windows projects.

Step 2. Create a new content page “MainPage” and paste below code.

public class ChooseContactPage : ContentPage  
 {  
   public ChooseContactPage()  
   {  
     var entryContact = new Entry { Placeholder = "Contact Number" };  
     var btnChooseContact = new Button  
     {  
       Text = "Choose Contact",  
     };  
     btnChooseContact.Clicked += async (s, e) =>  
     {  
       entryContact.Text = await DependencyService.Get<IMobile>().ChooseContact();  
     };  
     Content = new StackLayout  
     {  
       VerticalOptions = LayoutOptions.CenterAndExpand,  
       Children = { entryContact, btnChooseContact }  
     };  
   }
Step 3. Create an interface IChooseContact.
public interface IMobile  
   {  
      Task<string> ChooseContact();  
    }
Step 4. Now we will implement the native part. In this example, I have created a helper class in android to handle start and finish of activities. It also executes callback method after finishing an activity. Open Android project and create a class IntentHelper.
class IntentHelper { public static bool IsMobileIntent(int code)  
     {  
       return code == (int)RequestCodes.ContactPicker;  
     }  
     static Action<string> _callback;  
     struct RequestCodes { public const int ContactPicker = 101;  
     }  
     static Activity CurrentActivity  
     {  
       get { return (Xamarin.Forms.Forms.Context as MainActivity);  
       }  
     }  
     public static void ActivityResult(int requestCode, Intent data)  
     {  
       if (_callback == null)  
         return;  
       if (requestCode == RequestCodes.ContactPicker)  
       {  
         _callback(GetContactFromUri(data.Data));  
       }  
     }  
     static string GetContactFromUri(Android.Net.Uri contactUri)  
     {  
       try { string[] projection = { ContactsContract.CommonDataKinds.Phone.Number };  
         var cursor = Xamarin.Forms.Forms.Context.ContentResolver.Query(contactUri, projection, null, null, null);  
         if (cursor.MoveToFirst())  
         {  
           return cursor.GetString(cursor.GetColumnIndex(projection[0]));  
         }  
         return null;  
       }  
       catch { return null;  
       }  
     }  
     public static void OpenContactPicker(Action<string> callback)  
     {  
       _callback = callback;  
       Intent intent = new Intent(Intent.ActionPick);  
       intent.SetType(ContactsContract.CommonDataKinds.Phone.ContentType);  
       CurrentActivity.StartActivityForResult(intent, RequestCodes.ContactPicker);  
     }  
   }
 Step 5. Open Android project and add a class “ChooseContactDroid” and paste below content.
public class Mobile : IChooseContact  
   {  
     public Task<string> ChooseContact()  
     {  
       var task = new TaskCompletionSource<string>();  
       try {  
         IntentHelper.OpenContactPicker((path) =>  
         {  
           task.SetResult(path);  
         });  
       } catch (Exception ex)  
       {  
         task.SetException(ex);  
       }  
       return task.Task;  
     }  
   }
Step 6. Now add below lines to your MainActivity class
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)  
     {  
       base.OnActivityResult(requestCode, resultCode, data);  
       if (ChooseContact.IntentHelper.IsMobileIntent(requestCode))  
       {  
         ChooseContact.IntentHelper.ActivityResult(requestCode, data);  
       }  
     }
That's it for Android, now we will start implementation with iOS.
Step 7. Create a class ContactPicker in iOS project
public static class ContactPicker { static Action<AddressBook.ABPerson> _callback;  
     static ABPeoplePickerNavigationController picker;  
     static void Init()  
     {  
       if (picker != null)  
         return;  
       picker = new ABPeoplePickerNavigationController();  
       picker.Cancelled += (s, e) =>  
       {  
         picker.DismissModalViewController(true);  
         _callback(null);  
       };  
       picker.SelectPerson2 += (s, e) =>  
       {  
         picker.DismissModalViewController(true);  
         _callback(e.Person);  
       };  
     }  
     public static void Select(UIViewController parent, Action<AddressBook.ABPerson> callback)  
     {  
       _callback = callback;  
       Init();  
       parent.PresentModalViewController(picker, true);  
     }  
   }
Step 8. Now implement the interface.
[assembly: Xamarin.Forms.Dependency(typeof(ChooseContact))]namespace ChooseContact.iOS { public class ChooseContact : IChooseContact  
   {  
     public Task<string> ChooseContact()  
     {  
       var task = new TaskCompletionSource<string>();  
       try {  
         ContactPicker.Select(GetController(), (obj) =>  
         { if (obj == null)  
           {  
             task.SetResult(null);  
           }  
           else { var values = obj.GetPhones().GetValues();  
             task.SetResult(values.Length > 0 ? values[0] : null);  
           }  
         });  
       }  
       catch (Exception ex)  
       {  
         task.SetException(ex);  
       }  
       return task.Task;  
     }  
     private UIViewController GetController()  
     {  
       return UIApplication.SharedApplication.KeyWindow.RootViewController;  
     }  
   }
That’s it, now you can build and run the application.
Thanks.